|
1 | | -import re |
2 | 1 | import sys |
3 | | -import copy |
4 | 2 | import types |
5 | 3 | import inspect |
6 | 4 | import keyword |
7 | 5 | import itertools |
8 | 6 | import annotationlib |
9 | 7 | import abc |
10 | 8 | from reprlib import recursive_repr |
| 9 | +lazy import copy |
| 10 | +lazy import re |
11 | 11 |
|
12 | 12 |
|
13 | 13 | __all__ = ['dataclass', |
@@ -217,9 +217,8 @@ def __repr__(self): |
217 | 217 | _POST_INIT_NAME = '__post_init__' |
218 | 218 |
|
219 | 219 | # String regex that string annotations for ClassVar or InitVar must match. |
220 | | -# Allows "identifier.identifier[" or "identifier[". |
221 | | -# https://bugs.python.org/issue33453 for details. |
222 | | -_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)') |
| 220 | +# This regular expression is compiled on demand so that 're' module can be imported lazily |
| 221 | +_MODULE_IDENTIFIER_RE = None |
223 | 222 |
|
224 | 223 | # Atomic immutable types which don't require any recursive handling and for which deepcopy |
225 | 224 | # returns the same object. We can provide a fast-path for these types in asdict and astuple. |
@@ -804,10 +803,17 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): |
804 | 803 | # a eval() penalty for every single field of every dataclass |
805 | 804 | # that's defined. It was judged not worth it. |
806 | 805 |
|
807 | | - match = _MODULE_IDENTIFIER_RE.match(annotation) |
| 806 | + # String regex that string annotations for ClassVar or InitVar must match. |
| 807 | + # Allows "identifier.identifier[" or "identifier[". |
| 808 | + # https://github.com/python/cpython/issues/77634 for details. |
| 809 | + global _MODULE_IDENTIFIER_RE |
| 810 | + if _MODULE_IDENTIFIER_RE is None: |
| 811 | + _MODULE_IDENTIFIER_RE = re.compile(r'(?:\s*(\w+)\s*\.)?\s*(\w+)') |
| 812 | + |
| 813 | + match = _MODULE_IDENTIFIER_RE.prefixmatch(annotation) |
808 | 814 | if match: |
809 | 815 | ns = None |
810 | | - module_name = match.group(1) |
| 816 | + module_name = match[1] |
811 | 817 | if not module_name: |
812 | 818 | # No module name, assume the class's module did |
813 | 819 | # "from dataclasses import InitVar". |
@@ -817,7 +823,7 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): |
817 | 823 | module = sys.modules.get(cls.__module__) |
818 | 824 | if module and module.__dict__.get(module_name) is a_module: |
819 | 825 | ns = sys.modules.get(a_type.__module__).__dict__ |
820 | | - if ns and is_type_predicate(ns.get(match.group(2)), a_module): |
| 826 | + if ns and is_type_predicate(ns.get(match[2]), a_module): |
821 | 827 | return True |
822 | 828 | return False |
823 | 829 |
|
|