43c4c89aacf0c771de138e1f58decf9fb592f62f
[SubU] /
1 """
2     pygments.formatters
3     ~~~~~~~~~~~~~~~~~~~
4
5     Pygments formatters.
6
7     :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
8     :license: BSD, see LICENSE for details.
9 """
10
11 import re
12 import sys
13 import types
14 from fnmatch import fnmatch
15 from os.path import basename
16
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
20
21 __all__ = ['get_formatter_by_name', 'get_formatter_for_filename',
22            'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS)
23
24 _formatter_cache = {}  # classes by name
25
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
32
33
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():
42         yield formatter
43
44
45 def find_formatter_class(alias):
46     """Lookup a formatter by alias.
47
48     Returns None if not found.
49     """
50     for module_name, name, aliases, _, _ in FORMATTERS.values():
51         if alias in aliases:
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:
57             return cls
58
59
60 def get_formatter_by_name(_alias, **options):
61     """Lookup and instantiate a formatter by alias.
62
63     Raises ClassNotFound if not found.
64     """
65     cls = find_formatter_class(_alias)
66     if cls is None:
67         raise ClassNotFound("no formatter found for name %r" % _alias)
68     return cls(**options)
69
70
71 def load_formatter_from_file(filename, formattername="CustomFormatter",
72                              **options):
73     """Load a formatter from a file.
74
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.
79
80     Users should be very careful with the input, because this method
81     is equivalent to running eval on the input file.
82
83     Raises ClassNotFound if there are any problems importing the Formatter.
84
85     .. versionadded:: 2.2
86     """
87     try:
88         # This empty dict will contain the namespace for the exec'd file
89         custom_namespace = {}
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:
102         raise
103     except Exception as err:
104         raise ClassNotFound('error when loading custom formatter: %s' % err)
105
106
107 def get_formatter_for_filename(fn, **options):
108     """Lookup and instantiate a formatter by filename pattern.
109
110     Raises ClassNotFound if not found.
111     """
112     fn = basename(fn)
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)
124
125
126 class _automodule(types.ModuleType):
127     """Automatically import formatters."""
128
129     def __getattr__(self, name):
130         info = FORMATTERS.get(name)
131         if info:
132             _load_formatters(info[0])
133             cls = _formatter_cache[info[1]]
134             setattr(self, name, cls)
135             return cls
136         raise AttributeError(name)
137
138
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