Format: text/x-python
⬇ Download File (29.6 KB)
   1  """
   2  Implementations of standard library functions, because it's not possible to
   3  understand them with Jedi.
   4  
   5  To add a new implementation, create a function and add it to the
   6  ``_implemented`` dict at the bottom of this module.
   7  
   8  Note that this module exists only to implement very specific functionality in
   9  the standard library. The usual way to understand the standard library is the
  10  compiled module that returns the types for C-builtins.
  11  """
  12  import parso
  13  import os
  14  from inspect import Parameter
  15  
  16  from jedi import debug
  17  from jedi.inference.utils import safe_property
  18  from jedi.inference.helpers import get_str_or_none
  19  from jedi.inference.arguments import iterate_argument_clinic, ParamIssue, \
  20      repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
  21  from jedi.inference import analysis
  22  from jedi.inference import compiled
  23  from jedi.inference.value.instance import \
  24      AnonymousMethodExecutionContext, MethodExecutionContext
  25  from jedi.inference.base_value import ContextualizedNode, \
  26      NO_VALUES, ValueSet, ValueWrapper, LazyValueWrapper
  27  from jedi.inference.value import ClassValue, ModuleValue
  28  from jedi.inference.value.klass import ClassMixin
  29  from jedi.inference.value.function import FunctionMixin
  30  from jedi.inference.value import iterable
  31  from jedi.inference.lazy_value import LazyTreeValue, LazyKnownValue, \
  32      LazyKnownValues
  33  from jedi.inference.names import ValueName, BaseTreeParamName
  34  from jedi.inference.filters import AttributeOverwrite, publish_method, \
  35      ParserTreeFilter, DictFilter
  36  from jedi.inference.signature import AbstractSignature, SignatureWrapper
  37  
  38  
  39  # Copied from Python 3.6's stdlib.
  40  _NAMEDTUPLE_CLASS_TEMPLATE = """\
  41  _property = property
  42  _tuple = tuple
  43  from operator import itemgetter as _itemgetter
  44  from collections import OrderedDict
  45  
  46  class {typename}(tuple):
  47      __slots__ = ()
  48  
  49      _fields = {field_names!r}
  50  
  51      def __new__(_cls, {arg_list}):
  52          'Create new instance of {typename}({arg_list})'
  53          return _tuple.__new__(_cls, ({arg_list}))
  54  
  55      @classmethod
  56      def _make(cls, iterable, new=tuple.__new__, len=len):
  57          'Make a new {typename} object from a sequence or iterable'
  58          result = new(cls, iterable)
  59          if len(result) != {num_fields:d}:
  60              raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result))
  61          return result
  62  
  63      def _replace(_self, **kwds):
  64          'Return a new {typename} object replacing specified fields with new values'
  65          result = _self._make(map(kwds.pop, {field_names!r}, _self))
  66          if kwds:
  67              raise ValueError('Got unexpected field names: %r' % list(kwds))
  68          return result
  69  
  70      def __repr__(self):
  71          'Return a nicely formatted representation string'
  72          return self.__class__.__name__ + '({repr_fmt})' % self
  73  
  74      def _asdict(self):
  75          'Return a new OrderedDict which maps field names to their values.'
  76          return OrderedDict(zip(self._fields, self))
  77  
  78      def __getnewargs__(self):
  79          'Return self as a plain tuple.  Used by copy and pickle.'
  80          return tuple(self)
  81  
  82      # These methods were added by Jedi.
  83      # __new__ doesn't really work with Jedi. So adding this to nametuples seems
  84      # like the easiest way.
  85      def __init__(self, {arg_list}):
  86          'A helper function for namedtuple.'
  87          self.__iterable = ({arg_list})
  88  
  89      def __iter__(self):
  90          for i in self.__iterable:
  91              yield i
  92  
  93      def __getitem__(self, y):
  94          return self.__iterable[y]
  95  
  96  {field_defs}
  97  """
  98  
  99  _NAMEDTUPLE_FIELD_TEMPLATE = '''\
 100      {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}')
 101  '''
 102  
 103  
 104  def execute(callback):
 105      def wrapper(value, arguments):
 106          def call():
 107              return callback(value, arguments=arguments)
 108  
 109          try:
 110              obj_name = value.name.string_name
 111          except AttributeError:
 112              pass
 113          else:
 114              p = value.parent_context
 115              if p is not None and p.is_builtins_module():
 116                  module_name = 'builtins'
 117              elif p is not None and p.is_module():
 118                  module_name = p.py__name__()
 119              else:
 120                  return call()
 121  
 122              if value.is_bound_method() or value.is_instance():
 123                  # value can be an instance for example if it is a partial
 124                  # object.
 125                  return call()
 126  
 127              # for now we just support builtin functions.
 128              try:
 129                  func = _implemented[module_name][obj_name]
 130              except KeyError:
 131                  pass
 132              else:
 133                  return func(value, arguments=arguments, callback=call)
 134          return call()
 135  
 136      return wrapper
 137  
 138  
 139  def _follow_param(inference_state, arguments, index):
 140      try:
 141          key, lazy_value = list(arguments.unpack())[index]
 142      except IndexError:
 143          return NO_VALUES
 144      else:
 145          return lazy_value.infer()
 146  
 147  
 148  def argument_clinic(clinic_string, want_value=False, want_context=False,
 149                      want_arguments=False, want_inference_state=False,
 150                      want_callback=False):
 151      """
 152      Works like Argument Clinic (PEP 436), to validate function params.
 153      """
 154  
 155      def f(func):
 156          def wrapper(value, arguments, callback):
 157              try:
 158                  args = tuple(iterate_argument_clinic(
 159                      value.inference_state, arguments, clinic_string))
 160              except ParamIssue:
 161                  return NO_VALUES
 162  
 163              debug.dbg('builtin start %s' % value, color='MAGENTA')
 164              kwargs = {}
 165              if want_context:
 166                  kwargs['context'] = arguments.context
 167              if want_value:
 168                  kwargs['value'] = value
 169              if want_inference_state:
 170                  kwargs['inference_state'] = value.inference_state
 171              if want_arguments:
 172                  kwargs['arguments'] = arguments
 173              if want_callback:
 174                  kwargs['callback'] = callback
 175              result = func(*args, **kwargs)
 176              debug.dbg('builtin end: %s', result, color='MAGENTA')
 177              return result
 178  
 179          return wrapper
 180      return f
 181  
 182  
 183  @argument_clinic('iterator[, default], /', want_inference_state=True)
 184  def builtins_next(iterators, defaults, inference_state):
 185      # TODO theoretically we have to check here if something is an iterator.
 186      # That is probably done by checking if it's not a class.
 187      return defaults | iterators.py__getattribute__('__next__').execute_with_values()
 188  
 189  
 190  @argument_clinic('iterator[, default], /')
 191  def builtins_iter(iterators_or_callables, defaults):
 192      # TODO implement this if it's a callable.
 193      return iterators_or_callables.py__getattribute__('__iter__').execute_with_values()
 194  
 195  
 196  @argument_clinic('object, name[, default], /')
 197  def builtins_getattr(objects, names, defaults=None):
 198      # follow the first param
 199      for value in objects:
 200          for name in names:
 201              string = get_str_or_none(name)
 202              if string is None:
 203                  debug.warning('getattr called without str')
 204                  continue
 205              else:
 206                  return value.py__getattribute__(string)
 207      return NO_VALUES
 208  
 209  
 210  @argument_clinic('object[, bases, dict], /')
 211  def builtins_type(objects, bases, dicts):
 212      if bases or dicts:
 213          # It's a type creation... maybe someday...
 214          return NO_VALUES
 215      else:
 216          return objects.py__class__()
 217  
 218  
 219  class SuperInstance(LazyValueWrapper):
 220      """To be used like the object ``super`` returns."""
 221      def __init__(self, inference_state, instance):
 222          self.inference_state = inference_state
 223          self._instance = instance  # Corresponds to super().__self__
 224  
 225      def _get_bases(self):
 226          return self._instance.py__class__().py__bases__()
 227  
 228      def _get_wrapped_value(self):
 229          objs = self._get_bases()[0].infer().execute_with_values()
 230          if not objs:
 231              # This is just a fallback and will only be used, if it's not
 232              # possible to find a class
 233              return self._instance
 234          return next(iter(objs))
 235  
 236      def get_filters(self, origin_scope=None):
 237          for b in self._get_bases():
 238              for value in b.infer().execute_with_values():
 239                  for f in value.get_filters():
 240                      yield f
 241  
 242  
 243  @argument_clinic('[type[, value]], /', want_context=True)
 244  def builtins_super(types, objects, context):
 245      instance = None
 246      if isinstance(context, AnonymousMethodExecutionContext):
 247          instance = context.instance
 248      elif isinstance(context, MethodExecutionContext):
 249          instance = context.instance
 250      if instance is None:
 251          return NO_VALUES
 252      return ValueSet({SuperInstance(instance.inference_state, instance)})
 253  
 254  
 255  class ReversedObject(AttributeOverwrite):
 256      def __init__(self, reversed_obj, iter_list):
 257          super().__init__(reversed_obj)
 258          self._iter_list = iter_list
 259  
 260      def py__iter__(self, contextualized_node=None):
 261          return self._iter_list
 262  
 263      @publish_method('__next__')
 264      def _next(self, arguments):
 265          return ValueSet.from_sets(
 266              lazy_value.infer() for lazy_value in self._iter_list
 267          )
 268  
 269  
 270  @argument_clinic('sequence, /', want_value=True, want_arguments=True)
 271  def builtins_reversed(sequences, value, arguments):
 272      # While we could do without this variable (just by using sequences), we
 273      # want static analysis to work well. Therefore we need to generated the
 274      # values again.
 275      key, lazy_value = next(arguments.unpack())
 276      cn = None
 277      if isinstance(lazy_value, LazyTreeValue):
 278          cn = ContextualizedNode(lazy_value.context, lazy_value.data)
 279      ordered = list(sequences.iterate(cn))
 280  
 281      # Repack iterator values and then run it the normal way. This is
 282      # necessary, because `reversed` is a function and autocompletion
 283      # would fail in certain cases like `reversed(x).__iter__` if we
 284      # just returned the result directly.
 285      seq, = value.inference_state.typing_module.py__getattribute__('Iterator').execute_with_values()
 286      return ValueSet([ReversedObject(seq, list(reversed(ordered)))])
 287  
 288  
 289  @argument_clinic('value, type, /', want_arguments=True, want_inference_state=True)
 290  def builtins_isinstance(objects, types, arguments, inference_state):
 291      bool_results = set()
 292      for o in objects:
 293          cls = o.py__class__()
 294          try:
 295              cls.py__bases__
 296          except AttributeError:
 297              # This is temporary. Everything should have a class attribute in
 298              # Python?! Maybe we'll leave it here, because some numpy objects or
 299              # whatever might not.
 300              bool_results = set([True, False])
 301              break
 302  
 303          mro = list(cls.py__mro__())
 304  
 305          for cls_or_tup in types:
 306              if cls_or_tup.is_class():
 307                  bool_results.add(cls_or_tup in mro)
 308              elif cls_or_tup.name.string_name == 'tuple' \
 309                      and cls_or_tup.get_root_context().is_builtins_module():
 310                  # Check for tuples.
 311                  classes = ValueSet.from_sets(
 312                      lazy_value.infer()
 313                      for lazy_value in cls_or_tup.iterate()
 314                  )
 315                  bool_results.add(any(cls in mro for cls in classes))
 316              else:
 317                  _, lazy_value = list(arguments.unpack())[1]
 318                  if isinstance(lazy_value, LazyTreeValue):
 319                      node = lazy_value.data
 320                      message = 'TypeError: isinstance() arg 2 must be a ' \
 321                                'class, type, or tuple of classes and types, ' \
 322                                'not %s.' % cls_or_tup
 323                      analysis.add(lazy_value.context, 'type-error-isinstance', node, message)
 324  
 325      return ValueSet(
 326          compiled.builtin_from_name(inference_state, str(b))
 327          for b in bool_results
 328      )
 329  
 330  
 331  class StaticMethodObject(ValueWrapper):
 332      def py__get__(self, instance, class_value):
 333          return ValueSet([self._wrapped_value])
 334  
 335  
 336  @argument_clinic('sequence, /')
 337  def builtins_staticmethod(functions):
 338      return ValueSet(StaticMethodObject(f) for f in functions)
 339  
 340  
 341  class ClassMethodObject(ValueWrapper):
 342      def __init__(self, class_method_obj, function):
 343          super().__init__(class_method_obj)
 344          self._function = function
 345  
 346      def py__get__(self, instance, class_value):
 347          return ValueSet([
 348              ClassMethodGet(__get__, class_value, self._function)
 349              for __get__ in self._wrapped_value.py__getattribute__('__get__')
 350          ])
 351  
 352  
 353  class ClassMethodGet(ValueWrapper):
 354      def __init__(self, get_method, klass, function):
 355          super().__init__(get_method)
 356          self._class = klass
 357          self._function = function
 358  
 359      def get_signatures(self):
 360          return [sig.bind(self._function) for sig in self._function.get_signatures()]
 361  
 362      def py__call__(self, arguments):
 363          return self._function.execute(ClassMethodArguments(self._class, arguments))
 364  
 365  
 366  class ClassMethodArguments(TreeArgumentsWrapper):
 367      def __init__(self, klass, arguments):
 368          super().__init__(arguments)
 369          self._class = klass
 370  
 371      def unpack(self, func=None):
 372          yield None, LazyKnownValue(self._class)
 373          for values in self._wrapped_arguments.unpack(func):
 374              yield values
 375  
 376  
 377  @argument_clinic('sequence, /', want_value=True, want_arguments=True)
 378  def builtins_classmethod(functions, value, arguments):
 379      return ValueSet(
 380          ClassMethodObject(class_method_object, function)
 381          for class_method_object in value.py__call__(arguments=arguments)
 382          for function in functions
 383      )
 384  
 385  
 386  class PropertyObject(AttributeOverwrite, ValueWrapper):
 387      api_type = 'property'
 388  
 389      def __init__(self, property_obj, function):
 390          super().__init__(property_obj)
 391          self._function = function
 392  
 393      def py__get__(self, instance, class_value):
 394          if instance is None:
 395              return ValueSet([self])
 396          return self._function.execute_with_values(instance)
 397  
 398      @publish_method('deleter')
 399      @publish_method('getter')
 400      @publish_method('setter')
 401      def _return_self(self, arguments):
 402          return ValueSet({self})
 403  
 404  
 405  @argument_clinic('func, /', want_callback=True)
 406  def builtins_property(functions, callback):
 407      return ValueSet(
 408          PropertyObject(property_value, function)
 409          for property_value in callback()
 410          for function in functions
 411      )
 412  
 413  
 414  def collections_namedtuple(value, arguments, callback):
 415      """
 416      Implementation of the namedtuple function.
 417  
 418      This has to be done by processing the namedtuple class template and
 419      inferring the result.
 420  
 421      """
 422      inference_state = value.inference_state
 423  
 424      # Process arguments
 425      name = 'jedi_unknown_namedtuple'
 426      for c in _follow_param(inference_state, arguments, 0):
 427          x = get_str_or_none(c)
 428          if x is not None:
 429              name = x
 430              break
 431  
 432      # TODO here we only use one of the types, we should use all.
 433      param_values = _follow_param(inference_state, arguments, 1)
 434      if not param_values:
 435          return NO_VALUES
 436      _fields = list(param_values)[0]
 437      string = get_str_or_none(_fields)
 438      if string is not None:
 439          fields = string.replace(',', ' ').split()
 440      elif isinstance(_fields, iterable.Sequence):
 441          fields = [
 442              get_str_or_none(v)
 443              for lazy_value in _fields.py__iter__()
 444              for v in lazy_value.infer()
 445          ]
 446          fields = [f for f in fields if f is not None]
 447      else:
 448          return NO_VALUES
 449  
 450      # Build source code
 451      code = _NAMEDTUPLE_CLASS_TEMPLATE.format(
 452          typename=name,
 453          field_names=tuple(fields),
 454          num_fields=len(fields),
 455          arg_list=repr(tuple(fields)).replace("'", "")[1:-1],
 456          repr_fmt='',
 457          field_defs='\n'.join(_NAMEDTUPLE_FIELD_TEMPLATE.format(index=index, name=name)
 458                               for index, name in enumerate(fields))
 459      )
 460  
 461      # Parse source code
 462      module = inference_state.grammar.parse(code)
 463      generated_class = next(module.iter_classdefs())
 464      parent_context = ModuleValue(
 465          inference_state, module,
 466          code_lines=parso.split_lines(code, keepends=True),
 467      ).as_context()
 468  
 469      return ValueSet([ClassValue(inference_state, parent_context, generated_class)])
 470  
 471  
 472  class PartialObject(ValueWrapper):
 473      def __init__(self, actual_value, arguments, instance=None):
 474          super().__init__(actual_value)
 475          self._arguments = arguments
 476          self._instance = instance
 477  
 478      def _get_functions(self, unpacked_arguments):
 479          key, lazy_value = next(unpacked_arguments, (None, None))
 480          if key is not None or lazy_value is None:
 481              debug.warning("Partial should have a proper function %s", self._arguments)
 482              return None
 483          return lazy_value.infer()
 484  
 485      def get_signatures(self):
 486          unpacked_arguments = self._arguments.unpack()
 487          funcs = self._get_functions(unpacked_arguments)
 488          if funcs is None:
 489              return []
 490  
 491          arg_count = 0
 492          if self._instance is not None:
 493              arg_count = 1
 494          keys = set()
 495          for key, _ in unpacked_arguments:
 496              if key is None:
 497                  arg_count += 1
 498              else:
 499                  keys.add(key)
 500          return [PartialSignature(s, arg_count, keys) for s in funcs.get_signatures()]
 501  
 502      def py__call__(self, arguments):
 503          funcs = self._get_functions(self._arguments.unpack())
 504          if funcs is None:
 505              return NO_VALUES
 506  
 507          return funcs.execute(
 508              MergedPartialArguments(self._arguments, arguments, self._instance)
 509          )
 510  
 511      def py__doc__(self):
 512          """
 513          In CPython partial does not replace the docstring. However we are still
 514          imitating it here, because we want this docstring to be worth something
 515          for the user.
 516          """
 517          callables = self._get_functions(self._arguments.unpack())
 518          if callables is None:
 519              return ''
 520          for callable_ in callables:
 521              return callable_.py__doc__()
 522          return ''
 523  
 524      def py__get__(self, instance, class_value):
 525          return ValueSet([self])
 526  
 527  
 528  class PartialMethodObject(PartialObject):
 529      def py__get__(self, instance, class_value):
 530          if instance is None:
 531              return ValueSet([self])
 532          return ValueSet([PartialObject(self._wrapped_value, self._arguments, instance)])
 533  
 534  
 535  class PartialSignature(SignatureWrapper):
 536      def __init__(self, wrapped_signature, skipped_arg_count, skipped_arg_set):
 537          super().__init__(wrapped_signature)
 538          self._skipped_arg_count = skipped_arg_count
 539          self._skipped_arg_set = skipped_arg_set
 540  
 541      def get_param_names(self, resolve_stars=False):
 542          names = self._wrapped_signature.get_param_names()[self._skipped_arg_count:]
 543          return [n for n in names if n.string_name not in self._skipped_arg_set]
 544  
 545  
 546  class MergedPartialArguments(AbstractArguments):
 547      def __init__(self, partial_arguments, call_arguments, instance=None):
 548          self._partial_arguments = partial_arguments
 549          self._call_arguments = call_arguments
 550          self._instance = instance
 551  
 552      def unpack(self, funcdef=None):
 553          unpacked = self._partial_arguments.unpack(funcdef)
 554          # Ignore this one, it's the function. It was checked before that it's
 555          # there.
 556          next(unpacked, None)
 557          if self._instance is not None:
 558              yield None, LazyKnownValue(self._instance)
 559          for key_lazy_value in unpacked:
 560              yield key_lazy_value
 561          for key_lazy_value in self._call_arguments.unpack(funcdef):
 562              yield key_lazy_value
 563  
 564  
 565  def functools_partial(value, arguments, callback):
 566      return ValueSet(
 567          PartialObject(instance, arguments)
 568          for instance in value.py__call__(arguments)
 569      )
 570  
 571  
 572  def functools_partialmethod(value, arguments, callback):
 573      return ValueSet(
 574          PartialMethodObject(instance, arguments)
 575          for instance in value.py__call__(arguments)
 576      )
 577  
 578  
 579  @argument_clinic('first, /')
 580  def _return_first_param(firsts):
 581      return firsts
 582  
 583  
 584  @argument_clinic('seq')
 585  def _random_choice(sequences):
 586      return ValueSet.from_sets(
 587          lazy_value.infer()
 588          for sequence in sequences
 589          for lazy_value in sequence.py__iter__()
 590      )
 591  
 592  
 593  def _dataclass(value, arguments, callback):
 594      for c in _follow_param(value.inference_state, arguments, 0):
 595          if c.is_class():
 596              return ValueSet([DataclassWrapper(c)])
 597          else:
 598              return ValueSet([value])
 599      return NO_VALUES
 600  
 601  
 602  class DataclassWrapper(ValueWrapper, ClassMixin):
 603      def get_signatures(self):
 604          param_names = []
 605          for cls in reversed(list(self.py__mro__())):
 606              if isinstance(cls, DataclassWrapper):
 607                  filter_ = cls.as_context().get_global_filter()
 608                  # .values ordering is not guaranteed, at least not in
 609                  # Python < 3.6, when dicts where not ordered, which is an
 610                  # implementation detail anyway.
 611                  for name in sorted(filter_.values(), key=lambda name: name.start_pos):
 612                      d = name.tree_name.get_definition()
 613                      annassign = d.children[1]
 614                      if d.type == 'expr_stmt' and annassign.type == 'annassign':
 615                          if len(annassign.children) < 4:
 616                              default = None
 617                          else:
 618                              default = annassign.children[3]
 619                          param_names.append(DataclassParamName(
 620                              parent_context=cls.parent_context,
 621                              tree_name=name.tree_name,
 622                              annotation_node=annassign.children[1],
 623                              default_node=default,
 624                          ))
 625          return [DataclassSignature(cls, param_names)]
 626  
 627  
 628  class DataclassSignature(AbstractSignature):
 629      def __init__(self, value, param_names):
 630          super().__init__(value)
 631          self._param_names = param_names
 632  
 633      def get_param_names(self, resolve_stars=False):
 634          return self._param_names
 635  
 636  
 637  class DataclassParamName(BaseTreeParamName):
 638      def __init__(self, parent_context, tree_name, annotation_node, default_node):
 639          super().__init__(parent_context, tree_name)
 640          self.annotation_node = annotation_node
 641          self.default_node = default_node
 642  
 643      def get_kind(self):
 644          return Parameter.POSITIONAL_OR_KEYWORD
 645  
 646      def infer(self):
 647          if self.annotation_node is None:
 648              return NO_VALUES
 649          else:
 650              return self.parent_context.infer_node(self.annotation_node)
 651  
 652  
 653  class ItemGetterCallable(ValueWrapper):
 654      def __init__(self, instance, args_value_set):
 655          super().__init__(instance)
 656          self._args_value_set = args_value_set
 657  
 658      @repack_with_argument_clinic('item, /')
 659      def py__call__(self, item_value_set):
 660          value_set = NO_VALUES
 661          for args_value in self._args_value_set:
 662              lazy_values = list(args_value.py__iter__())
 663              if len(lazy_values) == 1:
 664                  # TODO we need to add the contextualized value.
 665                  value_set |= item_value_set.get_item(lazy_values[0].infer(), None)
 666              else:
 667                  value_set |= ValueSet([iterable.FakeList(
 668                      self._wrapped_value.inference_state,
 669                      [
 670                          LazyKnownValues(item_value_set.get_item(lazy_value.infer(), None))
 671                          for lazy_value in lazy_values
 672                      ],
 673                  )])
 674          return value_set
 675  
 676  
 677  @argument_clinic('func, /')
 678  def _functools_wraps(funcs):
 679      return ValueSet(WrapsCallable(func) for func in funcs)
 680  
 681  
 682  class WrapsCallable(ValueWrapper):
 683      # XXX this is not the correct wrapped value, it should be a weird
 684      #     partials object, but it doesn't matter, because it's always used as a
 685      #     decorator anyway.
 686      @repack_with_argument_clinic('func, /')
 687      def py__call__(self, funcs):
 688          return ValueSet({Wrapped(func, self._wrapped_value) for func in funcs})
 689  
 690  
 691  class Wrapped(ValueWrapper, FunctionMixin):
 692      def __init__(self, func, original_function):
 693          super().__init__(func)
 694          self._original_function = original_function
 695  
 696      @property
 697      def name(self):
 698          return self._original_function.name
 699  
 700      def get_signature_functions(self):
 701          return [self]
 702  
 703  
 704  @argument_clinic('*args, /', want_value=True, want_arguments=True)
 705  def _operator_itemgetter(args_value_set, value, arguments):
 706      return ValueSet([
 707          ItemGetterCallable(instance, args_value_set)
 708          for instance in value.py__call__(arguments)
 709      ])
 710  
 711  
 712  def _create_string_input_function(func):
 713      @argument_clinic('string, /', want_value=True, want_arguments=True)
 714      def wrapper(strings, value, arguments):
 715          def iterate():
 716              for value in strings:
 717                  s = get_str_or_none(value)
 718                  if s is not None:
 719                      s = func(s)
 720                      yield compiled.create_simple_object(value.inference_state, s)
 721          values = ValueSet(iterate())
 722          if values:
 723              return values
 724          return value.py__call__(arguments)
 725      return wrapper
 726  
 727  
 728  @argument_clinic('*args, /', want_callback=True)
 729  def _os_path_join(args_set, callback):
 730      if len(args_set) == 1:
 731          string = ''
 732          sequence, = args_set
 733          is_first = True
 734          for lazy_value in sequence.py__iter__():
 735              string_values = lazy_value.infer()
 736              if len(string_values) != 1:
 737                  break
 738              s = get_str_or_none(next(iter(string_values)))
 739              if s is None:
 740                  break
 741              if not is_first:
 742                  string += os.path.sep
 743              string += s
 744              is_first = False
 745          else:
 746              return ValueSet([compiled.create_simple_object(sequence.inference_state, string)])
 747      return callback()
 748  
 749  
 750  _implemented = {
 751      'builtins': {
 752          'getattr': builtins_getattr,
 753          'type': builtins_type,
 754          'super': builtins_super,
 755          'reversed': builtins_reversed,
 756          'isinstance': builtins_isinstance,
 757          'next': builtins_next,
 758          'iter': builtins_iter,
 759          'staticmethod': builtins_staticmethod,
 760          'classmethod': builtins_classmethod,
 761          'property': builtins_property,
 762      },
 763      'copy': {
 764          'copy': _return_first_param,
 765          'deepcopy': _return_first_param,
 766      },
 767      'json': {
 768          'load': lambda value, arguments, callback: NO_VALUES,
 769          'loads': lambda value, arguments, callback: NO_VALUES,
 770      },
 771      'collections': {
 772          'namedtuple': collections_namedtuple,
 773      },
 774      'functools': {
 775          'partial': functools_partial,
 776          'partialmethod': functools_partialmethod,
 777          'wraps': _functools_wraps,
 778      },
 779      '_weakref': {
 780          'proxy': _return_first_param,
 781      },
 782      'random': {
 783          'choice': _random_choice,
 784      },
 785      'operator': {
 786          'itemgetter': _operator_itemgetter,
 787      },
 788      'abc': {
 789          # Not sure if this is necessary, but it's used a lot in typeshed and
 790          # it's for now easier to just pass the function.
 791          'abstractmethod': _return_first_param,
 792      },
 793      'typing': {
 794          # The _alias function just leads to some annoying type inference.
 795          # Therefore, just make it return nothing, which leads to the stubs
 796          # being used instead. This only matters for 3.7+.
 797          '_alias': lambda value, arguments, callback: NO_VALUES,
 798          # runtime_checkable doesn't really change anything and is just
 799          # adding logs for infering stuff, so we can safely ignore it.
 800          'runtime_checkable': lambda value, arguments, callback: NO_VALUES,
 801      },
 802      'dataclasses': {
 803          # For now this works at least better than Jedi trying to understand it.
 804          'dataclass': _dataclass
 805      },
 806      # attrs exposes declaration interface roughly compatible with dataclasses
 807      # via attrs.define, attrs.frozen and attrs.mutable
 808      # https://www.attrs.org/en/stable/names.html
 809      'attr': {
 810          'define': _dataclass,
 811          'frozen': _dataclass,
 812      },
 813      'attrs': {
 814          'define': _dataclass,
 815          'frozen': _dataclass,
 816      },
 817      'os.path': {
 818          'dirname': _create_string_input_function(os.path.dirname),
 819          'abspath': _create_string_input_function(os.path.abspath),
 820          'relpath': _create_string_input_function(os.path.relpath),
 821          'join': _os_path_join,
 822      }
 823  }
 824  
 825  
 826  def get_metaclass_filters(func):
 827      def wrapper(cls, metaclasses, is_instance):
 828          for metaclass in metaclasses:
 829              if metaclass.py__name__() == 'EnumMeta' \
 830                      and metaclass.get_root_context().py__name__() == 'enum':
 831                  filter_ = ParserTreeFilter(parent_context=cls.as_context())
 832                  return [DictFilter({
 833                      name.string_name: EnumInstance(cls, name).name
 834                      for name in filter_.values()
 835                  })]
 836          return func(cls, metaclasses, is_instance)
 837      return wrapper
 838  
 839  
 840  class EnumInstance(LazyValueWrapper):
 841      def __init__(self, cls, name):
 842          self.inference_state = cls.inference_state
 843          self._cls = cls  # Corresponds to super().__self__
 844          self._name = name
 845          self.tree_node = self._name.tree_name
 846  
 847      @safe_property
 848      def name(self):
 849          return ValueName(self, self._name.tree_name)
 850  
 851      def _get_wrapped_value(self):
 852          n = self._name.string_name
 853          if n.startswith('__') and n.endswith('__') or self._name.api_type == 'function':
 854              inferred = self._name.infer()
 855              if inferred:
 856                  return next(iter(inferred))
 857              o, = self.inference_state.builtins_module.py__getattribute__('object')
 858              return o
 859  
 860          value, = self._cls.execute_with_values()
 861          return value
 862  
 863      def get_filters(self, origin_scope=None):
 864          yield DictFilter(dict(
 865              name=compiled.create_simple_object(self.inference_state, self._name.string_name).name,
 866              value=self._name,
 867          ))
 868          for f in self._get_wrapped_value().get_filters():
 869              yield f
 870  
 871  
 872  def tree_name_to_values(func):
 873      def wrapper(inference_state, context, tree_name):
 874          if tree_name.value == 'sep' and context.is_module() and context.py__name__() == 'os.path':
 875              return ValueSet({
 876                  compiled.create_simple_object(inference_state, os.path.sep),
 877              })
 878          return func(inference_state, context, tree_name)
 879      return wrapper
 880