@@ -191,10 +191,12 @@ def _exec_future(self, code):
191191 scope = {}
192192 exec (
193193 "from __future__ import annotations\n "
194- + code , {}, scope
194+ + code , scope
195195 )
196196 return scope
197197
198+ # TODO: RUSTPYTHON
199+ @unittest .expectedFailure
198200 def test_annotations (self ):
199201 eq = self .assertAnnotationEqual
200202 eq ('...' )
@@ -303,10 +305,11 @@ def test_annotations(self):
303305 eq ("list[str]" )
304306 eq ("dict[str, int]" )
305307 eq ("set[str,]" )
308+ eq ("tuple[()]" )
306309 eq ("tuple[str, ...]" )
307- eq ("tuple[( str, *types) ]" )
310+ eq ("tuple[str, *types]" )
308311 eq ("tuple[str, int, (str, int)]" )
309- eq ("tuple[( *int, str, str, (str, int) )]" )
312+ eq ("tuple[*int, str, str, (str, int)]" )
310313 eq ("tuple[str, int, float, dict[str, int]]" )
311314 eq ("slice[0]" )
312315 eq ("slice[0:1]" )
@@ -321,6 +324,21 @@ def test_annotations(self):
321324 eq ("slice[1:2, 1]" )
322325 eq ("slice[1:2, 2, 3]" )
323326 eq ("slice[()]" )
327+ # Note that `slice[*Ts]`, `slice[*Ts,]`, and `slice[(*Ts,)]` all have
328+ # the same AST, but only `slice[*Ts,]` passes this test, because that's
329+ # what the unparser produces.
330+ eq ("slice[*Ts,]" )
331+ eq ("slice[1, *Ts]" )
332+ eq ("slice[*Ts, 2]" )
333+ eq ("slice[1, *Ts, 2]" )
334+ eq ("slice[*Ts, *Ts]" )
335+ eq ("slice[1, *Ts, *Ts]" )
336+ eq ("slice[*Ts, 1, *Ts]" )
337+ eq ("slice[*Ts, *Ts, 1]" )
338+ eq ("slice[1, *Ts, *Ts, 2]" )
339+ eq ("slice[1:2, *Ts]" )
340+ eq ("slice[*Ts, 1:2]" )
341+ eq ("slice[1:2, *Ts, 3:4]" )
324342 eq ("slice[a, b:c, d:e:f]" )
325343 eq ("slice[(x for x in a)]" )
326344 eq ('str or None if sys.version_info[0] > (3,) else str or bytes or None' )
@@ -423,6 +441,27 @@ def foo():
423441 def bar(arg: (yield)): pass
424442 """ ))
425443
444+ # TODO: RUSTPYTHON
445+ @unittest .expectedFailure
446+ def test_get_type_hints_on_func_with_variadic_arg (self ):
447+ # `typing.get_type_hints` might break on a function with a variadic
448+ # annotation (e.g. `f(*args: *Ts)`) if `from __future__ import
449+ # annotations`, because it could try to evaluate `*Ts` as an expression,
450+ # which on its own isn't value syntax.
451+ namespace = self ._exec_future (dedent ("""\
452+ class StarredC: pass
453+ class C:
454+ def __iter__(self):
455+ yield StarredC()
456+ c = C()
457+ def f(*args: *c): pass
458+ import typing
459+ hints = typing.get_type_hints(f)
460+ """ ))
461+
462+ hints = namespace .pop ('hints' )
463+ self .assertIsInstance (hints ['args' ], namespace ['StarredC' ])
464+
426465
427466if __name__ == "__main__" :
428467 unittest .main ()
0 commit comments