diff options
author | Matthew Rahtz <matthew.rahtz@gmail.com> | 2022-03-26 16:55:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-26 16:55:35 (GMT) |
commit | e8e737bcf6d22927caebc30c5d57ac4634063219 (patch) | |
tree | 6c0d4d51e8216f02fa0e6874aa4d78e20dd9397a /Lib/test/test_future.py | |
parent | 26cca8067bf5306e372c0e90036d832c5021fd90 (diff) | |
download | cpython-e8e737bcf6d22927caebc30c5d57ac4634063219.zip cpython-e8e737bcf6d22927caebc30c5d57ac4634063219.tar.gz cpython-e8e737bcf6d22927caebc30c5d57ac4634063219.tar.bz2 |
bpo-43224: Implement PEP 646 grammar changes (GH-31018)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Diffstat (limited to 'Lib/test/test_future.py')
-rw-r--r-- | Lib/test/test_future.py | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index 5a3944e..c3e8420 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -175,7 +175,7 @@ class AnnotationsFutureTestCase(unittest.TestCase): scope = {} exec( "from __future__ import annotations\n" - + code, {}, scope + + code, scope ) return scope @@ -287,10 +287,11 @@ class AnnotationsFutureTestCase(unittest.TestCase): eq("list[str]") eq("dict[str, int]") eq("set[str,]") + eq("tuple[()]") eq("tuple[str, ...]") - eq("tuple[(str, *types)]") + eq("tuple[str, *types]") eq("tuple[str, int, (str, int)]") - eq("tuple[(*int, str, str, (str, int))]") + eq("tuple[*int, str, str, (str, int)]") eq("tuple[str, int, float, dict[str, int]]") eq("slice[0]") eq("slice[0:1]") @@ -305,6 +306,21 @@ class AnnotationsFutureTestCase(unittest.TestCase): eq("slice[1:2, 1]") eq("slice[1:2, 2, 3]") eq("slice[()]") + # Note that `slice[*Ts]`, `slice[*Ts,]`, and `slice[(*Ts,)]` all have + # the same AST, but only `slice[*Ts,]` passes this test, because that's + # what the unparser produces. + eq("slice[*Ts,]") + eq("slice[1, *Ts]") + eq("slice[*Ts, 2]") + eq("slice[1, *Ts, 2]") + eq("slice[*Ts, *Ts]") + eq("slice[1, *Ts, *Ts]") + eq("slice[*Ts, 1, *Ts]") + eq("slice[*Ts, *Ts, 1]") + eq("slice[1, *Ts, *Ts, 2]") + eq("slice[1:2, *Ts]") + eq("slice[*Ts, 1:2]") + eq("slice[1:2, *Ts, 3:4]") eq("slice[a, b:c, d:e:f]") eq("slice[(x for x in a)]") eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') @@ -403,6 +419,25 @@ class AnnotationsFutureTestCase(unittest.TestCase): def bar(arg: (yield)): pass """)) + def test_get_type_hints_on_func_with_variadic_arg(self): + # `typing.get_type_hints` might break on a function with a variadic + # annotation (e.g. `f(*args: *Ts)`) if `from __future__ import + # annotations`, because it could try to evaluate `*Ts` as an expression, + # which on its own isn't value syntax. + namespace = self._exec_future(dedent("""\ + class StarredC: pass + class C: + def __iter__(self): + yield StarredC() + c = C() + def f(*args: *c): pass + import typing + hints = typing.get_type_hints(f) + """)) + + hints = namespace.pop('hints') + self.assertIsInstance(hints['args'], namespace['StarredC']) + if __name__ == "__main__": unittest.main() |