Format: text/x-python
⬇ Download File (22.0 KB)
   1  from abc import abstractproperty
   2  
   3  from parso.tree import search_ancestor
   4  
   5  from jedi import debug
   6  from jedi import settings
   7  from jedi.inference import compiled
   8  from jedi.inference.compiled.value import CompiledValueFilter
   9  from jedi.inference.helpers import values_from_qualified_names, is_big_annoying_library
  10  from jedi.inference.filters import AbstractFilter, AnonymousFunctionExecutionFilter
  11  from jedi.inference.names import ValueName, TreeNameDefinition, ParamName, \
  12      NameWrapper
  13  from jedi.inference.base_value import Value, NO_VALUES, ValueSet, \
  14      iterator_to_value_set, ValueWrapper
  15  from jedi.inference.lazy_value import LazyKnownValue, LazyKnownValues
  16  from jedi.inference.cache import inference_state_method_cache
  17  from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper
  18  from jedi.inference.value.function import \
  19      FunctionValue, FunctionMixin, OverloadedFunctionValue, \
  20      BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass
  21  from jedi.inference.value.klass import ClassFilter
  22  from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance
  23  from jedi.parser_utils import function_is_staticmethod, function_is_classmethod
  24  
  25  
  26  class InstanceExecutedParamName(ParamName):
  27      def __init__(self, instance, function_value, tree_name):
  28          super().__init__(
  29              function_value, tree_name, arguments=None)
  30          self._instance = instance
  31  
  32      def infer(self):
  33          return ValueSet([self._instance])
  34  
  35      def matches_signature(self):
  36          return True
  37  
  38  
  39  class AnonymousMethodExecutionFilter(AnonymousFunctionExecutionFilter):
  40      def __init__(self, instance, *args, **kwargs):
  41          super().__init__(*args, **kwargs)
  42          self._instance = instance
  43  
  44      def _convert_param(self, param, name):
  45          if param.position_index == 0:
  46              if function_is_classmethod(self._function_value.tree_node):
  47                  return InstanceExecutedParamName(
  48                      self._instance.py__class__(),
  49                      self._function_value,
  50                      name
  51                  )
  52              elif not function_is_staticmethod(self._function_value.tree_node):
  53                  return InstanceExecutedParamName(
  54                      self._instance,
  55                      self._function_value,
  56                      name
  57                  )
  58          return super()._convert_param(param, name)
  59  
  60  
  61  class AnonymousMethodExecutionContext(BaseFunctionExecutionContext):
  62      def __init__(self, instance, value):
  63          super().__init__(value)
  64          self.instance = instance
  65  
  66      def get_filters(self, until_position=None, origin_scope=None):
  67          yield AnonymousMethodExecutionFilter(
  68              self.instance, self, self._value,
  69              until_position=until_position,
  70              origin_scope=origin_scope,
  71          )
  72  
  73      def get_param_names(self):
  74          param_names = list(self._value.get_param_names())
  75          # set the self name
  76          param_names[0] = InstanceExecutedParamName(
  77              self.instance,
  78              self._value,
  79              param_names[0].tree_name
  80          )
  81          return param_names
  82  
  83  
  84  class MethodExecutionContext(FunctionExecutionContext):
  85      def __init__(self, instance, *args, **kwargs):
  86          super().__init__(*args, **kwargs)
  87          self.instance = instance
  88  
  89  
  90  class AbstractInstanceValue(Value):
  91      api_type = 'instance'
  92  
  93      def __init__(self, inference_state, parent_context, class_value):
  94          super().__init__(inference_state, parent_context)
  95          # Generated instances are classes that are just generated by self
  96          # (No arguments) used.
  97          self.class_value = class_value
  98  
  99      def is_instance(self):
 100          return True
 101  
 102      def get_qualified_names(self):
 103          return self.class_value.get_qualified_names()
 104  
 105      def get_annotated_class_object(self):
 106          return self.class_value  # This is the default.
 107  
 108      def py__class__(self):
 109          return self.class_value
 110  
 111      def py__bool__(self):
 112          # Signalize that we don't know about the bool type.
 113          return None
 114  
 115      @abstractproperty
 116      def name(self):
 117          raise NotImplementedError
 118  
 119      def get_signatures(self):
 120          call_funcs = self.py__getattribute__('__call__').py__get__(self, self.class_value)
 121          return [s.bind(self) for s in call_funcs.get_signatures()]
 122  
 123      def get_function_slot_names(self, name):
 124          # Python classes don't look at the dictionary of the instance when
 125          # looking up `__call__`. This is something that has to do with Python's
 126          # internal slot system (note: not __slots__, but C slots).
 127          for filter in self.get_filters(include_self_names=False):
 128              names = filter.get(name)
 129              if names:
 130                  return names
 131          return []
 132  
 133      def execute_function_slots(self, names, *inferred_args):
 134          return ValueSet.from_sets(
 135              name.infer().execute_with_values(*inferred_args)
 136              for name in names
 137          )
 138  
 139      def get_type_hint(self, add_class_info=True):
 140          return self.py__name__()
 141  
 142      def py__getitem__(self, index_value_set, contextualized_node):
 143          names = self.get_function_slot_names('__getitem__')
 144          if not names:
 145              return super().py__getitem__(
 146                  index_value_set,
 147                  contextualized_node,
 148              )
 149  
 150          args = ValuesArguments([index_value_set])
 151          return ValueSet.from_sets(name.infer().execute(args) for name in names)
 152  
 153      def py__iter__(self, contextualized_node=None):
 154          iter_slot_names = self.get_function_slot_names('__iter__')
 155          if not iter_slot_names:
 156              return super().py__iter__(contextualized_node)
 157  
 158          def iterate():
 159              for generator in self.execute_function_slots(iter_slot_names):
 160                  yield from generator.py__next__(contextualized_node)
 161          return iterate()
 162  
 163      def __repr__(self):
 164          return "<%s of %s>" % (self.__class__.__name__, self.class_value)
 165  
 166  
 167  class CompiledInstance(AbstractInstanceValue):
 168      # This is not really a compiled class, it's just an instance from a
 169      # compiled class.
 170      def __init__(self, inference_state, parent_context, class_value, arguments):
 171          super().__init__(inference_state, parent_context, class_value)
 172          self._arguments = arguments
 173  
 174      def get_filters(self, origin_scope=None, include_self_names=True):
 175          class_value = self.get_annotated_class_object()
 176          class_filters = class_value.get_filters(
 177              origin_scope=origin_scope,
 178              is_instance=True,
 179          )
 180          for f in class_filters:
 181              yield CompiledInstanceClassFilter(self, f)
 182  
 183      @property
 184      def name(self):
 185          return compiled.CompiledValueName(self, self.class_value.name.string_name)
 186  
 187      def is_stub(self):
 188          return False
 189  
 190  
 191  class _BaseTreeInstance(AbstractInstanceValue):
 192      @property
 193      def array_type(self):
 194          name = self.class_value.py__name__()
 195          if name in ['list', 'set', 'dict'] \
 196                  and self.parent_context.get_root_context().is_builtins_module():
 197              return name
 198          return None
 199  
 200      @property
 201      def name(self):
 202          return ValueName(self, self.class_value.name.tree_name)
 203  
 204      def get_filters(self, origin_scope=None, include_self_names=True):
 205          class_value = self.get_annotated_class_object()
 206          if include_self_names:
 207              for cls in class_value.py__mro__():
 208                  if not cls.is_compiled():
 209                      # In this case we're excluding compiled objects that are
 210                      # not fake objects. It doesn't make sense for normal
 211                      # compiled objects to search for self variables.
 212                      yield SelfAttributeFilter(self, class_value, cls.as_context(), origin_scope)
 213  
 214          class_filters = class_value.get_filters(
 215              origin_scope=origin_scope,
 216              is_instance=True,
 217          )
 218          for f in class_filters:
 219              if isinstance(f, ClassFilter):
 220                  yield InstanceClassFilter(self, f)
 221              elif isinstance(f, CompiledValueFilter):
 222                  yield CompiledInstanceClassFilter(self, f)
 223              else:
 224                  # Propably from the metaclass.
 225                  yield f
 226  
 227      @inference_state_method_cache()
 228      def create_instance_context(self, class_context, node):
 229          new = node
 230          while True:
 231              func_node = new
 232              new = search_ancestor(new, 'funcdef', 'classdef')
 233              if class_context.tree_node is new:
 234                  func = FunctionValue.from_context(class_context, func_node)
 235                  bound_method = BoundMethod(self, class_context, func)
 236                  if func_node.name.value == '__init__':
 237                      context = bound_method.as_context(self._arguments)
 238                  else:
 239                      context = bound_method.as_context()
 240                  break
 241          return context.create_context(node)
 242  
 243      def py__getattribute__alternatives(self, string_name):
 244          '''
 245          Since nothing was inferred, now check the __getattr__ and
 246          __getattribute__ methods. Stubs don't need to be checked, because
 247          they don't contain any logic.
 248          '''
 249          if self.is_stub():
 250              return NO_VALUES
 251  
 252          name = compiled.create_simple_object(self.inference_state, string_name)
 253  
 254          # This is a little bit special. `__getattribute__` is in Python
 255          # executed before `__getattr__`. But: I know no use case, where
 256          # this could be practical and where Jedi would return wrong types.
 257          # If you ever find something, let me know!
 258          # We are inversing this, because a hand-crafted `__getattribute__`
 259          # could still call another hand-crafted `__getattr__`, but not the
 260          # other way around.
 261          if is_big_annoying_library(self.parent_context):
 262              return NO_VALUES
 263          names = (self.get_function_slot_names('__getattr__')
 264                   or self.get_function_slot_names('__getattribute__'))
 265          return self.execute_function_slots(names, name)
 266  
 267      def py__next__(self, contextualized_node=None):
 268          name = u'__next__'
 269          next_slot_names = self.get_function_slot_names(name)
 270          if next_slot_names:
 271              yield LazyKnownValues(
 272                  self.execute_function_slots(next_slot_names)
 273              )
 274          else:
 275              debug.warning('Instance has no __next__ function in %s.', self)
 276  
 277      def py__call__(self, arguments):
 278          names = self.get_function_slot_names('__call__')
 279          if not names:
 280              # Means the Instance is not callable.
 281              return super().py__call__(arguments)
 282  
 283          return ValueSet.from_sets(name.infer().execute(arguments) for name in names)
 284  
 285      def py__get__(self, instance, class_value):
 286          """
 287          obj may be None.
 288          """
 289          # Arguments in __get__ descriptors are obj, class.
 290          # `method` is the new parent of the array, don't know if that's good.
 291          for cls in self.class_value.py__mro__():
 292              result = cls.py__get__on_class(self, instance, class_value)
 293              if result is not NotImplemented:
 294                  return result
 295  
 296          names = self.get_function_slot_names('__get__')
 297          if names:
 298              if instance is None:
 299                  instance = compiled.builtin_from_name(self.inference_state, 'None')
 300              return self.execute_function_slots(names, instance, class_value)
 301          else:
 302              return ValueSet([self])
 303  
 304  
 305  class TreeInstance(_BaseTreeInstance):
 306      def __init__(self, inference_state, parent_context, class_value, arguments):
 307          # I don't think that dynamic append lookups should happen here. That
 308          # sounds more like something that should go to py__iter__.
 309          if class_value.py__name__() in ['list', 'set'] \
 310                  and parent_context.get_root_context().is_builtins_module():
 311              # compare the module path with the builtin name.
 312              if settings.dynamic_array_additions:
 313                  arguments = get_dynamic_array_instance(self, arguments)
 314  
 315          super().__init__(inference_state, parent_context, class_value)
 316          self._arguments = arguments
 317          self.tree_node = class_value.tree_node
 318  
 319      # This can recurse, if the initialization of the class includes a reference
 320      # to itself.
 321      @inference_state_method_cache(default=None)
 322      def _get_annotated_class_object(self):
 323          from jedi.inference.gradual.annotation import py__annotations__, \
 324              infer_type_vars_for_execution
 325  
 326          args = InstanceArguments(self, self._arguments)
 327          for signature in self.class_value.py__getattribute__('__init__').get_signatures():
 328              # Just take the first result, it should always be one, because we
 329              # control the typeshed code.
 330              funcdef = signature.value.tree_node
 331              if funcdef is None or funcdef.type != 'funcdef' \
 332                      or not signature.matches_signature(args):
 333                  # First check if the signature even matches, if not we don't
 334                  # need to infer anything.
 335                  continue
 336              bound_method = BoundMethod(self, self.class_value.as_context(), signature.value)
 337              all_annotations = py__annotations__(funcdef)
 338              type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations)
 339              if type_var_dict:
 340                  defined, = self.class_value.define_generics(
 341                      infer_type_vars_for_execution(signature.value, args, all_annotations),
 342                  )
 343                  debug.dbg('Inferred instance value as %s', defined, color='BLUE')
 344                  return defined
 345          return None
 346  
 347      def get_annotated_class_object(self):
 348          return self._get_annotated_class_object() or self.class_value
 349  
 350      def get_key_values(self):
 351          values = NO_VALUES
 352          if self.array_type == 'dict':
 353              for i, (key, instance) in enumerate(self._arguments.unpack()):
 354                  if key is None and i == 0:
 355                      values |= ValueSet.from_sets(
 356                          v.get_key_values()
 357                          for v in instance.infer()
 358                          if v.array_type == 'dict'
 359                      )
 360                  if key:
 361                      values |= ValueSet([compiled.create_simple_object(
 362                          self.inference_state,
 363                          key,
 364                      )])
 365  
 366          return values
 367  
 368      def py__simple_getitem__(self, index):
 369          if self.array_type == 'dict':
 370              # Logic for dict({'foo': bar}) and dict(foo=bar)
 371              # reversed, because:
 372              # >>> dict({'a': 1}, a=3)
 373              # {'a': 3}
 374              # TODO tuple initializations
 375              # >>> dict([('a', 4)])
 376              # {'a': 4}
 377              for key, lazy_context in reversed(list(self._arguments.unpack())):
 378                  if key is None:
 379                      values = ValueSet.from_sets(
 380                          dct_value.py__simple_getitem__(index)
 381                          for dct_value in lazy_context.infer()
 382                          if dct_value.array_type == 'dict'
 383                      )
 384                      if values:
 385                          return values
 386                  else:
 387                      if key == index:
 388                          return lazy_context.infer()
 389          return super().py__simple_getitem__(index)
 390  
 391      def __repr__(self):
 392          return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_value,
 393                                     self._arguments)
 394  
 395  
 396  class AnonymousInstance(_BaseTreeInstance):
 397      _arguments = None
 398  
 399  
 400  class CompiledInstanceName(NameWrapper):
 401      @iterator_to_value_set
 402      def infer(self):
 403          for result_value in self._wrapped_name.infer():
 404              if result_value.api_type == 'function':
 405                  yield CompiledBoundMethod(result_value)
 406              else:
 407                  yield result_value
 408  
 409  
 410  class CompiledInstanceClassFilter(AbstractFilter):
 411      def __init__(self, instance, f):
 412          self._instance = instance
 413          self._class_filter = f
 414  
 415      def get(self, name):
 416          return self._convert(self._class_filter.get(name))
 417  
 418      def values(self):
 419          return self._convert(self._class_filter.values())
 420  
 421      def _convert(self, names):
 422          return [CompiledInstanceName(n) for n in names]
 423  
 424  
 425  class BoundMethod(FunctionMixin, ValueWrapper):
 426      def __init__(self, instance, class_context, function):
 427          super().__init__(function)
 428          self.instance = instance
 429          self._class_context = class_context
 430  
 431      def is_bound_method(self):
 432          return True
 433  
 434      @property
 435      def name(self):
 436          return FunctionNameInClass(
 437              self._class_context,
 438              super().name
 439          )
 440  
 441      def py__class__(self):
 442          c, = values_from_qualified_names(self.inference_state, 'types', 'MethodType')
 443          return c
 444  
 445      def _get_arguments(self, arguments):
 446          assert arguments is not None
 447          return InstanceArguments(self.instance, arguments)
 448  
 449      def _as_context(self, arguments=None):
 450          if arguments is None:
 451              return AnonymousMethodExecutionContext(self.instance, self)
 452  
 453          arguments = self._get_arguments(arguments)
 454          return MethodExecutionContext(self.instance, self, arguments)
 455  
 456      def py__call__(self, arguments):
 457          if isinstance(self._wrapped_value, OverloadedFunctionValue):
 458              return self._wrapped_value.py__call__(self._get_arguments(arguments))
 459  
 460          function_execution = self.as_context(arguments)
 461          return function_execution.infer()
 462  
 463      def get_signature_functions(self):
 464          return [
 465              BoundMethod(self.instance, self._class_context, f)
 466              for f in self._wrapped_value.get_signature_functions()
 467          ]
 468  
 469      def get_signatures(self):
 470          return [sig.bind(self) for sig in super().get_signatures()]
 471  
 472      def __repr__(self):
 473          return '<%s: %s>' % (self.__class__.__name__, self._wrapped_value)
 474  
 475  
 476  class CompiledBoundMethod(ValueWrapper):
 477      def is_bound_method(self):
 478          return True
 479  
 480      def get_signatures(self):
 481          return [sig.bind(self) for sig in self._wrapped_value.get_signatures()]
 482  
 483  
 484  class SelfName(TreeNameDefinition):
 485      """
 486      This name calculates the parent_context lazily.
 487      """
 488      def __init__(self, instance, class_context, tree_name):
 489          self._instance = instance
 490          self.class_context = class_context
 491          self.tree_name = tree_name
 492  
 493      @property
 494      def parent_context(self):
 495          return self._instance.create_instance_context(self.class_context, self.tree_name)
 496  
 497      def get_defining_qualified_value(self):
 498          return self._instance
 499  
 500      def infer(self):
 501          stmt = search_ancestor(self.tree_name, 'expr_stmt')
 502          if stmt is not None:
 503              if stmt.children[1].type == "annassign":
 504                  from jedi.inference.gradual.annotation import infer_annotation
 505                  values = infer_annotation(
 506                      self.parent_context, stmt.children[1].children[1]
 507                  ).execute_annotation()
 508                  if values:
 509                      return values
 510          return super().infer()
 511  
 512  
 513  class LazyInstanceClassName(NameWrapper):
 514      def __init__(self, instance, class_member_name):
 515          super().__init__(class_member_name)
 516          self._instance = instance
 517  
 518      @iterator_to_value_set
 519      def infer(self):
 520          for result_value in self._wrapped_name.infer():
 521              yield from result_value.py__get__(self._instance, self._instance.py__class__())
 522  
 523      def get_signatures(self):
 524          return self.infer().get_signatures()
 525  
 526      def get_defining_qualified_value(self):
 527          return self._instance
 528  
 529  
 530  class InstanceClassFilter(AbstractFilter):
 531      """
 532      This filter is special in that it uses the class filter and wraps the
 533      resulting names in LazyInstanceClassName. The idea is that the class name
 534      filtering can be very flexible and always be reflected in instances.
 535      """
 536      def __init__(self, instance, class_filter):
 537          self._instance = instance
 538          self._class_filter = class_filter
 539  
 540      def get(self, name):
 541          return self._convert(self._class_filter.get(name))
 542  
 543      def values(self):
 544          return self._convert(self._class_filter.values())
 545  
 546      def _convert(self, names):
 547          return [
 548              LazyInstanceClassName(self._instance, n)
 549              for n in names
 550          ]
 551  
 552      def __repr__(self):
 553          return '<%s for %s>' % (self.__class__.__name__, self._class_filter)
 554  
 555  
 556  class SelfAttributeFilter(ClassFilter):
 557      """
 558      This class basically filters all the use cases where `self.*` was assigned.
 559      """
 560      def __init__(self, instance, instance_class, node_context, origin_scope):
 561          super().__init__(
 562              class_value=instance_class,
 563              node_context=node_context,
 564              origin_scope=origin_scope,
 565              is_instance=True,
 566          )
 567          self._instance = instance
 568  
 569      def _filter(self, names):
 570          start, end = self._parser_scope.start_pos, self._parser_scope.end_pos
 571          names = [n for n in names if start < n.start_pos < end]
 572          return self._filter_self_names(names)
 573  
 574      def _filter_self_names(self, names):
 575          for name in names:
 576              trailer = name.parent
 577              if trailer.type == 'trailer' \
 578                      and len(trailer.parent.children) == 2 \
 579                      and trailer.children[0] == '.':
 580                  if name.is_definition() and self._access_possible(name):
 581                      # TODO filter non-self assignments instead of this bad
 582                      #      filter.
 583                      if self._is_in_right_scope(trailer.parent.children[0], name):
 584                          yield name
 585  
 586      def _is_in_right_scope(self, self_name, name):
 587          self_context = self._node_context.create_context(self_name)
 588          names = self_context.goto(self_name, position=self_name.start_pos)
 589          return any(
 590              n.api_type == 'param'
 591              and n.tree_name.get_definition().position_index == 0
 592              and n.parent_context.tree_node is self._parser_scope
 593              for n in names
 594          )
 595  
 596      def _convert_names(self, names):
 597          return [SelfName(self._instance, self._node_context, name) for name in names]
 598  
 599      def _check_flows(self, names):
 600          return names
 601  
 602  
 603  class InstanceArguments(TreeArgumentsWrapper):
 604      def __init__(self, instance, arguments):
 605          super().__init__(arguments)
 606          self.instance = instance
 607  
 608      def unpack(self, func=None):
 609          yield None, LazyKnownValue(self.instance)
 610          yield from self._wrapped_arguments.unpack(func)
 611