summaryrefslogtreecommitdiffstats
path: root/Lib/dataclasses.py
diff options
context:
space:
mode:
authorBatuhan Taskaya <batuhanosmantaskaya@gmail.com>2020-10-06 20:03:02 (GMT)
committerGitHub <noreply@github.com>2020-10-06 20:03:02 (GMT)
commit044a1048ca93d466965afc027b91a5a9eb9ce23c (patch)
tree94ef2bca072693d83448edef4009dc840c58a3e2 /Lib/dataclasses.py
parentbef7d299eb911086ea5a7ccf7a9da337e38a8491 (diff)
downloadcpython-044a1048ca93d466965afc027b91a5a9eb9ce23c.zip
cpython-044a1048ca93d466965afc027b91a5a9eb9ce23c.tar.gz
cpython-044a1048ca93d466965afc027b91a5a9eb9ce23c.tar.bz2
bpo-38605: Make 'from __future__ import annotations' the default (GH-20434)
The hard part was making all the tests pass; there are some subtle issues here, because apparently the future import wasn't tested very thoroughly in previous Python versions. For example, `inspect.signature()` returned type objects normally (except for forward references), but strings with the future import. We changed it to try and return type objects by calling `typing.get_type_hints()`, but fall back on returning strings if that function fails (which it may do if there are future references in the annotations that require passing in a specific namespace to resolve).
Diffstat (limited to 'Lib/dataclasses.py')
-rw-r--r--Lib/dataclasses.py13
1 files changed, 10 insertions, 3 deletions
diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py
index 6509102..adfb9b7 100644
--- a/Lib/dataclasses.py
+++ b/Lib/dataclasses.py
@@ -399,8 +399,10 @@ def _create_fn(name, args, body, *, globals=None, locals=None,
ns = {}
exec(txt, globals, ns)
- return ns['__create_fn__'](**locals)
-
+ func = ns['__create_fn__'](**locals)
+ for arg, annotation in func.__annotations__.copy().items():
+ func.__annotations__[arg] = locals[annotation]
+ return func
def _field_assign(frozen, name, value, self_name):
# If we're a frozen class, then assign to our fields in __init__
@@ -651,6 +653,11 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate):
# a eval() penalty for every single field of every dataclass
# that's defined. It was judged not worth it.
+ # Strip away the extra quotes as a result of double-stringifying when the
+ # 'annotations' feature became default.
+ if annotation.startswith(("'", '"')) and annotation.endswith(("'", '"')):
+ annotation = annotation[1:-1]
+
match = _MODULE_IDENTIFIER_RE.match(annotation)
if match:
ns = None
@@ -991,7 +998,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
if not getattr(cls, '__doc__'):
# Create a class doc-string.
cls.__doc__ = (cls.__name__ +
- str(inspect.signature(cls)).replace(' -> None', ''))
+ str(inspect.signature(cls)).replace(' -> NoneType', ''))
abc.update_abstractmethods(cls)