Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ee36572

Browse filesBrowse files
gh-118761: Optimise import time for string (#132037)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 53908bd commit ee36572
Copy full SHA for ee36572

File tree

2 files changed

+32
-15
lines changed
Filter options

2 files changed

+32
-15
lines changed

‎Lib/string.py

Copy file name to clipboardExpand all lines: Lib/string.py
+30-15Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,18 @@ def capwords(s, sep=None):
4949

5050

5151
####################################################################
52-
import re as _re
53-
from collections import ChainMap as _ChainMap
54-
5552
_sentinel_dict = {}
5653

54+
55+
class _TemplatePattern:
56+
# This descriptor is overwritten in ``Template._compile_pattern()``.
57+
def __get__(self, instance, cls=None):
58+
if cls is None:
59+
return self
60+
return cls._compile_pattern()
61+
_TemplatePattern = _TemplatePattern()
62+
63+
5764
class Template:
5865
"""A string class for supporting $-substitutions."""
5966

@@ -64,14 +71,21 @@ class Template:
6471
# See https://bugs.python.org/issue31672
6572
idpattern = r'(?a:[_a-z][_a-z0-9]*)'
6673
braceidpattern = None
67-
flags = _re.IGNORECASE
74+
flags = None # default: re.IGNORECASE
75+
76+
pattern = _TemplatePattern # use a descriptor to compile the pattern
6877

6978
def __init_subclass__(cls):
7079
super().__init_subclass__()
71-
if 'pattern' in cls.__dict__:
72-
pattern = cls.pattern
73-
else:
74-
delim = _re.escape(cls.delimiter)
80+
cls._compile_pattern()
81+
82+
@classmethod
83+
def _compile_pattern(cls):
84+
import re # deferred import, for performance
85+
86+
pattern = cls.__dict__.get('pattern', _TemplatePattern)
87+
if pattern is _TemplatePattern:
88+
delim = re.escape(cls.delimiter)
7589
id = cls.idpattern
7690
bid = cls.braceidpattern or cls.idpattern
7791
pattern = fr"""
@@ -82,7 +96,10 @@ def __init_subclass__(cls):
8296
(?P<invalid>) # Other ill-formed delimiter exprs
8397
)
8498
"""
85-
cls.pattern = _re.compile(pattern, cls.flags | _re.VERBOSE)
99+
if cls.flags is None:
100+
cls.flags = re.IGNORECASE
101+
pat = cls.pattern = re.compile(pattern, cls.flags | re.VERBOSE)
102+
return pat
86103

87104
def __init__(self, template):
88105
self.template = template
@@ -105,7 +122,8 @@ def substitute(self, mapping=_sentinel_dict, /, **kws):
105122
if mapping is _sentinel_dict:
106123
mapping = kws
107124
elif kws:
108-
mapping = _ChainMap(kws, mapping)
125+
from collections import ChainMap
126+
mapping = ChainMap(kws, mapping)
109127
# Helper function for .sub()
110128
def convert(mo):
111129
# Check the most common path first.
@@ -124,7 +142,8 @@ def safe_substitute(self, mapping=_sentinel_dict, /, **kws):
124142
if mapping is _sentinel_dict:
125143
mapping = kws
126144
elif kws:
127-
mapping = _ChainMap(kws, mapping)
145+
from collections import ChainMap
146+
mapping = ChainMap(kws, mapping)
128147
# Helper function for .sub()
129148
def convert(mo):
130149
named = mo.group('named') or mo.group('braced')
@@ -170,10 +189,6 @@ def get_identifiers(self):
170189
self.pattern)
171190
return ids
172191

173-
# Initialize Template.pattern. __init_subclass__() is automatically called
174-
# only for subclasses, not for the Template class itself.
175-
Template.__init_subclass__()
176-
177192

178193
########################################################################
179194
# the Formatter class
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve import times by up to 27x for the :mod:`string` module.
2+
Patch by Adam Turner.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.