diff options
author | Georg Brandl <georg@python.org> | 2014-09-20 09:25:38 +0200 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2014-09-20 09:25:38 +0200 |
commit | f44f4394a82ca8d0e08c58850b4c08c67a981d61 (patch) | |
tree | e6c20c873b8e80551bfc39a6765483105baa292a /pygments/formatters/__init__.py | |
parent | b46db39223c23d199dad06d479bd2ac165dbed19 (diff) | |
download | pygments-f44f4394a82ca8d0e08c58850b4c08c67a981d61.tar.gz |
Refactored formatter mapping to work like the lexer mapping.
Thanks to Ilia Choly for the initial pull request.
Diffstat (limited to 'pygments/formatters/__init__.py')
-rw-r--r-- | pygments/formatters/__init__.py | 128 |
1 files changed, 88 insertions, 40 deletions
diff --git a/pygments/formatters/__init__.py b/pygments/formatters/__init__.py index f0c5dc41..45ceaff6 100644 --- a/pygments/formatters/__init__.py +++ b/pygments/formatters/__init__.py @@ -8,63 +8,111 @@ :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ -import os.path -import fnmatch + import re +import sys +import types +import fnmatch +from os.path import basename from pygments.formatters._mapping import FORMATTERS from pygments.plugin import find_plugin_formatters -from pygments.util import ClassNotFound - -ns = globals() -for fcls in FORMATTERS: - ns[fcls.__name__] = fcls -del fcls +from pygments.util import ClassNotFound, itervalues __all__ = ['get_formatter_by_name', 'get_formatter_for_filename', - 'get_all_formatters'] + [cls.__name__ for cls in FORMATTERS] + 'get_all_formatters'] + list(FORMATTERS) + +_formatter_cache = {} # classes by name +_pattern_cache = {} + + +def _fn_matches(fn, glob): + """Return whether the supplied file name fn matches pattern filename.""" + if glob not in _pattern_cache: + pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob)) + return pattern.match(fn) + return _pattern_cache[glob].match(fn) + + +def _load_formatters(module_name): + """Load a formatter (and all others in the module too).""" + mod = __import__(module_name, None, None, ['__all__']) + for formatter_name in mod.__all__: + cls = getattr(mod, formatter_name) + _formatter_cache[cls.name] = cls + +def get_all_formatters(): + """Return a generator for all formatter classes.""" + # NB: this returns formatter classes, not info like get_all_lexers(). + for info in itervalues(FORMATTERS): + if info[1] not in _formatter_cache: + _load_formatters(info[0]) + yield _formatter_cache[info[1]] + for _, formatter in find_plugin_formatters(): + yield formatter -_formatter_alias_cache = {} -_formatter_filename_cache = [] -def _init_formatter_cache(): - if _formatter_alias_cache: - return - for cls in get_all_formatters(): - for alias in cls.aliases: - _formatter_alias_cache[alias] = cls - for fn in cls.filenames: - _formatter_filename_cache.append(( - re.compile(fnmatch.translate(fn)), cls)) +def find_formatter_class(alias): + """Lookup a formatter by alias. + Returns None if not found. + """ + for module_name, name, aliases, _, _ in itervalues(FORMATTERS): + if alias in aliases: + if name not in _formatter_cache: + _load_formatters(module_name) + return _formatter_cache[name] + for _, cls in find_plugin_formatters(): + if alias in cls.aliases: + return cls -def find_formatter_class(name): - _init_formatter_cache() - cls = _formatter_alias_cache.get(name, None) - return cls +def get_formatter_by_name(_alias, **options): + """Lookup and instantiate a formatter by alias. -def get_formatter_by_name(name, **options): - _init_formatter_cache() - cls = _formatter_alias_cache.get(name, None) - if not cls: - raise ClassNotFound("No formatter found for name %r" % name) + Raises ClassNotFound if not found. + """ + cls = find_formatter_class(_alias) + if cls is None: + raise ClassNotFound("No formatter found for name %r" % _alias) return cls(**options) def get_formatter_for_filename(fn, **options): - _init_formatter_cache() - fn = os.path.basename(fn) - for pattern, cls in _formatter_filename_cache: - if pattern.match(fn): - return cls(**options) + """Lookup and instantiate a formatter by filename pattern. + + Raises ClassNotFound if not found. + """ + fn = basename(fn) + for modname, name, _, filenames, _ in itervalues(FORMATTERS): + for filename in filenames: + if _fn_matches(fn, filename): + if name not in _formatter_cache: + _load_formatters(modname) + return _formatter_cache[name](**options) + for cls in find_plugin_formatters(): + for filename in cls.filenames: + if _fn_matches(fn, filename): + return cls(**options) raise ClassNotFound("No formatter found for file name %r" % fn) -def get_all_formatters(): - """Return a generator for all formatters.""" - for formatter in FORMATTERS: - yield formatter - for _, formatter in find_plugin_formatters(): - yield formatter +class _automodule(types.ModuleType): + """Automatically import formatters.""" + + def __getattr__(self, name): + info = FORMATTERS.get(name) + if info: + _load_formatters(info[0]) + cls = _formatter_cache[info[1]] + setattr(self, name, cls) + return cls + raise AttributeError(name) + + +oldmod = sys.modules[__name__] +newmod = _automodule(__name__) +newmod.__dict__.update(oldmod.__dict__) +sys.modules[__name__] = newmod +del newmod.newmod, newmod.oldmod, newmod.sys, newmod.types |