__init__.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # -*- coding: utf-8 -*-
  2. """
  3. pygments.formatters
  4. ~~~~~~~~~~~~~~~~~~~
  5. Pygments formatters.
  6. :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS.
  7. :license: BSD, see LICENSE for details.
  8. """
  9. import re
  10. import sys
  11. import types
  12. import fnmatch
  13. from os.path import basename
  14. from pygments.formatters._mapping import FORMATTERS
  15. from pygments.plugin import find_plugin_formatters
  16. from pygments.util import ClassNotFound, itervalues
  17. __all__ = ['get_formatter_by_name', 'get_formatter_for_filename',
  18. 'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS)
  19. _formatter_cache = {} # classes by name
  20. _pattern_cache = {}
  21. def _fn_matches(fn, glob):
  22. """Return whether the supplied file name fn matches pattern filename."""
  23. if glob not in _pattern_cache:
  24. pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob))
  25. return pattern.match(fn)
  26. return _pattern_cache[glob].match(fn)
  27. def _load_formatters(module_name):
  28. """Load a formatter (and all others in the module too)."""
  29. mod = __import__(module_name, None, None, ['__all__'])
  30. for formatter_name in mod.__all__:
  31. cls = getattr(mod, formatter_name)
  32. _formatter_cache[cls.name] = cls
  33. def get_all_formatters():
  34. """Return a generator for all formatter classes."""
  35. # NB: this returns formatter classes, not info like get_all_lexers().
  36. for info in itervalues(FORMATTERS):
  37. if info[1] not in _formatter_cache:
  38. _load_formatters(info[0])
  39. yield _formatter_cache[info[1]]
  40. for _, formatter in find_plugin_formatters():
  41. yield formatter
  42. def find_formatter_class(alias):
  43. """Lookup a formatter by alias.
  44. Returns None if not found.
  45. """
  46. for module_name, name, aliases, _, _ in itervalues(FORMATTERS):
  47. if alias in aliases:
  48. if name not in _formatter_cache:
  49. _load_formatters(module_name)
  50. return _formatter_cache[name]
  51. for _, cls in find_plugin_formatters():
  52. if alias in cls.aliases:
  53. return cls
  54. def get_formatter_by_name(_alias, **options):
  55. """Lookup and instantiate a formatter by alias.
  56. Raises ClassNotFound if not found.
  57. """
  58. cls = find_formatter_class(_alias)
  59. if cls is None:
  60. raise ClassNotFound("no formatter found for name %r" % _alias)
  61. return cls(**options)
  62. def load_formatter_from_file(filename, formattername="CustomFormatter",
  63. **options):
  64. """Load a formatter from a file.
  65. This method expects a file located relative to the current working
  66. directory, which contains a class named CustomFormatter. By default,
  67. it expects the Formatter to be named CustomFormatter; you can specify
  68. your own class name as the second argument to this function.
  69. Users should be very careful with the input, because this method
  70. is equivalent to running eval on the input file.
  71. Raises ClassNotFound if there are any problems importing the Formatter.
  72. .. versionadded:: 2.2
  73. """
  74. try:
  75. # This empty dict will contain the namespace for the exec'd file
  76. custom_namespace = {}
  77. with open(filename, 'rb') as f:
  78. exec(f.read(), custom_namespace)
  79. # Retrieve the class `formattername` from that namespace
  80. if formattername not in custom_namespace:
  81. raise ClassNotFound('no valid %s class found in %s' %
  82. (formattername, filename))
  83. formatter_class = custom_namespace[formattername]
  84. # And finally instantiate it with the options
  85. return formatter_class(**options)
  86. except IOError as err:
  87. raise ClassNotFound('cannot read %s: %s' % (filename, err))
  88. except ClassNotFound:
  89. raise
  90. except Exception as err:
  91. raise ClassNotFound('error when loading custom formatter: %s' % err)
  92. def get_formatter_for_filename(fn, **options):
  93. """Lookup and instantiate a formatter by filename pattern.
  94. Raises ClassNotFound if not found.
  95. """
  96. fn = basename(fn)
  97. for modname, name, _, filenames, _ in itervalues(FORMATTERS):
  98. for filename in filenames:
  99. if _fn_matches(fn, filename):
  100. if name not in _formatter_cache:
  101. _load_formatters(modname)
  102. return _formatter_cache[name](**options)
  103. for cls in find_plugin_formatters():
  104. for filename in cls.filenames:
  105. if _fn_matches(fn, filename):
  106. return cls(**options)
  107. raise ClassNotFound("no formatter found for file name %r" % fn)
  108. class _automodule(types.ModuleType):
  109. """Automatically import formatters."""
  110. def __getattr__(self, name):
  111. info = FORMATTERS.get(name)
  112. if info:
  113. _load_formatters(info[0])
  114. cls = _formatter_cache[info[1]]
  115. setattr(self, name, cls)
  116. return cls
  117. raise AttributeError(name)
  118. oldmod = sys.modules[__name__]
  119. newmod = _automodule(__name__)
  120. newmod.__dict__.update(oldmod.__dict__)
  121. sys.modules[__name__] = newmod
  122. del newmod.newmod, newmod.oldmod, newmod.sys, newmod.types