From 044a1048ca93d466965afc027b91a5a9eb9ce23c Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Tue, 6 Oct 2020 23:03:02 +0300 Subject: 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). --- Lib/dataclasses.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'Lib/dataclasses.py') diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 65091021f37..adfb9b7240b 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) -- cgit v1.2.3