summaryrefslogtreecommitdiff
path: root/pygments/formatters/__init__.py
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2014-09-20 09:25:38 +0200
committerGeorg Brandl <georg@python.org>2014-09-20 09:25:38 +0200
commitf44f4394a82ca8d0e08c58850b4c08c67a981d61 (patch)
treee6c20c873b8e80551bfc39a6765483105baa292a /pygments/formatters/__init__.py
parentb46db39223c23d199dad06d479bd2ac165dbed19 (diff)
downloadpygments-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__.py128
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