mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +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 = {}
 | 
					_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:
 | 
					class Template:
 | 
				
			||||||
    """A string class for supporting $-substitutions."""
 | 
					    """A string class for supporting $-substitutions."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,14 +71,21 @@ class Template:
 | 
				
			||||||
    # See https://bugs.python.org/issue31672
 | 
					    # See https://bugs.python.org/issue31672
 | 
				
			||||||
    idpattern = r'(?a:[_a-z][_a-z0-9]*)'
 | 
					    idpattern = r'(?a:[_a-z][_a-z0-9]*)'
 | 
				
			||||||
    braceidpattern = None
 | 
					    braceidpattern = None
 | 
				
			||||||
    flags = _re.IGNORECASE
 | 
					    flags = None  # default: re.IGNORECASE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pattern = _TemplatePattern  # use a descriptor to compile the pattern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init_subclass__(cls):
 | 
					    def __init_subclass__(cls):
 | 
				
			||||||
        super().__init_subclass__()
 | 
					        super().__init_subclass__()
 | 
				
			||||||
        if 'pattern' in cls.__dict__:
 | 
					        cls._compile_pattern()
 | 
				
			||||||
            pattern = cls.pattern
 | 
					
 | 
				
			||||||
        else:
 | 
					    @classmethod
 | 
				
			||||||
            delim = _re.escape(cls.delimiter)
 | 
					    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
 | 
					            id = cls.idpattern
 | 
				
			||||||
            bid = cls.braceidpattern or cls.idpattern
 | 
					            bid = cls.braceidpattern or cls.idpattern
 | 
				
			||||||
            pattern = fr"""
 | 
					            pattern = fr"""
 | 
				
			||||||
| 
						 | 
					@ -82,7 +96,10 @@ def __init_subclass__(cls):
 | 
				
			||||||
              (?P<invalid>)             # Other ill-formed delimiter exprs
 | 
					              (?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):
 | 
					    def __init__(self, template):
 | 
				
			||||||
        self.template = template
 | 
					        self.template = template
 | 
				
			||||||
| 
						 | 
					@ -105,7 +122,8 @@ def substitute(self, mapping=_sentinel_dict, /, **kws):
 | 
				
			||||||
        if mapping is _sentinel_dict:
 | 
					        if mapping is _sentinel_dict:
 | 
				
			||||||
            mapping = kws
 | 
					            mapping = kws
 | 
				
			||||||
        elif kws:
 | 
					        elif kws:
 | 
				
			||||||
            mapping = _ChainMap(kws, mapping)
 | 
					            from collections import ChainMap
 | 
				
			||||||
 | 
					            mapping = ChainMap(kws, mapping)
 | 
				
			||||||
        # Helper function for .sub()
 | 
					        # Helper function for .sub()
 | 
				
			||||||
        def convert(mo):
 | 
					        def convert(mo):
 | 
				
			||||||
            # Check the most common path first.
 | 
					            # Check the most common path first.
 | 
				
			||||||
| 
						 | 
					@ -124,7 +142,8 @@ def safe_substitute(self, mapping=_sentinel_dict, /, **kws):
 | 
				
			||||||
        if mapping is _sentinel_dict:
 | 
					        if mapping is _sentinel_dict:
 | 
				
			||||||
            mapping = kws
 | 
					            mapping = kws
 | 
				
			||||||
        elif kws:
 | 
					        elif kws:
 | 
				
			||||||
            mapping = _ChainMap(kws, mapping)
 | 
					            from collections import ChainMap
 | 
				
			||||||
 | 
					            mapping = ChainMap(kws, mapping)
 | 
				
			||||||
        # Helper function for .sub()
 | 
					        # Helper function for .sub()
 | 
				
			||||||
        def convert(mo):
 | 
					        def convert(mo):
 | 
				
			||||||
            named = mo.group('named') or mo.group('braced')
 | 
					            named = mo.group('named') or mo.group('braced')
 | 
				
			||||||
| 
						 | 
					@ -170,10 +189,6 @@ def get_identifiers(self):
 | 
				
			||||||
                    self.pattern)
 | 
					                    self.pattern)
 | 
				
			||||||
        return ids
 | 
					        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
 | 
					# the Formatter class
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Improve import times by up to 27x for the :mod:`string` module.
 | 
				
			||||||
 | 
					Patch by Adam Turner.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue