klass.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. """
  2. Like described in the :mod:`parso.python.tree` module,
  3. there's a need for an ast like module to represent the states of parsed
  4. modules.
  5. But now there are also structures in Python that need a little bit more than
  6. that. An ``Instance`` for example is only a ``Class`` before it is
  7. instantiated. This class represents these cases.
  8. So, why is there also a ``Class`` class here? Well, there are decorators and
  9. they change classes in Python 3.
  10. Representation modules also define "magic methods". Those methods look like
  11. ``py__foo__`` and are typically mappable to the Python equivalents ``__call__``
  12. and others. Here's a list:
  13. ====================================== ========================================
  14. **Method** **Description**
  15. -------------------------------------- ----------------------------------------
  16. py__call__(arguments: Array) On callable objects, returns types.
  17. py__bool__() Returns True/False/None; None means that
  18. there's no certainty.
  19. py__bases__() Returns a list of base classes.
  20. py__iter__() Returns a generator of a set of types.
  21. py__class__() Returns the class of an instance.
  22. py__simple_getitem__(index: int/str) Returns a a set of types of the index.
  23. Can raise an IndexError/KeyError.
  24. py__getitem__(indexes: ValueSet) Returns a a set of types of the index.
  25. py__file__() Only on modules. Returns None if does
  26. not exist.
  27. py__package__() -> List[str] Only on modules. For the import system.
  28. py__path__() Only on modules. For the import system.
  29. py__get__(call_object) Only on instances. Simulates
  30. descriptors.
  31. py__doc__() Returns the docstring for a value.
  32. ====================================== ========================================
  33. """
  34. from jedi import debug
  35. from jedi.parser_utils import get_cached_parent_scope, expr_is_dotted, \
  36. function_is_property
  37. from jedi.inference.cache import inference_state_method_cache, CachedMetaClass, \
  38. inference_state_method_generator_cache
  39. from jedi.inference import compiled
  40. from jedi.inference.lazy_value import LazyKnownValues, LazyTreeValue
  41. from jedi.inference.filters import ParserTreeFilter
  42. from jedi.inference.names import TreeNameDefinition, ValueName
  43. from jedi.inference.arguments import unpack_arglist, ValuesArguments
  44. from jedi.inference.base_value import ValueSet, iterator_to_value_set, \
  45. NO_VALUES
  46. from jedi.inference.context import ClassContext
  47. from jedi.inference.value.function import FunctionAndClassBase
  48. from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager
  49. from jedi.plugins import plugin_manager
  50. class ClassName(TreeNameDefinition):
  51. def __init__(self, class_value, tree_name, name_context, apply_decorators):
  52. super().__init__(name_context, tree_name)
  53. self._apply_decorators = apply_decorators
  54. self._class_value = class_value
  55. @iterator_to_value_set
  56. def infer(self):
  57. # We're using a different value to infer, so we cannot call super().
  58. from jedi.inference.syntax_tree import tree_name_to_values
  59. inferred = tree_name_to_values(
  60. self.parent_context.inference_state, self.parent_context, self.tree_name)
  61. for result_value in inferred:
  62. if self._apply_decorators:
  63. yield from result_value.py__get__(instance=None, class_value=self._class_value)
  64. else:
  65. yield result_value
  66. @property
  67. def api_type(self):
  68. type_ = super().api_type
  69. if type_ == 'function':
  70. definition = self.tree_name.get_definition()
  71. if definition is None:
  72. return type_
  73. if function_is_property(definition):
  74. # This essentially checks if there is an @property before
  75. # the function. @property could be something different, but
  76. # any programmer that redefines property as something that
  77. # is not really a property anymore, should be shot. (i.e.
  78. # this is a heuristic).
  79. return 'property'
  80. return type_
  81. class ClassFilter(ParserTreeFilter):
  82. def __init__(self, class_value, node_context=None, until_position=None,
  83. origin_scope=None, is_instance=False):
  84. super().__init__(
  85. class_value.as_context(), node_context,
  86. until_position=until_position,
  87. origin_scope=origin_scope,
  88. )
  89. self._class_value = class_value
  90. self._is_instance = is_instance
  91. def _convert_names(self, names):
  92. return [
  93. ClassName(
  94. class_value=self._class_value,
  95. tree_name=name,
  96. name_context=self._node_context,
  97. apply_decorators=not self._is_instance,
  98. ) for name in names
  99. ]
  100. def _equals_origin_scope(self):
  101. node = self._origin_scope
  102. while node is not None:
  103. if node == self._parser_scope or node == self.parent_context:
  104. return True
  105. node = get_cached_parent_scope(self._parso_cache_node, node)
  106. return False
  107. def _access_possible(self, name):
  108. # Filter for name mangling of private variables like __foo
  109. return not name.value.startswith('__') or name.value.endswith('__') \
  110. or self._equals_origin_scope()
  111. def _filter(self, names):
  112. names = super()._filter(names)
  113. return [name for name in names if self._access_possible(name)]
  114. class ClassMixin:
  115. def is_class(self):
  116. return True
  117. def is_class_mixin(self):
  118. return True
  119. def py__call__(self, arguments):
  120. from jedi.inference.value import TreeInstance
  121. from jedi.inference.gradual.typing import TypedDict
  122. if self.is_typeddict():
  123. return ValueSet([TypedDict(self)])
  124. return ValueSet([TreeInstance(self.inference_state, self.parent_context, self, arguments)])
  125. def py__class__(self):
  126. return compiled.builtin_from_name(self.inference_state, 'type')
  127. @property
  128. def name(self):
  129. return ValueName(self, self.tree_node.name)
  130. def py__name__(self):
  131. return self.name.string_name
  132. @inference_state_method_generator_cache()
  133. def py__mro__(self):
  134. mro = [self]
  135. yield self
  136. # TODO Do a proper mro resolution. Currently we are just listing
  137. # classes. However, it's a complicated algorithm.
  138. for lazy_cls in self.py__bases__():
  139. # TODO there's multiple different mro paths possible if this yields
  140. # multiple possibilities. Could be changed to be more correct.
  141. for cls in lazy_cls.infer():
  142. # TODO detect for TypeError: duplicate base class str,
  143. # e.g. `class X(str, str): pass`
  144. try:
  145. mro_method = cls.py__mro__
  146. except AttributeError:
  147. # TODO add a TypeError like:
  148. """
  149. >>> class Y(lambda: test): pass
  150. Traceback (most recent call last):
  151. File "<stdin>", line 1, in <module>
  152. TypeError: function() argument 1 must be code, not str
  153. >>> class Y(1): pass
  154. Traceback (most recent call last):
  155. File "<stdin>", line 1, in <module>
  156. TypeError: int() takes at most 2 arguments (3 given)
  157. """
  158. debug.warning('Super class of %s is not a class: %s', self, cls)
  159. else:
  160. for cls_new in mro_method():
  161. if cls_new not in mro:
  162. mro.append(cls_new)
  163. yield cls_new
  164. def get_filters(self, origin_scope=None, is_instance=False,
  165. include_metaclasses=True, include_type_when_class=True):
  166. if include_metaclasses:
  167. metaclasses = self.get_metaclasses()
  168. if metaclasses:
  169. yield from self.get_metaclass_filters(metaclasses, is_instance)
  170. for cls in self.py__mro__():
  171. if cls.is_compiled():
  172. yield from cls.get_filters(is_instance=is_instance)
  173. else:
  174. yield ClassFilter(
  175. self, node_context=cls.as_context(),
  176. origin_scope=origin_scope,
  177. is_instance=is_instance
  178. )
  179. if not is_instance and include_type_when_class:
  180. from jedi.inference.compiled import builtin_from_name
  181. type_ = builtin_from_name(self.inference_state, 'type')
  182. assert isinstance(type_, ClassValue)
  183. if type_ != self:
  184. # We are not using execute_with_values here, because the
  185. # plugin function for type would get executed instead of an
  186. # instance creation.
  187. args = ValuesArguments([])
  188. for instance in type_.py__call__(args):
  189. instance_filters = instance.get_filters()
  190. # Filter out self filters
  191. next(instance_filters, None)
  192. next(instance_filters, None)
  193. x = next(instance_filters, None)
  194. assert x is not None
  195. yield x
  196. def get_signatures(self):
  197. # Since calling staticmethod without a function is illegal, the Jedi
  198. # plugin doesn't return anything. Therefore call directly and get what
  199. # we want: An instance of staticmethod.
  200. metaclasses = self.get_metaclasses()
  201. if metaclasses:
  202. sigs = self.get_metaclass_signatures(metaclasses)
  203. if sigs:
  204. return sigs
  205. args = ValuesArguments([])
  206. init_funcs = self.py__call__(args).py__getattribute__('__init__')
  207. return [sig.bind(self) for sig in init_funcs.get_signatures()]
  208. def _as_context(self):
  209. return ClassContext(self)
  210. def get_type_hint(self, add_class_info=True):
  211. if add_class_info:
  212. return 'Type[%s]' % self.py__name__()
  213. return self.py__name__()
  214. @inference_state_method_cache(default=False)
  215. def is_typeddict(self):
  216. # TODO Do a proper mro resolution. Currently we are just listing
  217. # classes. However, it's a complicated algorithm.
  218. from jedi.inference.gradual.typing import TypedDictClass
  219. for lazy_cls in self.py__bases__():
  220. if not isinstance(lazy_cls, LazyTreeValue):
  221. return False
  222. tree_node = lazy_cls.data
  223. # Only resolve simple classes, stuff like Iterable[str] are more
  224. # intensive to resolve and if generics are involved, we know it's
  225. # not a TypedDict.
  226. if not expr_is_dotted(tree_node):
  227. return False
  228. for cls in lazy_cls.infer():
  229. if isinstance(cls, TypedDictClass):
  230. return True
  231. try:
  232. method = cls.is_typeddict
  233. except AttributeError:
  234. # We're only dealing with simple classes, so just returning
  235. # here should be fine. This only happens with e.g. compiled
  236. # classes.
  237. return False
  238. else:
  239. if method():
  240. return True
  241. return False
  242. def py__getitem__(self, index_value_set, contextualized_node):
  243. from jedi.inference.gradual.base import GenericClass
  244. if not index_value_set:
  245. debug.warning('Class indexes inferred to nothing. Returning class instead')
  246. return ValueSet([self])
  247. return ValueSet(
  248. GenericClass(
  249. self,
  250. LazyGenericManager(
  251. context_of_index=contextualized_node.context,
  252. index_value=index_value,
  253. )
  254. )
  255. for index_value in index_value_set
  256. )
  257. def with_generics(self, generics_tuple):
  258. from jedi.inference.gradual.base import GenericClass
  259. return GenericClass(
  260. self,
  261. TupleGenericManager(generics_tuple)
  262. )
  263. def define_generics(self, type_var_dict):
  264. from jedi.inference.gradual.base import GenericClass
  265. def remap_type_vars():
  266. """
  267. The TypeVars in the resulting classes have sometimes different names
  268. and we need to check for that, e.g. a signature can be:
  269. def iter(iterable: Iterable[_T]) -> Iterator[_T]: ...
  270. However, the iterator is defined as Iterator[_T_co], which means it has
  271. a different type var name.
  272. """
  273. for type_var in self.list_type_vars():
  274. yield type_var_dict.get(type_var.py__name__(), NO_VALUES)
  275. if type_var_dict:
  276. return ValueSet([GenericClass(
  277. self,
  278. TupleGenericManager(tuple(remap_type_vars()))
  279. )])
  280. return ValueSet({self})
  281. class ClassValue(ClassMixin, FunctionAndClassBase, metaclass=CachedMetaClass):
  282. api_type = 'class'
  283. @inference_state_method_cache()
  284. def list_type_vars(self):
  285. found = []
  286. arglist = self.tree_node.get_super_arglist()
  287. if arglist is None:
  288. return []
  289. for stars, node in unpack_arglist(arglist):
  290. if stars:
  291. continue # These are not relevant for this search.
  292. from jedi.inference.gradual.annotation import find_unknown_type_vars
  293. for type_var in find_unknown_type_vars(self.parent_context, node):
  294. if type_var not in found:
  295. # The order matters and it's therefore a list.
  296. found.append(type_var)
  297. return found
  298. def _get_bases_arguments(self):
  299. arglist = self.tree_node.get_super_arglist()
  300. if arglist:
  301. from jedi.inference import arguments
  302. return arguments.TreeArguments(self.inference_state, self.parent_context, arglist)
  303. return None
  304. @inference_state_method_cache(default=())
  305. def py__bases__(self):
  306. args = self._get_bases_arguments()
  307. if args is not None:
  308. lst = [value for key, value in args.unpack() if key is None]
  309. if lst:
  310. return lst
  311. if self.py__name__() == 'object' \
  312. and self.parent_context.is_builtins_module():
  313. return []
  314. return [LazyKnownValues(
  315. self.inference_state.builtins_module.py__getattribute__('object')
  316. )]
  317. @plugin_manager.decorate()
  318. def get_metaclass_filters(self, metaclasses, is_instance):
  319. debug.warning('Unprocessed metaclass %s', metaclasses)
  320. return []
  321. @inference_state_method_cache(default=NO_VALUES)
  322. def get_metaclasses(self):
  323. args = self._get_bases_arguments()
  324. if args is not None:
  325. m = [value for key, value in args.unpack() if key == 'metaclass']
  326. metaclasses = ValueSet.from_sets(lazy_value.infer() for lazy_value in m)
  327. metaclasses = ValueSet(m for m in metaclasses if m.is_class())
  328. if metaclasses:
  329. return metaclasses
  330. for lazy_base in self.py__bases__():
  331. for value in lazy_base.infer():
  332. if value.is_class():
  333. values = value.get_metaclasses()
  334. if values:
  335. return values
  336. return NO_VALUES
  337. @plugin_manager.decorate()
  338. def get_metaclass_signatures(self, metaclasses):
  339. return []