16 from os.path import basename |
16 from os.path import basename |
17 |
17 |
18 from pygments.lexers._mapping import LEXERS |
18 from pygments.lexers._mapping import LEXERS |
19 from pygments.modeline import get_filetype_from_buffer |
19 from pygments.modeline import get_filetype_from_buffer |
20 from pygments.plugin import find_plugin_lexers |
20 from pygments.plugin import find_plugin_lexers |
21 from pygments.util import ClassNotFound, itervalues, guess_decode |
21 from pygments.util import ClassNotFound, guess_decode |
22 |
22 |
|
23 COMPAT = { |
|
24 'Python3Lexer': 'PythonLexer', |
|
25 'Python3TracebackLexer': 'PythonTracebackLexer', |
|
26 } |
23 |
27 |
24 __all__ = ['get_lexer_by_name', 'get_lexer_for_filename', 'find_lexer_class', |
28 __all__ = ['get_lexer_by_name', 'get_lexer_for_filename', 'find_lexer_class', |
25 'guess_lexer', 'load_lexer_from_file'] + list(LEXERS) |
29 'guess_lexer', 'load_lexer_from_file'] + list(LEXERS) + list(COMPAT) |
26 |
30 |
27 _lexer_cache = {} |
31 _lexer_cache = {} |
28 _pattern_cache = {} |
32 _pattern_cache = {} |
29 |
33 |
30 |
34 |
46 |
50 |
47 def get_all_lexers(): |
51 def get_all_lexers(): |
48 """Return a generator of tuples in the form ``(name, aliases, |
52 """Return a generator of tuples in the form ``(name, aliases, |
49 filenames, mimetypes)`` of all know lexers. |
53 filenames, mimetypes)`` of all know lexers. |
50 """ |
54 """ |
51 for item in itervalues(LEXERS): |
55 for item in LEXERS.values(): |
52 yield item[1:] |
56 yield item[1:] |
53 for lexer in find_plugin_lexers(): |
57 for lexer in find_plugin_lexers(): |
54 yield lexer.name, lexer.aliases, lexer.filenames, lexer.mimetypes |
58 yield lexer.name, lexer.aliases, lexer.filenames, lexer.mimetypes |
55 |
59 |
56 |
60 |
60 Return None if not found. |
64 Return None if not found. |
61 """ |
65 """ |
62 if name in _lexer_cache: |
66 if name in _lexer_cache: |
63 return _lexer_cache[name] |
67 return _lexer_cache[name] |
64 # lookup builtin lexers |
68 # lookup builtin lexers |
65 for module_name, lname, aliases, _, _ in itervalues(LEXERS): |
69 for module_name, lname, aliases, _, _ in LEXERS.values(): |
66 if name == lname: |
70 if name == lname: |
67 _load_lexers(module_name) |
71 _load_lexers(module_name) |
68 return _lexer_cache[name] |
72 return _lexer_cache[name] |
69 # continue with lexers from setuptools entrypoints |
73 # continue with lexers from setuptools entrypoints |
70 for cls in find_plugin_lexers(): |
74 for cls in find_plugin_lexers(): |
80 .. versionadded:: 2.2 |
84 .. versionadded:: 2.2 |
81 """ |
85 """ |
82 if not _alias: |
86 if not _alias: |
83 raise ClassNotFound('no lexer for alias %r found' % _alias) |
87 raise ClassNotFound('no lexer for alias %r found' % _alias) |
84 # lookup builtin lexers |
88 # lookup builtin lexers |
85 for module_name, name, aliases, _, _ in itervalues(LEXERS): |
89 for module_name, name, aliases, _, _ in LEXERS.values(): |
86 if _alias.lower() in aliases: |
90 if _alias.lower() in aliases: |
87 if name not in _lexer_cache: |
91 if name not in _lexer_cache: |
88 _load_lexers(module_name) |
92 _load_lexers(module_name) |
89 return _lexer_cache[name] |
93 return _lexer_cache[name] |
90 # continue with lexers from setuptools entrypoints |
94 # continue with lexers from setuptools entrypoints |
101 """ |
105 """ |
102 if not _alias: |
106 if not _alias: |
103 raise ClassNotFound('no lexer for alias %r found' % _alias) |
107 raise ClassNotFound('no lexer for alias %r found' % _alias) |
104 |
108 |
105 # lookup builtin lexers |
109 # lookup builtin lexers |
106 for module_name, name, aliases, _, _ in itervalues(LEXERS): |
110 for module_name, name, aliases, _, _ in LEXERS.values(): |
107 if _alias.lower() in aliases: |
111 if _alias.lower() in aliases: |
108 if name not in _lexer_cache: |
112 if name not in _lexer_cache: |
109 _load_lexers(module_name) |
113 _load_lexers(module_name) |
110 return _lexer_cache[name](**options) |
114 return _lexer_cache[name](**options) |
111 # continue with lexers from setuptools entrypoints |
115 # continue with lexers from setuptools entrypoints |
131 .. versionadded:: 2.2 |
135 .. versionadded:: 2.2 |
132 """ |
136 """ |
133 try: |
137 try: |
134 # This empty dict will contain the namespace for the exec'd file |
138 # This empty dict will contain the namespace for the exec'd file |
135 custom_namespace = {} |
139 custom_namespace = {} |
136 exec(open(filename, 'rb').read(), custom_namespace) |
140 with open(filename, 'rb') as f: |
|
141 exec(f.read(), custom_namespace) |
137 # Retrieve the class `lexername` from that namespace |
142 # Retrieve the class `lexername` from that namespace |
138 if lexername not in custom_namespace: |
143 if lexername not in custom_namespace: |
139 raise ClassNotFound('no valid %s class found in %s' % |
144 raise ClassNotFound('no valid %s class found in %s' % |
140 (lexername, filename)) |
145 (lexername, filename)) |
141 lexer_class = custom_namespace[lexername] |
146 lexer_class = custom_namespace[lexername] |
142 # And finally instantiate it with the options |
147 # And finally instantiate it with the options |
143 return lexer_class(**options) |
148 return lexer_class(**options) |
144 except IOError as err: |
149 except IOError as err: |
145 raise ClassNotFound('cannot read %s' % filename) |
150 raise ClassNotFound('cannot read %s: %s' % (filename, err)) |
146 except ClassNotFound as err: |
151 except ClassNotFound: |
147 raise |
152 raise |
148 except Exception as err: |
153 except Exception as err: |
149 raise ClassNotFound('error when loading custom lexer: %s' % err) |
154 raise ClassNotFound('error when loading custom lexer: %s' % err) |
150 |
155 |
151 |
156 |
157 |
162 |
158 Returns None if not found. |
163 Returns None if not found. |
159 """ |
164 """ |
160 matches = [] |
165 matches = [] |
161 fn = basename(_fn) |
166 fn = basename(_fn) |
162 for modname, name, _, filenames, _ in itervalues(LEXERS): |
167 for modname, name, _, filenames, _ in LEXERS.values(): |
163 for filename in filenames: |
168 for filename in filenames: |
164 if _fn_matches(fn, filename): |
169 if _fn_matches(fn, filename): |
165 if name not in _lexer_cache: |
170 if name not in _lexer_cache: |
166 _load_lexers(modname) |
171 _load_lexers(modname) |
167 matches.append((_lexer_cache[name], filename)) |
172 matches.append((_lexer_cache[name], filename)) |
168 for cls in find_plugin_lexers(): |
173 for cls in find_plugin_lexers(): |
169 for filename in cls.filenames: |
174 for filename in cls.filenames: |
170 if _fn_matches(fn, filename): |
175 if _fn_matches(fn, filename): |
171 matches.append((cls, filename)) |
176 matches.append((cls, filename)) |
172 |
177 |
173 if sys.version_info > (3,) and isinstance(code, bytes): |
178 if isinstance(code, bytes): |
174 # decode it, since all analyse_text functions expect unicode |
179 # decode it, since all analyse_text functions expect unicode |
175 code = guess_decode(code) |
180 code = guess_decode(code) |
176 |
181 |
177 def get_rating(info): |
182 def get_rating(info): |
178 cls, filename = info |
183 cls, filename = info |
209 def get_lexer_for_mimetype(_mime, **options): |
214 def get_lexer_for_mimetype(_mime, **options): |
210 """Get a lexer for a mimetype. |
215 """Get a lexer for a mimetype. |
211 |
216 |
212 Raises ClassNotFound if not found. |
217 Raises ClassNotFound if not found. |
213 """ |
218 """ |
214 for modname, name, _, _, mimetypes in itervalues(LEXERS): |
219 for modname, name, _, _, mimetypes in LEXERS.values(): |
215 if _mime in mimetypes: |
220 if _mime in mimetypes: |
216 if name not in _lexer_cache: |
221 if name not in _lexer_cache: |
217 _load_lexers(modname) |
222 _load_lexers(modname) |
218 return _lexer_cache[name](**options) |
223 return _lexer_cache[name](**options) |
219 for cls in find_plugin_lexers(): |
224 for cls in find_plugin_lexers(): |
286 |
291 |
287 |
292 |
288 def guess_lexer(_text, **options): |
293 def guess_lexer(_text, **options): |
289 """Guess a lexer by strong distinctions in the text (eg, shebang).""" |
294 """Guess a lexer by strong distinctions in the text (eg, shebang).""" |
290 |
295 |
|
296 if not isinstance(_text, str): |
|
297 inencoding = options.get('inencoding', options.get('encoding')) |
|
298 if inencoding: |
|
299 _text = _text.decode(inencoding or 'utf8') |
|
300 else: |
|
301 _text, _ = guess_decode(_text) |
|
302 |
291 # try to get a vim modeline first |
303 # try to get a vim modeline first |
292 ft = get_filetype_from_buffer(_text) |
304 ft = get_filetype_from_buffer(_text) |
293 |
305 |
294 if ft is not None: |
306 if ft is not None: |
295 try: |
307 try: |
317 if info: |
329 if info: |
318 _load_lexers(info[0]) |
330 _load_lexers(info[0]) |
319 cls = _lexer_cache[info[1]] |
331 cls = _lexer_cache[info[1]] |
320 setattr(self, name, cls) |
332 setattr(self, name, cls) |
321 return cls |
333 return cls |
|
334 if name in COMPAT: |
|
335 return getattr(self, COMPAT[name]) |
322 raise AttributeError(name) |
336 raise AttributeError(name) |
323 |
337 |
324 |
338 |
325 oldmod = sys.modules[__name__] |
339 oldmod = sys.modules[__name__] |
326 newmod = _automodule(__name__) |
340 newmod = _automodule(__name__) |