Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/plugins/stdlib.py: 33%
452 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1"""
2Implementations of standard library functions, because it's not possible to
3understand them with Jedi.
5To add a new implementation, create a function and add it to the
6``_implemented`` dict at the bottom of this module.
8Note that this module exists only to implement very specific functionality in
9the standard library. The usual way to understand the standard library is the
10compiled module that returns the types for C-builtins.
11"""
12import parso
13import os
14from inspect import Parameter
16from jedi import debug
17from jedi.inference.utils import safe_property
18from jedi.inference.helpers import get_str_or_none
19from jedi.inference.arguments import iterate_argument_clinic, ParamIssue, \
20 repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
21from jedi.inference import analysis
22from jedi.inference import compiled
23from jedi.inference.value.instance import \
24 AnonymousMethodExecutionContext, MethodExecutionContext
25from jedi.inference.base_value import ContextualizedNode, \
26 NO_VALUES, ValueSet, ValueWrapper, LazyValueWrapper
27from jedi.inference.value import ClassValue, ModuleValue
28from jedi.inference.value.klass import ClassMixin
29from jedi.inference.value.function import FunctionMixin
30from jedi.inference.value import iterable
31from jedi.inference.lazy_value import LazyTreeValue, LazyKnownValue, \
32 LazyKnownValues
33from jedi.inference.names import ValueName, BaseTreeParamName
34from jedi.inference.filters import AttributeOverwrite, publish_method, \
35 ParserTreeFilter, DictFilter
36from jedi.inference.signature import AbstractSignature, SignatureWrapper
39# Copied from Python 3.6's stdlib.
40_NAMEDTUPLE_CLASS_TEMPLATE = """\
41_property = property
42_tuple = tuple
43from operator import itemgetter as _itemgetter
44from collections import OrderedDict
46class {typename}(tuple):
47 __slots__ = ()
49 _fields = {field_names!r}
51 def __new__(_cls, {arg_list}):
52 'Create new instance of {typename}({arg_list})'
53 return _tuple.__new__(_cls, ({arg_list}))
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
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
70 def __repr__(self):
71 'Return a nicely formatted representation string'
72 return self.__class__.__name__ + '({repr_fmt})' % self
74 def _asdict(self):
75 'Return a new OrderedDict which maps field names to their values.'
76 return OrderedDict(zip(self._fields, self))
78 def __getnewargs__(self):
79 'Return self as a plain tuple. Used by copy and pickle.'
80 return tuple(self)
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})
89 def __iter__(self):
90 for i in self.__iterable:
91 yield i
93 def __getitem__(self, y):
94 return self.__iterable[y]
96{field_defs}
97"""
99_NAMEDTUPLE_FIELD_TEMPLATE = '''\
100 {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}')
101'''
104def execute(callback):
105 def wrapper(value, arguments):
106 def call():
107 return callback(value, arguments=arguments)
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()
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()
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()
136 return wrapper
139def _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()
148def 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 """
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
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
179 return wrapper
180 return f
183@argument_clinic('iterator[, default], /', want_inference_state=True)
184def 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()
190@argument_clinic('iterator[, default], /')
191def 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()
196@argument_clinic('object, name[, default], /')
197def 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
210@argument_clinic('object[, bases, dict], /')
211def 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__()
219class 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__
225 def _get_bases(self):
226 return self._instance.py__class__().py__bases__()
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))
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
243@argument_clinic('[type[, value]], /', want_context=True)
244def 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)})
255class ReversedObject(AttributeOverwrite):
256 def __init__(self, reversed_obj, iter_list):
257 super().__init__(reversed_obj)
258 self._iter_list = iter_list
260 def py__iter__(self, contextualized_node=None):
261 return self._iter_list
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 )
270@argument_clinic('sequence, /', want_value=True, want_arguments=True)
271def 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))
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)))])
289@argument_clinic('value, type, /', want_arguments=True, want_inference_state=True)
290def 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
303 mro = list(cls.py__mro__())
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)
325 return ValueSet(
326 compiled.builtin_from_name(inference_state, str(b))
327 for b in bool_results
328 )
331class StaticMethodObject(ValueWrapper):
332 def py__get__(self, instance, class_value):
333 return ValueSet([self._wrapped_value])
336@argument_clinic('sequence, /')
337def builtins_staticmethod(functions):
338 return ValueSet(StaticMethodObject(f) for f in functions)
341class ClassMethodObject(ValueWrapper):
342 def __init__(self, class_method_obj, function):
343 super().__init__(class_method_obj)
344 self._function = function
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 ])
353class ClassMethodGet(ValueWrapper):
354 def __init__(self, get_method, klass, function):
355 super().__init__(get_method)
356 self._class = klass
357 self._function = function
359 def get_signatures(self):
360 return [sig.bind(self._function) for sig in self._function.get_signatures()]
362 def py__call__(self, arguments):
363 return self._function.execute(ClassMethodArguments(self._class, arguments))
366class ClassMethodArguments(TreeArgumentsWrapper):
367 def __init__(self, klass, arguments):
368 super().__init__(arguments)
369 self._class = klass
371 def unpack(self, func=None):
372 yield None, LazyKnownValue(self._class)
373 for values in self._wrapped_arguments.unpack(func):
374 yield values
377@argument_clinic('sequence, /', want_value=True, want_arguments=True)
378def 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 )
386class PropertyObject(AttributeOverwrite, ValueWrapper):
387 api_type = 'property'
389 def __init__(self, property_obj, function):
390 super().__init__(property_obj)
391 self._function = function
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)
398 @publish_method('deleter')
399 @publish_method('getter')
400 @publish_method('setter')
401 def _return_self(self, arguments):
402 return ValueSet({self})
405@argument_clinic('func, /', want_callback=True)
406def builtins_property(functions, callback):
407 return ValueSet(
408 PropertyObject(property_value, function)
409 for property_value in callback()
410 for function in functions
411 )
414def collections_namedtuple(value, arguments, callback):
415 """
416 Implementation of the namedtuple function.
418 This has to be done by processing the namedtuple class template and
419 inferring the result.
421 """
422 inference_state = value.inference_state
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
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
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 )
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()
469 return ValueSet([ClassValue(inference_state, parent_context, generated_class)])
472class PartialObject(ValueWrapper):
473 def __init__(self, actual_value, arguments, instance=None):
474 super().__init__(actual_value)
475 self._arguments = arguments
476 self._instance = instance
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()
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 []
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()]
502 def py__call__(self, arguments):
503 funcs = self._get_functions(self._arguments.unpack())
504 if funcs is None:
505 return NO_VALUES
507 return funcs.execute(
508 MergedPartialArguments(self._arguments, arguments, self._instance)
509 )
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 ''
524 def py__get__(self, instance, class_value):
525 return ValueSet([self])
528class 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)])
535class 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
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]
546class 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
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
565def functools_partial(value, arguments, callback):
566 return ValueSet(
567 PartialObject(instance, arguments)
568 for instance in value.py__call__(arguments)
569 )
572def functools_partialmethod(value, arguments, callback):
573 return ValueSet(
574 PartialMethodObject(instance, arguments)
575 for instance in value.py__call__(arguments)
576 )
579@argument_clinic('first, /')
580def _return_first_param(firsts):
581 return firsts
584@argument_clinic('seq')
585def _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 )
593def _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
602class 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)]
628class DataclassSignature(AbstractSignature):
629 def __init__(self, value, param_names):
630 super().__init__(value)
631 self._param_names = param_names
633 def get_param_names(self, resolve_stars=False):
634 return self._param_names
637class 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
643 def get_kind(self):
644 return Parameter.POSITIONAL_OR_KEYWORD
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)
653class ItemGetterCallable(ValueWrapper):
654 def __init__(self, instance, args_value_set):
655 super().__init__(instance)
656 self._args_value_set = args_value_set
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
677@argument_clinic('func, /')
678def _functools_wraps(funcs):
679 return ValueSet(WrapsCallable(func) for func in funcs)
682class 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})
691class Wrapped(ValueWrapper, FunctionMixin):
692 def __init__(self, func, original_function):
693 super().__init__(func)
694 self._original_function = original_function
696 @property
697 def name(self):
698 return self._original_function.name
700 def get_signature_functions(self):
701 return [self]
704@argument_clinic('*args, /', want_value=True, want_arguments=True)
705def _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 ])
712def _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
728@argument_clinic('*args, /', want_callback=True)
729def _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()
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}
826def 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
840class 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
847 @safe_property
848 def name(self):
849 return ValueName(self, self._name.tree_name)
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
860 value, = self._cls.execute_with_values()
861 return value
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
872def 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