""" Test the typing library, with docstrings and annotations """ import typing from typing import Sequence, MutableSequence, List, Iterable, Iterator, \ AbstractSet, Tuple, Mapping, Dict, Union, Optional class B: pass def we_can_has_sequence(p: Sequence[int], q: Sequence[B], r: Sequence[int], s: Sequence["int"], t: MutableSequence[dict], u: List[float]): #? ["count"] p.c #? int() p[1] #? ["count"] q.c #? B() q[1] #? ["count"] r.c #? int() r[1] #? ["count"] s.c #? int() s[1] #? [] s.a #? ["append"] t.a #? dict() t[1] #? ["append"] u.a #? float() list() u[1.0] #? float() u[1] def iterators(ps: Iterable[int], qs: Iterator[str], rs: Sequence["ForwardReference"], ts: AbstractSet["float"]): for p in ps: #? int() p #? next(ps) a, b = ps #? int() a ##? int() --- TODO fix support for tuple assignment # https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854 # test below is just to make sure that in case it gets fixed by accident # these tests will be fixed as well the way they should be #? b for q in qs: #? str() q #? str() next(qs) for r in rs: #? ForwardReference() r #? next(rs) for t in ts: #? float() t def sets(p: AbstractSet[int], q: typing.MutableSet[float]): #? [] p.a #? ["add"] q.a def tuple(p: Tuple[int], q: Tuple[int, str, float], r: Tuple[B, ...]): #? int() p[0] #? ['index'] p.index #? int() q[0] #? str() q[1] #? float() q[2] #? B() r[0] #? B() r[1] #? B() r[2] #? B() r[10000] i, s, f = q #? int() i #? str() s #? float() f class Key: pass class Value: pass def mapping( p: Mapping[Key, Value], q: typing.MutableMapping[Key, Value], d: Dict[Key, Value], dd: typing.DefaultDict[Key, Value], r: typing.KeysView[Key], s: typing.ValuesView[Value], t: typing.ItemsView[Key, Value]): #? [] p.setd #? ["setdefault"] q.setd #? ["setdefault"] d.setd #? ["setdefault"] dd.setd #? Value() p[1] for key in p: #? Key() key for key in p.keys(): #? Key() key for value in p.values(): #? Value() value for item in p.items(): #? Key() item[0] #? Value() item[1] (key, value) = item #? Key() key #? Value() value for key, value in p.items(): #? Key() key #? Value() value for key, value in q.items(): #? Key() key #? Value() value for key, value in d.items(): #? Key() key #? Value() value for key, value in dd.items(): #? Key() key #? Value() value for key in r: #? Key() key for value in s: #? Value() value for key, value in t: #? Key() key #? Value() value def union( p: Union[int], q: Union[int, int], r: Union[int, str, "int"], s: Union[int, typing.Union[str, "typing.Union['float', 'dict']"]], t: Union[int, None]): #? int() p #? int() q #? int() str() r #? int() str() float() dict() s #? int() None t def optional(p: Optional[int]): """ Optional does not do anything special. However it should be recognised as being of that type. Jedi doesn't do anything with the extra into that it can be None as well """ #? int() None p class ForwardReference: pass class TestDict(typing.Dict[str, int]): def setdud(self): pass def testdict(x: TestDict): #? ["setdud", "setdefault"] x.setd for key in x.keys(): #? str() key for value in x.values(): #? int() value x = TestDict() #? ["setdud", "setdefault"] x.setd for key in x.keys(): #? str() key for value in x.values(): #? int() value WrappingType = typing.NewType('WrappingType', str) # Chosen arbitrarily y = WrappingType(0) # Per https://github.com/davidhalter/jedi/issues/1015#issuecomment-355795929 #? str() y def testnewtype(y: WrappingType): #? str() y #? ["upper"] y.u WrappingType2 = typing.NewType() def testnewtype2(y: WrappingType2): #? y #? [] y. # The type of a NewType is equivalent to the type of its underlying type. MyInt = typing.NewType('MyInt', int) x = type(MyInt) #? type.mro x.mro PlainInt = int y = type(PlainInt) #? type.mro y.mro class TestDefaultDict(typing.DefaultDict[str, int]): def setdud(self): pass def testdict(x: TestDefaultDict): #? ["setdud", "setdefault"] x.setd for key in x.keys(): #? str() key for value in x.values(): #? int() value x = TestDefaultDict() #? ["setdud", "setdefault"] x.setd for key in x.keys(): #? str() key for value in x.values(): #? int() value """ docstrings have some auto-import, annotations can use all of Python's import logic """ import typing as t def union2(x: t.Union[int, str]): #? int() str() x from typing import Union def union3(x: Union[int, str]): #? int() str() x from typing import Union as U def union4(x: U[int, str]): #? int() str() x #? typing.Optional typing.Optional[0] # ------------------------- # Type Vars # ------------------------- TYPE_VARX = typing.TypeVar('TYPE_VARX') TYPE_VAR_CONSTRAINTSX = typing.TypeVar('TYPE_VAR_CONSTRAINTSX', str, int) #? ['__class__'] TYPE_VARX.__clas #! ["TYPE_VARX = typing.TypeVar('TYPE_VARX')"] TYPE_VARX class WithTypeVar(typing.Generic[TYPE_VARX]): def lala(self) -> TYPE_VARX: ... def maaan(p: WithTypeVar[int]): #? int() p.lala() def in_out1(x: TYPE_VARX) -> TYPE_VARX: ... #? int() in_out1(1) #? str() in_out1("") #? str() in_out1(str()) #? in_out1() def type_in_out1(x: typing.Type[TYPE_VARX]) -> TYPE_VARX: ... #? int() type_in_out1(int) #? str() type_in_out1(str) #? float() type_in_out1(float) #? type_in_out1() def in_out2(x: TYPE_VAR_CONSTRAINTSX) -> TYPE_VAR_CONSTRAINTSX: ... #? int() in_out2(1) #? str() in_out2("") #? str() in_out2(str()) #? str() int() in_out2() # TODO this should actually be str() int(), because of the constraints. #? float() in_out2(1.0) def type_in_out2(x: typing.Type[TYPE_VAR_CONSTRAINTSX]) -> TYPE_VAR_CONSTRAINTSX: ... #? int() type_in_out2(int) #? str() type_in_out2(str) #? str() int() type_in_out2() # TODO this should actually be str() int(), because of the constraints. #? float() type_in_out2(float) def ma(a: typing.Callable[[str], TYPE_VARX]) -> typing.Callable[[str], TYPE_VARX]: #? typing.Callable() return a def mf(s: str) -> int: return int(s) #? int() ma(mf)('2') def xxx(x: typing.Iterable[TYPE_VARX]) -> typing.Tuple[str, TYPE_VARX]: ... #? str() xxx([0])[0] #? int() xxx([0])[1] #? xxx([0])[2] def call_pls() -> typing.Callable[[TYPE_VARX], TYPE_VARX]: ... #? int() call_pls()(1) def call2_pls() -> typing.Callable[[str, typing.Callable[[int], TYPE_VARX]], TYPE_VARX]: ... #? float() call2_pls('')(1, lambda x: 3.0) def call3_pls() -> typing.Callable[[typing.Callable[[int], TYPE_VARX]], typing.List[TYPE_VARX]]: ... def the_callable() -> float: ... #? float() call3_pls()(the_callable)[0] def call4_pls(fn: typing.Callable[..., TYPE_VARX]) -> typing.Callable[..., TYPE_VARX]: return "" #? int() call4_pls(lambda x: 1)() # ------------------------- # TYPE_CHECKING # ------------------------- if typing.TYPE_CHECKING: with_type_checking = 1 else: without_type_checking = 1.0 #? int() with_type_checking #? without_type_checking def foo(a: typing.List, b: typing.Dict, c: typing.MutableMapping) -> typing.Type[int]: #? ['append'] a.appen #? list() a #? a[0] #? ['setdefault'] b.setd #? ['setdefault'] c.setd #? typing.MutableMapping() c #? c['asdf'] #? int foo() # ------------------------- # cast # ------------------------- def cast_tests(): x = 3.0 y = typing.cast(int, x) #? int() y return typing.cast(str, x) #? str() cast_tests() # ------------------------- # dynamic # ------------------------- def dynamic_annotation(x: int): #? int() return x #? int() dynamic_annotation('') # ------------------------- # TypeDict # ------------------------- # python >= 3.8 class Foo(typing.TypedDict): foo: str bar: typing.List[float] an_int: int #! ['foo: str'] foo #? str() foo #? int() an_int def typed_dict_test_foo(arg: Foo): a_string = arg['foo'] a_list_of_floats = arg['bar'] an_int = arg['an_int'] #? str() a_string #? list() a_list_of_floats #? float() a_list_of_floats[0] #? int() an_int #? ['isupper'] a_string.isuppe #? ['pop'] a_list_of_floats.po #? ['as_integer_ratio'] an_int.as_integer_rati #! ['class Foo'] d: Foo #? str() d['foo'] #? float() d['bar'][0] #? d['baz'] #? d.foo #? d.bar #! [] d.foo #? [] Foo.set #? ['setdefault'] d.setdefaul #? [] Foo.setdefaul #? 5 ["'foo"] d['fo'] #? 5 ['"bar"'] d["bar"] class Bar(Foo): another_variable: int #? int() another_variable #? an_int def typed_dict_test_foo(arg: Bar): #? str() arg['foo'] #? list() arg['bar'] #? float() arg['bar'][0] #? int() arg['an_int'] #? int() arg['another_variable']