]> crepu.dev Git - config.git/blame_incremental - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/plugins/stdlib.py
Archivo de configuraciĆ³n de la terminal
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / plugins / stdlib.py
... / ...
CommitLineData
1"""
2Implementations of standard library functions, because it's not possible to
3understand them with Jedi.
4
5To add a new implementation, create a function and add it to the
6``_implemented`` dict at the bottom of this module.
7
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
15
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
37
38
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
45
46class {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
104def 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
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()
146
147
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 """
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)
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()
188
189
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()
194
195
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
208
209
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__()
217
218
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__
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)
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)})
253
254
255class 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)
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))
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)
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
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
331class StaticMethodObject(ValueWrapper):
332 def py__get__(self, instance, class_value):
333 return ValueSet([self._wrapped_value])
334
335
336@argument_clinic('sequence, /')
337def builtins_staticmethod(functions):
338 return ValueSet(StaticMethodObject(f) for f in functions)
339
340
341class 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
353class 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
366class 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)
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 )
384
385
386class 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)
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 )
412
413
414def 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
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
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
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)])
533
534
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
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
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
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
565def functools_partial(value, arguments, callback):
566 return ValueSet(
567 PartialObject(instance, arguments)
568 for instance in value.py__call__(arguments)
569 )
570
571
572def 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, /')
580def _return_first_param(firsts):
581 return firsts
582
583
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 )
591
592
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
600
601
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)]
626
627
628class 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
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
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
653class 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, /')
678def _functools_wraps(funcs):
679 return ValueSet(WrapsCallable(func) for func in funcs)
680
681
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})
689
690
691class 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)
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 ])
710
711
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
726
727
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()
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
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
838
839
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
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
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