mirror of
https://github.com/python/cpython.git
synced 2025-08-05 17:39:02 +00:00
gh-118761: Optimise import time for `string
` (#132037)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
53908bd790
commit
ee3657209b
2 changed files with 32 additions and 15 deletions
|
@ -49,11 +49,18 @@ def capwords(s, sep=None):
|
|||
|
||||
|
||||
####################################################################
|
||||
import re as _re
|
||||
from collections import ChainMap as _ChainMap
|
||||
|
||||
_sentinel_dict = {}
|
||||
|
||||
|
||||
class _TemplatePattern:
|
||||
# This descriptor is overwritten in ``Template._compile_pattern()``.
|
||||
def __get__(self, instance, cls=None):
|
||||
if cls is None:
|
||||
return self
|
||||
return cls._compile_pattern()
|
||||
_TemplatePattern = _TemplatePattern()
|
||||
|
||||
|
||||
class Template:
|
||||
"""A string class for supporting $-substitutions."""
|
||||
|
||||
|
@ -64,14 +71,21 @@ class Template:
|
|||
# See https://bugs.python.org/issue31672
|
||||
idpattern = r'(?a:[_a-z][_a-z0-9]*)'
|
||||
braceidpattern = None
|
||||
flags = _re.IGNORECASE
|
||||
flags = None # default: re.IGNORECASE
|
||||
|
||||
pattern = _TemplatePattern # use a descriptor to compile the pattern
|
||||
|
||||
def __init_subclass__(cls):
|
||||
super().__init_subclass__()
|
||||
if 'pattern' in cls.__dict__:
|
||||
pattern = cls.pattern
|
||||
else:
|
||||
delim = _re.escape(cls.delimiter)
|
||||
cls._compile_pattern()
|
||||
|
||||
@classmethod
|
||||
def _compile_pattern(cls):
|
||||
import re # deferred import, for performance
|
||||
|
||||
pattern = cls.__dict__.get('pattern', _TemplatePattern)
|
||||
if pattern is _TemplatePattern:
|
||||
delim = re.escape(cls.delimiter)
|
||||
id = cls.idpattern
|
||||
bid = cls.braceidpattern or cls.idpattern
|
||||
pattern = fr"""
|
||||
|
@ -82,7 +96,10 @@ class Template:
|
|||
(?P<invalid>) # Other ill-formed delimiter exprs
|
||||
)
|
||||
"""
|
||||
cls.pattern = _re.compile(pattern, cls.flags | _re.VERBOSE)
|
||||
if cls.flags is None:
|
||||
cls.flags = re.IGNORECASE
|
||||
pat = cls.pattern = re.compile(pattern, cls.flags | re.VERBOSE)
|
||||
return pat
|
||||
|
||||
def __init__(self, template):
|
||||
self.template = template
|
||||
|
@ -105,7 +122,8 @@ class Template:
|
|||
if mapping is _sentinel_dict:
|
||||
mapping = kws
|
||||
elif kws:
|
||||
mapping = _ChainMap(kws, mapping)
|
||||
from collections import ChainMap
|
||||
mapping = ChainMap(kws, mapping)
|
||||
# Helper function for .sub()
|
||||
def convert(mo):
|
||||
# Check the most common path first.
|
||||
|
@ -124,7 +142,8 @@ class Template:
|
|||
if mapping is _sentinel_dict:
|
||||
mapping = kws
|
||||
elif kws:
|
||||
mapping = _ChainMap(kws, mapping)
|
||||
from collections import ChainMap
|
||||
mapping = ChainMap(kws, mapping)
|
||||
# Helper function for .sub()
|
||||
def convert(mo):
|
||||
named = mo.group('named') or mo.group('braced')
|
||||
|
@ -170,10 +189,6 @@ class Template:
|
|||
self.pattern)
|
||||
return ids
|
||||
|
||||
# Initialize Template.pattern. __init_subclass__() is automatically called
|
||||
# only for subclasses, not for the Template class itself.
|
||||
Template.__init_subclass__()
|
||||
|
||||
|
||||
########################################################################
|
||||
# the Formatter class
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue