summaryrefslogtreecommitdiffstats
path: root/Lib/string.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-10-21 06:36:21 (GMT)
committerGitHub <noreply@github.com>2019-10-21 06:36:21 (GMT)
commit919f0bc8c904d3aa13eedb2dd1fe9c6b0555a591 (patch)
treec603fb5b8ceb2b8fc5d01fd25500b2e9e08fd891 /Lib/string.py
parent06cd5b6acd98205adae1a3ea4223e88f38ad55ab (diff)
downloadcpython-919f0bc8c904d3aa13eedb2dd1fe9c6b0555a591.zip
cpython-919f0bc8c904d3aa13eedb2dd1fe9c6b0555a591.tar.gz
cpython-919f0bc8c904d3aa13eedb2dd1fe9c6b0555a591.tar.bz2
bpo-38208: Simplify string.Template by using __init_subclass__(). (GH-16256)
Diffstat (limited to 'Lib/string.py')
-rw-r--r--Lib/string.py46
1 files changed, 22 insertions, 24 deletions
diff --git a/Lib/string.py b/Lib/string.py
index b423ff5..489777b 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -54,30 +54,7 @@ from collections import ChainMap as _ChainMap
_sentinel_dict = {}
-class _TemplateMetaclass(type):
- pattern = r"""
- %(delim)s(?:
- (?P<escaped>%(delim)s) | # Escape sequence of two delimiters
- (?P<named>%(id)s) | # delimiter and a Python identifier
- {(?P<braced>%(bid)s)} | # delimiter and a braced identifier
- (?P<invalid>) # Other ill-formed delimiter exprs
- )
- """
-
- def __init__(cls, name, bases, dct):
- super(_TemplateMetaclass, cls).__init__(name, bases, dct)
- if 'pattern' in dct:
- pattern = cls.pattern
- else:
- pattern = _TemplateMetaclass.pattern % {
- 'delim' : _re.escape(cls.delimiter),
- 'id' : cls.idpattern,
- 'bid' : cls.braceidpattern or cls.idpattern,
- }
- cls.pattern = _re.compile(pattern, cls.flags | _re.VERBOSE)
-
-
-class Template(metaclass=_TemplateMetaclass):
+class Template:
"""A string class for supporting $-substitutions."""
delimiter = '$'
@@ -89,6 +66,24 @@ class Template(metaclass=_TemplateMetaclass):
braceidpattern = None
flags = _re.IGNORECASE
+ def __init_subclass__(cls):
+ super().__init_subclass__()
+ if 'pattern' in cls.__dict__:
+ pattern = cls.pattern
+ else:
+ delim = _re.escape(cls.delimiter)
+ id = cls.idpattern
+ bid = cls.braceidpattern or cls.idpattern
+ pattern = fr"""
+ {delim}(?:
+ (?P<escaped>{delim}) | # Escape sequence of two delimiters
+ (?P<named>{id}) | # delimiter and a Python identifier
+ {{(?P<braced>{bid})}} | # delimiter and a braced identifier
+ (?P<invalid>) # Other ill-formed delimiter exprs
+ )
+ """
+ cls.pattern = _re.compile(pattern, cls.flags | _re.VERBOSE)
+
def __init__(self, template):
self.template = template
@@ -146,6 +141,9 @@ class Template(metaclass=_TemplateMetaclass):
self.pattern)
return self.pattern.sub(convert, self.template)
+# Initialize Template.pattern. __init_subclass__() is automatically called
+# only for subclasses, not for the Template class itself.
+Template.__init_subclass__()
########################################################################