summaryrefslogtreecommitdiff
path: root/pygments/formatters
diff options
context:
space:
mode:
authorDirk Mueller <dmueller@suse.com>2023-01-31 16:16:11 +0100
committerGitHub <noreply@github.com>2023-01-31 16:16:11 +0100
commitc467d61ccf23d24cba47957e6e0dde790b94136f (patch)
tree6c38b233051ae955aba698128d520f2f38346a6e /pygments/formatters
parent6e870b449dae9ac69899b0bed06962aaf2b8adf1 (diff)
downloadpygments-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__.py17
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)