]> crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/plugins/stdlib.py
Actualizado el Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / plugins / stdlib.py
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