typing.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. """
  2. We need to somehow work with the typing objects. Since the typing objects are
  3. pretty bare we need to add all the Jedi customizations to make them work as
  4. values.
  5. This file deals with all the typing.py cases.
  6. """
  7. import itertools
  8. from jedi import debug
  9. from jedi.inference.compiled import builtin_from_name, create_simple_object
  10. from jedi.inference.base_value import ValueSet, NO_VALUES, Value, \
  11. LazyValueWrapper, ValueWrapper
  12. from jedi.inference.lazy_value import LazyKnownValues
  13. from jedi.inference.arguments import repack_with_argument_clinic
  14. from jedi.inference.filters import FilterWrapper
  15. from jedi.inference.names import NameWrapper, ValueName
  16. from jedi.inference.value.klass import ClassMixin
  17. from jedi.inference.gradual.base import BaseTypingValue, \
  18. BaseTypingClassWithGenerics, BaseTypingInstance
  19. from jedi.inference.gradual.type_var import TypeVarClass
  20. from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager
  21. _PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split()
  22. _TYPE_ALIAS_TYPES = {
  23. 'List': 'builtins.list',
  24. 'Dict': 'builtins.dict',
  25. 'Set': 'builtins.set',
  26. 'FrozenSet': 'builtins.frozenset',
  27. 'ChainMap': 'collections.ChainMap',
  28. 'Counter': 'collections.Counter',
  29. 'DefaultDict': 'collections.defaultdict',
  30. 'Deque': 'collections.deque',
  31. }
  32. _PROXY_TYPES = 'Optional Union ClassVar Annotated'.split()
  33. class TypingModuleName(NameWrapper):
  34. def infer(self):
  35. return ValueSet(self._remap())
  36. def _remap(self):
  37. name = self.string_name
  38. inference_state = self.parent_context.inference_state
  39. try:
  40. actual = _TYPE_ALIAS_TYPES[name]
  41. except KeyError:
  42. pass
  43. else:
  44. yield TypeAlias.create_cached(
  45. inference_state, self.parent_context, self.tree_name, actual)
  46. return
  47. if name in _PROXY_CLASS_TYPES:
  48. yield ProxyTypingClassValue.create_cached(
  49. inference_state, self.parent_context, self.tree_name)
  50. elif name in _PROXY_TYPES:
  51. yield ProxyTypingValue.create_cached(
  52. inference_state, self.parent_context, self.tree_name)
  53. elif name == 'runtime':
  54. # We don't want anything here, not sure what this function is
  55. # supposed to do, since it just appears in the stubs and shouldn't
  56. # have any effects there (because it's never executed).
  57. return
  58. elif name == 'TypeVar':
  59. cls, = self._wrapped_name.infer()
  60. yield TypeVarClass.create_cached(inference_state, cls)
  61. elif name == 'Any':
  62. yield AnyClass.create_cached(
  63. inference_state, self.parent_context, self.tree_name)
  64. elif name == 'TYPE_CHECKING':
  65. # This is needed for e.g. imports that are only available for type
  66. # checking or are in cycles. The user can then check this variable.
  67. yield builtin_from_name(inference_state, 'True')
  68. elif name == 'overload':
  69. yield OverloadFunction.create_cached(
  70. inference_state, self.parent_context, self.tree_name)
  71. elif name == 'NewType':
  72. v, = self._wrapped_name.infer()
  73. yield NewTypeFunction.create_cached(inference_state, v)
  74. elif name == 'cast':
  75. cast_fn, = self._wrapped_name.infer()
  76. yield CastFunction.create_cached(inference_state, cast_fn)
  77. elif name == 'TypedDict':
  78. # TODO doesn't even exist in typeshed/typing.py, yet. But will be
  79. # added soon.
  80. yield TypedDictClass.create_cached(
  81. inference_state, self.parent_context, self.tree_name)
  82. else:
  83. # Not necessary, as long as we are not doing type checking:
  84. # no_type_check & no_type_check_decorator
  85. # Everything else shouldn't be relevant...
  86. yield from self._wrapped_name.infer()
  87. class TypingModuleFilterWrapper(FilterWrapper):
  88. name_wrapper_class = TypingModuleName
  89. class ProxyWithGenerics(BaseTypingClassWithGenerics):
  90. def execute_annotation(self):
  91. string_name = self._tree_name.value
  92. if string_name == 'Union':
  93. # This is kind of a special case, because we have Unions (in Jedi
  94. # ValueSets).
  95. return self.gather_annotation_classes().execute_annotation()
  96. elif string_name == 'Optional':
  97. # Optional is basically just saying it's either None or the actual
  98. # type.
  99. return self.gather_annotation_classes().execute_annotation() \
  100. | ValueSet([builtin_from_name(self.inference_state, 'None')])
  101. elif string_name == 'Type':
  102. # The type is actually already given in the index_value
  103. return self._generics_manager[0]
  104. elif string_name in ['ClassVar', 'Annotated']:
  105. # For now don't do anything here, ClassVars are always used.
  106. return self._generics_manager[0].execute_annotation()
  107. mapped = {
  108. 'Tuple': Tuple,
  109. 'Generic': Generic,
  110. 'Protocol': Protocol,
  111. 'Callable': Callable,
  112. }
  113. cls = mapped[string_name]
  114. return ValueSet([cls(
  115. self.parent_context,
  116. self,
  117. self._tree_name,
  118. generics_manager=self._generics_manager,
  119. )])
  120. def gather_annotation_classes(self):
  121. return ValueSet.from_sets(self._generics_manager.to_tuple())
  122. def _create_instance_with_generics(self, generics_manager):
  123. return ProxyWithGenerics(
  124. self.parent_context,
  125. self._tree_name,
  126. generics_manager
  127. )
  128. def infer_type_vars(self, value_set):
  129. annotation_generics = self.get_generics()
  130. if not annotation_generics:
  131. return {}
  132. annotation_name = self.py__name__()
  133. if annotation_name == 'Optional':
  134. # Optional[T] is equivalent to Union[T, None]. In Jedi unions
  135. # are represented by members within a ValueSet, so we extract
  136. # the T from the Optional[T] by removing the None value.
  137. none = builtin_from_name(self.inference_state, 'None')
  138. return annotation_generics[0].infer_type_vars(
  139. value_set.filter(lambda x: x != none),
  140. )
  141. return {}
  142. class ProxyTypingValue(BaseTypingValue):
  143. index_class = ProxyWithGenerics
  144. def with_generics(self, generics_tuple):
  145. return self.index_class.create_cached(
  146. self.inference_state,
  147. self.parent_context,
  148. self._tree_name,
  149. generics_manager=TupleGenericManager(generics_tuple)
  150. )
  151. def py__getitem__(self, index_value_set, contextualized_node):
  152. return ValueSet(
  153. self.index_class.create_cached(
  154. self.inference_state,
  155. self.parent_context,
  156. self._tree_name,
  157. generics_manager=LazyGenericManager(
  158. context_of_index=contextualized_node.context,
  159. index_value=index_value,
  160. )
  161. ) for index_value in index_value_set
  162. )
  163. class _TypingClassMixin(ClassMixin):
  164. def py__bases__(self):
  165. return [LazyKnownValues(
  166. self.inference_state.builtins_module.py__getattribute__('object')
  167. )]
  168. def get_metaclasses(self):
  169. return []
  170. @property
  171. def name(self):
  172. return ValueName(self, self._tree_name)
  173. class TypingClassWithGenerics(ProxyWithGenerics, _TypingClassMixin):
  174. def infer_type_vars(self, value_set):
  175. type_var_dict = {}
  176. annotation_generics = self.get_generics()
  177. if not annotation_generics:
  178. return type_var_dict
  179. annotation_name = self.py__name__()
  180. if annotation_name == 'Type':
  181. return annotation_generics[0].infer_type_vars(
  182. # This is basically a trick to avoid extra code: We execute the
  183. # incoming classes to be able to use the normal code for type
  184. # var inference.
  185. value_set.execute_annotation(),
  186. )
  187. elif annotation_name == 'Callable':
  188. if len(annotation_generics) == 2:
  189. return annotation_generics[1].infer_type_vars(
  190. value_set.execute_annotation(),
  191. )
  192. elif annotation_name == 'Tuple':
  193. tuple_annotation, = self.execute_annotation()
  194. return tuple_annotation.infer_type_vars(value_set)
  195. return type_var_dict
  196. def _create_instance_with_generics(self, generics_manager):
  197. return TypingClassWithGenerics(
  198. self.parent_context,
  199. self._tree_name,
  200. generics_manager
  201. )
  202. class ProxyTypingClassValue(ProxyTypingValue, _TypingClassMixin):
  203. index_class = TypingClassWithGenerics
  204. class TypeAlias(LazyValueWrapper):
  205. def __init__(self, parent_context, origin_tree_name, actual):
  206. self.inference_state = parent_context.inference_state
  207. self.parent_context = parent_context
  208. self._origin_tree_name = origin_tree_name
  209. self._actual = actual # e.g. builtins.list
  210. @property
  211. def name(self):
  212. return ValueName(self, self._origin_tree_name)
  213. def py__name__(self):
  214. return self.name.string_name
  215. def __repr__(self):
  216. return '<%s: %s>' % (self.__class__.__name__, self._actual)
  217. def _get_wrapped_value(self):
  218. module_name, class_name = self._actual.split('.')
  219. # TODO use inference_state.import_module?
  220. from jedi.inference.imports import Importer
  221. module, = Importer(
  222. self.inference_state, [module_name], self.inference_state.builtins_module
  223. ).follow()
  224. classes = module.py__getattribute__(class_name)
  225. # There should only be one, because it's code that we control.
  226. assert len(classes) == 1, classes
  227. cls = next(iter(classes))
  228. return cls
  229. def gather_annotation_classes(self):
  230. return ValueSet([self._get_wrapped_value()])
  231. def get_signatures(self):
  232. return []
  233. class Callable(BaseTypingInstance):
  234. def py__call__(self, arguments):
  235. """
  236. def x() -> Callable[[Callable[..., _T]], _T]: ...
  237. """
  238. # The 0th index are the arguments.
  239. try:
  240. param_values = self._generics_manager[0]
  241. result_values = self._generics_manager[1]
  242. except IndexError:
  243. debug.warning('Callable[...] defined without two arguments')
  244. return NO_VALUES
  245. else:
  246. from jedi.inference.gradual.annotation import infer_return_for_callable
  247. return infer_return_for_callable(arguments, param_values, result_values)
  248. def py__get__(self, instance, class_value):
  249. return ValueSet([self])
  250. class Tuple(BaseTypingInstance):
  251. def _is_homogenous(self):
  252. # To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
  253. # is used.
  254. return self._generics_manager.is_homogenous_tuple()
  255. def py__simple_getitem__(self, index):
  256. if self._is_homogenous():
  257. return self._generics_manager.get_index_and_execute(0)
  258. else:
  259. if isinstance(index, int):
  260. return self._generics_manager.get_index_and_execute(index)
  261. debug.dbg('The getitem type on Tuple was %s' % index)
  262. return NO_VALUES
  263. def py__iter__(self, contextualized_node=None):
  264. if self._is_homogenous():
  265. yield LazyKnownValues(self._generics_manager.get_index_and_execute(0))
  266. else:
  267. for v in self._generics_manager.to_tuple():
  268. yield LazyKnownValues(v.execute_annotation())
  269. def py__getitem__(self, index_value_set, contextualized_node):
  270. if self._is_homogenous():
  271. return self._generics_manager.get_index_and_execute(0)
  272. return ValueSet.from_sets(
  273. self._generics_manager.to_tuple()
  274. ).execute_annotation()
  275. def _get_wrapped_value(self):
  276. tuple_, = self.inference_state.builtins_module \
  277. .py__getattribute__('tuple').execute_annotation()
  278. return tuple_
  279. @property
  280. def name(self):
  281. return self._wrapped_value.name
  282. def infer_type_vars(self, value_set):
  283. # Circular
  284. from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
  285. value_set = value_set.filter(
  286. lambda x: x.py__name__().lower() == 'tuple',
  287. )
  288. if self._is_homogenous():
  289. # The parameter annotation is of the form `Tuple[T, ...]`,
  290. # so we treat the incoming tuple like a iterable sequence
  291. # rather than a positional container of elements.
  292. return self._class_value.get_generics()[0].infer_type_vars(
  293. value_set.merge_types_of_iterate(),
  294. )
  295. else:
  296. # The parameter annotation has only explicit type parameters
  297. # (e.g: `Tuple[T]`, `Tuple[T, U]`, `Tuple[T, U, V]`, etc.) so we
  298. # treat the incoming values as needing to match the annotation
  299. # exactly, just as we would for non-tuple annotations.
  300. type_var_dict = {}
  301. for element in value_set:
  302. try:
  303. method = element.get_annotated_class_object
  304. except AttributeError:
  305. # This might still happen, because the tuple name matching
  306. # above is not 100% correct, so just catch the remaining
  307. # cases here.
  308. continue
  309. py_class = method()
  310. merge_type_var_dicts(
  311. type_var_dict,
  312. merge_pairwise_generics(self._class_value, py_class),
  313. )
  314. return type_var_dict
  315. class Generic(BaseTypingInstance):
  316. pass
  317. class Protocol(BaseTypingInstance):
  318. pass
  319. class AnyClass(BaseTypingValue):
  320. def execute_annotation(self):
  321. debug.warning('Used Any - returned no results')
  322. return NO_VALUES
  323. class OverloadFunction(BaseTypingValue):
  324. @repack_with_argument_clinic('func, /')
  325. def py__call__(self, func_value_set):
  326. # Just pass arguments through.
  327. return func_value_set
  328. class NewTypeFunction(ValueWrapper):
  329. def py__call__(self, arguments):
  330. ordered_args = arguments.unpack()
  331. next(ordered_args, (None, None))
  332. _, second_arg = next(ordered_args, (None, None))
  333. if second_arg is None:
  334. return NO_VALUES
  335. return ValueSet(
  336. NewType(
  337. self.inference_state,
  338. contextualized_node.context,
  339. contextualized_node.node,
  340. second_arg.infer(),
  341. ) for contextualized_node in arguments.get_calling_nodes())
  342. class NewType(Value):
  343. def __init__(self, inference_state, parent_context, tree_node, type_value_set):
  344. super().__init__(inference_state, parent_context)
  345. self._type_value_set = type_value_set
  346. self.tree_node = tree_node
  347. def py__class__(self):
  348. c, = self._type_value_set.py__class__()
  349. return c
  350. def py__call__(self, arguments):
  351. return self._type_value_set.execute_annotation()
  352. @property
  353. def name(self):
  354. from jedi.inference.compiled.value import CompiledValueName
  355. return CompiledValueName(self, 'NewType')
  356. def __repr__(self) -> str:
  357. return '<NewType: %s>%s' % (self.tree_node, self._type_value_set)
  358. class CastFunction(ValueWrapper):
  359. @repack_with_argument_clinic('type, object, /')
  360. def py__call__(self, type_value_set, object_value_set):
  361. return type_value_set.execute_annotation()
  362. class TypedDictClass(BaseTypingValue):
  363. """
  364. This class has no responsibilities and is just here to make sure that typed
  365. dicts can be identified.
  366. """
  367. class TypedDict(LazyValueWrapper):
  368. """Represents the instance version of ``TypedDictClass``."""
  369. def __init__(self, definition_class):
  370. self.inference_state = definition_class.inference_state
  371. self.parent_context = definition_class.parent_context
  372. self.tree_node = definition_class.tree_node
  373. self._definition_class = definition_class
  374. @property
  375. def name(self):
  376. return ValueName(self, self.tree_node.name)
  377. def py__simple_getitem__(self, index):
  378. if isinstance(index, str):
  379. return ValueSet.from_sets(
  380. name.infer()
  381. for filter in self._definition_class.get_filters(is_instance=True)
  382. for name in filter.get(index)
  383. )
  384. return NO_VALUES
  385. def get_key_values(self):
  386. filtered_values = itertools.chain.from_iterable((
  387. f.values()
  388. for f in self._definition_class.get_filters(is_instance=True)
  389. ))
  390. return ValueSet({
  391. create_simple_object(self.inference_state, v.string_name)
  392. for v in filtered_values
  393. })
  394. def _get_wrapped_value(self):
  395. d, = self.inference_state.builtins_module.py__getattribute__('dict')
  396. result, = d.execute_with_values()
  397. return result