diff options
author | Dirk Mueller <dmueller@suse.com> | 2023-01-31 16:16:11 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-31 16:16:11 +0100 |
commit | c467d61ccf23d24cba47957e6e0dde790b94136f (patch) | |
tree | 6c38b233051ae955aba698128d520f2f38346a6e /pygments/formatters | |
parent | 6e870b449dae9ac69899b0bed06962aaf2b8adf1 (diff) | |
download | pygments-git-c467d61ccf23d24cba47957e6e0dde790b94136f.tar.gz |
Revert "Remove filename pattern caches (#2153)" (#2328)
This introduced a performance regession. While it is true that
fnmatch already uses functools.lru_cache, that cache is limited to 256
on python 3.10 and older and we have over 1000 matching patterns, which
means the cache is evicted entirely on every iteration.
This reverts commit 951c894ab23537be90fbf3973d0345591e682371.
Diffstat (limited to 'pygments/formatters')
-rw-r--r-- | pygments/formatters/__init__.py | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/pygments/formatters/__init__.py b/pygments/formatters/__init__.py index 58de5fe3..887015c8 100644 --- a/pygments/formatters/__init__.py +++ b/pygments/formatters/__init__.py @@ -8,9 +8,10 @@ :license: BSD, see LICENSE for details. """ +import re import sys import types -from fnmatch import fnmatch +import fnmatch from os.path import basename from pygments.formatters._mapping import FORMATTERS @@ -21,6 +22,16 @@ __all__ = ['get_formatter_by_name', 'get_formatter_for_filename', 'get_all_formatters', 'load_formatter_from_file'] + 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).""" @@ -111,13 +122,13 @@ def get_formatter_for_filename(fn, **options): fn = basename(fn) for modname, name, _, filenames, _ in FORMATTERS.values(): for filename in filenames: - if fnmatch(fn, filename): + 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 fnmatch(fn, filename): + if _fn_matches(fn, filename): return cls(**options) raise ClassNotFound("no formatter found for file name %r" % fn) |