7 :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
14 from fnmatch import fnmatch
15 from os.path import basename
17 from pip._vendor.pygments.formatters._mapping import FORMATTERS
18 from pip._vendor.pygments.plugin import find_plugin_formatters
19 from pip._vendor.pygments.util import ClassNotFound
21 __all__ = ['get_formatter_by_name', 'get_formatter_for_filename',
22 'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS)
24 _formatter_cache = {} # classes by name
26 def _load_formatters(module_name):
27 """Load a formatter (and all others in the module too)."""
28 mod = __import__(module_name, None, None, ['__all__'])
29 for formatter_name in mod.__all__:
30 cls = getattr(mod, formatter_name)
31 _formatter_cache[cls.name] = cls
34 def get_all_formatters():
35 """Return a generator for all formatter classes."""
36 # NB: this returns formatter classes, not info like get_all_lexers().
37 for info in FORMATTERS.values():
38 if info[1] not in _formatter_cache:
39 _load_formatters(info[0])
40 yield _formatter_cache[info[1]]
41 for _, formatter in find_plugin_formatters():
45 def find_formatter_class(alias):
46 """Lookup a formatter by alias.
48 Returns None if not found.
50 for module_name, name, aliases, _, _ in FORMATTERS.values():
52 if name not in _formatter_cache:
53 _load_formatters(module_name)
54 return _formatter_cache[name]
55 for _, cls in find_plugin_formatters():
56 if alias in cls.aliases:
60 def get_formatter_by_name(_alias, **options):
61 """Lookup and instantiate a formatter by alias.
63 Raises ClassNotFound if not found.
65 cls = find_formatter_class(_alias)
67 raise ClassNotFound("no formatter found for name %r" % _alias)
71 def load_formatter_from_file(filename, formattername="CustomFormatter",
73 """Load a formatter from a file.
75 This method expects a file located relative to the current working
76 directory, which contains a class named CustomFormatter. By default,
77 it expects the Formatter to be named CustomFormatter; you can specify
78 your own class name as the second argument to this function.
80 Users should be very careful with the input, because this method
81 is equivalent to running eval on the input file.
83 Raises ClassNotFound if there are any problems importing the Formatter.
88 # This empty dict will contain the namespace for the exec'd file
90 with open(filename, 'rb') as f:
91 exec(f.read(), custom_namespace)
92 # Retrieve the class `formattername` from that namespace
93 if formattername not in custom_namespace:
94 raise ClassNotFound('no valid %s class found in %s' %
95 (formattername, filename))
96 formatter_class = custom_namespace[formattername]
97 # And finally instantiate it with the options
98 return formatter_class(**options)
99 except OSError as err:
100 raise ClassNotFound('cannot read %s: %s' % (filename, err))
101 except ClassNotFound:
103 except Exception as err:
104 raise ClassNotFound('error when loading custom formatter: %s' % err)
107 def get_formatter_for_filename(fn, **options):
108 """Lookup and instantiate a formatter by filename pattern.
110 Raises ClassNotFound if not found.
113 for modname, name, _, filenames, _ in FORMATTERS.values():
114 for filename in filenames:
115 if fnmatch(fn, filename):
116 if name not in _formatter_cache:
117 _load_formatters(modname)
118 return _formatter_cache[name](**options)
119 for cls in find_plugin_formatters():
120 for filename in cls.filenames:
121 if fnmatch(fn, filename):
122 return cls(**options)
123 raise ClassNotFound("no formatter found for file name %r" % fn)
126 class _automodule(types.ModuleType):
127 """Automatically import formatters."""
129 def __getattr__(self, name):
130 info = FORMATTERS.get(name)
132 _load_formatters(info[0])
133 cls = _formatter_cache[info[1]]
134 setattr(self, name, cls)
136 raise AttributeError(name)
139 oldmod = sys.modules[__name__]
140 newmod = _automodule(__name__)
141 newmod.__dict__.update(oldmod.__dict__)
142 sys.modules[__name__] = newmod
143 del newmod.newmod, newmod.oldmod, newmod.sys, newmod.types