@@ -191,10 +191,12 @@ def _exec_future(self, code):
191
191
scope = {}
192
192
exec (
193
193
"from __future__ import annotations\n "
194
- + code , {}, scope
194
+ + code , scope
195
195
)
196
196
return scope
197
197
198
+ # TODO: RUSTPYTHON
199
+ @unittest .expectedFailure
198
200
def test_annotations (self ):
199
201
eq = self .assertAnnotationEqual
200
202
eq ('...' )
@@ -303,10 +305,11 @@ def test_annotations(self):
303
305
eq ("list[str]" )
304
306
eq ("dict[str, int]" )
305
307
eq ("set[str,]" )
308
+ eq ("tuple[()]" )
306
309
eq ("tuple[str, ...]" )
307
- eq ("tuple[( str, *types) ]" )
310
+ eq ("tuple[str, *types]" )
308
311
eq ("tuple[str, int, (str, int)]" )
309
- eq ("tuple[( *int, str, str, (str, int) )]" )
312
+ eq ("tuple[*int, str, str, (str, int)]" )
310
313
eq ("tuple[str, int, float, dict[str, int]]" )
311
314
eq ("slice[0]" )
312
315
eq ("slice[0:1]" )
@@ -321,6 +324,21 @@ def test_annotations(self):
321
324
eq ("slice[1:2, 1]" )
322
325
eq ("slice[1:2, 2, 3]" )
323
326
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]" )
324
342
eq ("slice[a, b:c, d:e:f]" )
325
343
eq ("slice[(x for x in a)]" )
326
344
eq ('str or None if sys.version_info[0] > (3,) else str or bytes or None' )
@@ -423,6 +441,27 @@ def foo():
423
441
def bar(arg: (yield)): pass
424
442
""" ))
425
443
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
+
426
465
427
466
if __name__ == "__main__" :
428
467
unittest .main ()
0 commit comments