Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Adapt code into the latest changes
  • Loading branch information
isidentical committed Oct 1, 2020
commit 1e2c3f826e9196ddc2fc457017cbaa8b1a42552d
3 changes: 1 addition & 2 deletions Doc/reference/compound_stmts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,7 @@ any valid Python expression. The presence of annotations does not change the
semantics of a function. The annotation values are available as values of
a dictionary keyed by the parameters' names in the :attr:`__annotations__`
attribute of the function object. Used annnotations are preserved as strings at
runtime which enables postponed evaluation (annotations may be evaluated in a
different order than they appear in the source code).
runtime which enables postponed evaluation.

.. index:: pair: lambda; expression

Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ def test_annotations(self):
eq('(((a, b)))', '(a, b)')
eq("(x := 10)")
eq("f'{(x := 10):=10}'")
eq("1 + 2")
eq("1 + 2 + 3")

def test_fstring_debug_annotations(self):
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ def check_wrapper(self, wrapper, wrapped,


def _default_update(self):
def f(a:'This is a new annotation'):
def f(a: int):
"""This is a test"""
pass
f.attr = 'This is also a test'
Expand All @@ -635,7 +635,7 @@ def test_default_update(self):
self.assertEqual(wrapper.__name__, 'f')
self.assertEqual(wrapper.__qualname__, f.__qualname__)
self.assertEqual(wrapper.attr, 'This is also a test')
self.assertEqual(wrapper.__annotations__['a'], repr('This is a new annotation'))
self.assertEqual(wrapper.__annotations__['a'], 'int')
self.assertNotIn('b', wrapper.__annotations__)

@unittest.skipIf(sys.flags.optimize >= 2,
Expand Down
4 changes: 0 additions & 4 deletions Lib/test/test_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,10 +636,6 @@ def f(*x: str): pass
self.assertEqual(f.__annotations__, {'x': 'str'})
def f(**x: float): pass
self.assertEqual(f.__annotations__, {'x': 'float'})
def f(x, y: 1+2): pass
self.assertEqual(f.__annotations__, {'y': '1 + 2'})
def f(x, y: 1+2, /): pass
self.assertEqual(f.__annotations__, {'y': '1 + 2'})
def f(a, b: 1, c: 2, d): pass
self.assertEqual(f.__annotations__, {'b': '1', 'c': '2'})
def f(a, b: 1, /, c: 2, d): pass
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,8 @@ def test_or_type_operator_with_forward(self):
ForwardBefore = 'Forward' | T
def forward_after(x: ForwardAfter[int]) -> None: ...
def forward_before(x: ForwardBefore[int]) -> None: ...
assert typing.get_args(typing.get_type_hints(forward_after)['x']) == (int, Forward)
assert typing.get_args(typing.get_type_hints(forward_before)['x']) == (int, Forward)
assert typing.get_args(typing.get_type_hints(forward_after, localns=locals())['x']) == (int, Forward)
assert typing.get_args(typing.get_type_hints(forward_before, localns=locals())['x']) == (int, Forward)

def test_or_type_operator_with_Protocol(self):
class Proto(typing.Protocol):
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2849,7 +2849,7 @@ def test_get_type_hints_classes(self):
self.assertEqual(gth(HasForeignBaseClass),
{'some_xrepr': XRepr, 'other_a': mod_generics_cache.A,
'some_b': mod_generics_cache.B})
self.assertEqual(gth(XRepr.__new__),
self.assertEqual(gth(XRepr),
{'x': int, 'y': int})
self.assertEqual(gth(mod_generics_cache.B),
{'my_inner_a1': mod_generics_cache.B.A,
Expand Down
20 changes: 9 additions & 11 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"""

from abc import abstractmethod, ABCMeta
import ast
import collections
import collections.abc
import contextlib
Expand Down Expand Up @@ -469,11 +470,13 @@ class ForwardRef(_Final, _root=True):
def __init__(self, arg, is_argument=True):
if not isinstance(arg, str):
raise TypeError(f"Forward reference must be a string -- got {arg!r}")
# since annotations feature is now default, stringified annotations
# should be escaped from quotes, or this will result with double
# forward refs.
if arg[0] in "'\"" and arg[-1] in "'\"":

# Double-stringified forward references is a result of activating
# 'annotations' future by default. This way, we eliminate them on
Comment thread
isidentical marked this conversation as resolved.
Outdated
# the runtime.
if arg.startswith(("'", '\"')) and arg.endswith(("'", '"')):
arg = arg[1:-1]

try:
code = compile(arg, '<string>', 'eval')
except SyntaxError:
Expand Down Expand Up @@ -1366,11 +1369,6 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False):
locals, respectively.
"""

def resolve(value, globalns, localns=localns):
# double resolve forward refs
value = _eval_type(value, globalns, localns)
return _eval_type(value, globalns, localns)

if getattr(obj, '__no_type_check__', None):
return {}
# Classes require a special treatment.
Expand All @@ -1387,7 +1385,7 @@ def resolve(value, globalns, localns=localns):
value = type(None)
if isinstance(value, str):
value = ForwardRef(value, is_argument=False)
value = resolve(value, base_globals)
value = _eval_type(value, base_globals, localns)
hints[name] = value
return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()}

Expand Down Expand Up @@ -1419,7 +1417,7 @@ def resolve(value, globalns, localns=localns):
value = type(None)
if isinstance(value, str):
value = ForwardRef(value)
value = resolve(value, globalns)
value = _eval_type(value, globalns, localns)
if name in defaults and defaults[name] is None:
value = Optional[value]
hints[name] = value
Expand Down