Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jedi-0.19.2-py3.11.egg/jedi/plugins/stdlib.py: 32%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

436 statements  

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 

14 

15from jedi import debug 

16from jedi.inference.utils import safe_property 

17from jedi.inference.helpers import get_str_or_none 

18from jedi.inference.arguments import iterate_argument_clinic, ParamIssue, \ 

19 repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper 

20from jedi.inference import analysis 

21from jedi.inference import compiled 

22from jedi.inference.value.instance import \ 

23 AnonymousMethodExecutionContext, MethodExecutionContext 

24from jedi.inference.base_value import ContextualizedNode, \ 

25 NO_VALUES, ValueSet, ValueWrapper, LazyValueWrapper 

26from jedi.inference.value import ClassValue, ModuleValue 

27from jedi.inference.value.decorator import Decoratee 

28from jedi.inference.value.klass import ( 

29 DataclassWrapper, 

30 DataclassDecorator, 

31 DataclassTransformer, 

32) 

33from jedi.inference.value.function import FunctionMixin 

34from jedi.inference.value import iterable 

35from jedi.inference.lazy_value import LazyTreeValue, LazyKnownValue, \ 

36 LazyKnownValues 

37from jedi.inference.names import ValueName 

38from jedi.inference.filters import AttributeOverwrite, publish_method, \ 

39 ParserTreeFilter, DictFilter 

40from jedi.inference.signature import SignatureWrapper 

41 

42 

43# Copied from Python 3.6's stdlib. 

44_NAMEDTUPLE_CLASS_TEMPLATE = """\ 

45_property = property 

46_tuple = tuple 

47from operator import itemgetter as _itemgetter 

48from collections import OrderedDict 

49 

50class {typename}(tuple): 

51 __slots__ = () 

52 

53 _fields = {field_names!r} 

54 

55 def __new__(_cls, {arg_list}): 

56 'Create new instance of {typename}({arg_list})' 

57 return _tuple.__new__(_cls, ({arg_list})) 

58 

59 @classmethod 

60 def _make(cls, iterable, new=tuple.__new__, len=len): 

61 'Make a new {typename} object from a sequence or iterable' 

62 result = new(cls, iterable) 

63 if len(result) != {num_fields:d}: 

64 raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result)) 

65 return result 

66 

67 def _replace(_self, **kwds): 

68 'Return a new {typename} object replacing specified fields with new values' 

69 result = _self._make(map(kwds.pop, {field_names!r}, _self)) 

70 if kwds: 

71 raise ValueError('Got unexpected field names: %r' % list(kwds)) 

72 return result 

73 

74 def __repr__(self): 

75 'Return a nicely formatted representation string' 

76 return self.__class__.__name__ + '({repr_fmt})' % self 

77 

78 def _asdict(self): 

79 'Return a new OrderedDict which maps field names to their values.' 

80 return OrderedDict(zip(self._fields, self)) 

81 

82 def __getnewargs__(self): 

83 'Return self as a plain tuple. Used by copy and pickle.' 

84 return tuple(self) 

85 

86 # These methods were added by Jedi. 

87 # __new__ doesn't really work with Jedi. So adding this to nametuples seems 

88 # like the easiest way. 

89 def __init__(self, {arg_list}): 

90 'A helper function for namedtuple.' 

91 self.__iterable = ({arg_list}) 

92 

93 def __iter__(self): 

94 for i in self.__iterable: 

95 yield i 

96 

97 def __getitem__(self, y): 

98 return self.__iterable[y] 

99 

100{field_defs} 

101""" 

102 

103_NAMEDTUPLE_FIELD_TEMPLATE = '''\ 

104 {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}') 

105''' 

106 

107 

108def execute(callback): 

109 def wrapper(value, arguments): 

110 def call(): 

111 return callback(value, arguments=arguments) 

112 

113 try: 

114 obj_name = value.name.string_name 

115 except AttributeError: 

116 pass 

117 else: 

118 p = value.parent_context 

119 if p is not None and p.is_builtins_module(): 

120 module_name = 'builtins' 

121 elif p is not None and p.is_module(): 

122 module_name = p.py__name__() 

123 else: 

124 return call() 

125 

126 if value.is_bound_method() or value.is_instance(): 

127 # value can be an instance for example if it is a partial 

128 # object. 

129 return call() 

130 

131 # for now we just support builtin functions. 

132 try: 

133 func = _implemented[module_name][obj_name] 

134 except KeyError: 

135 pass 

136 else: 

137 return func(value, arguments=arguments, callback=call) 

138 return call() 

139 

140 return wrapper 

141 

142 

143def _follow_param(inference_state, arguments, index): 

144 try: 

145 key, lazy_value = list(arguments.unpack())[index] 

146 except IndexError: 

147 return NO_VALUES 

148 else: 

149 return lazy_value.infer() 

150 

151 

152def argument_clinic(clinic_string, want_value=False, want_context=False, 

153 want_arguments=False, want_inference_state=False, 

154 want_callback=False): 

155 """ 

156 Works like Argument Clinic (PEP 436), to validate function params. 

157 """ 

158 

159 def f(func): 

160 def wrapper(value, arguments, callback): 

161 try: 

162 args = tuple(iterate_argument_clinic( 

163 value.inference_state, arguments, clinic_string)) 

164 except ParamIssue: 

165 return NO_VALUES 

166 

167 debug.dbg('builtin start %s' % value, color='MAGENTA') 

168 kwargs = {} 

169 if want_context: 

170 kwargs['context'] = arguments.context 

171 if want_value: 

172 kwargs['value'] = value 

173 if want_inference_state: 

174 kwargs['inference_state'] = value.inference_state 

175 if want_arguments: 

176 kwargs['arguments'] = arguments 

177 if want_callback: 

178 kwargs['callback'] = callback 

179 result = func(*args, **kwargs) 

180 debug.dbg('builtin end: %s', result, color='MAGENTA') 

181 return result 

182 

183 return wrapper 

184 return f 

185 

186 

187@argument_clinic('iterator[, default], /', want_inference_state=True) 

188def builtins_next(iterators, defaults, inference_state): 

189 # TODO theoretically we have to check here if something is an iterator. 

190 # That is probably done by checking if it's not a class. 

191 return defaults | iterators.py__getattribute__('__next__').execute_with_values() 

192 

193 

194@argument_clinic('iterator[, default], /') 

195def builtins_iter(iterators_or_callables, defaults): 

196 # TODO implement this if it's a callable. 

197 return iterators_or_callables.py__getattribute__('__iter__').execute_with_values() 

198 

199 

200@argument_clinic('object, name[, default], /') 

201def builtins_getattr(objects, names, defaults=None): 

202 # follow the first param 

203 for value in objects: 

204 for name in names: 

205 string = get_str_or_none(name) 

206 if string is None: 

207 debug.warning('getattr called without str') 

208 continue 

209 else: 

210 return value.py__getattribute__(string) 

211 return NO_VALUES 

212 

213 

214@argument_clinic('object[, bases, dict], /') 

215def builtins_type(objects, bases, dicts): 

216 if bases or dicts: 

217 # It's a type creation... maybe someday... 

218 return NO_VALUES 

219 else: 

220 return objects.py__class__() 

221 

222 

223class SuperInstance(LazyValueWrapper): 

224 """To be used like the object ``super`` returns.""" 

225 def __init__(self, inference_state, instance): 

226 self.inference_state = inference_state 

227 self._instance = instance # Corresponds to super().__self__ 

228 

229 def _get_bases(self): 

230 return self._instance.py__class__().py__bases__() 

231 

232 def _get_wrapped_value(self): 

233 objs = self._get_bases()[0].infer().execute_with_values() 

234 if not objs: 

235 # This is just a fallback and will only be used, if it's not 

236 # possible to find a class 

237 return self._instance 

238 return next(iter(objs)) 

239 

240 def get_filters(self, origin_scope=None): 

241 for b in self._get_bases(): 

242 for value in b.infer().execute_with_values(): 

243 for f in value.get_filters(): 

244 yield f 

245 

246 

247@argument_clinic('[type[, value]], /', want_context=True) 

248def builtins_super(types, objects, context): 

249 instance = None 

250 if isinstance(context, AnonymousMethodExecutionContext): 

251 instance = context.instance 

252 elif isinstance(context, MethodExecutionContext): 

253 instance = context.instance 

254 if instance is None: 

255 return NO_VALUES 

256 return ValueSet({SuperInstance(instance.inference_state, instance)}) 

257 

258 

259class ReversedObject(AttributeOverwrite): 

260 def __init__(self, reversed_obj, iter_list): 

261 super().__init__(reversed_obj) 

262 self._iter_list = iter_list 

263 

264 def py__iter__(self, contextualized_node=None): 

265 return self._iter_list 

266 

267 @publish_method('__next__') 

268 def _next(self, arguments): 

269 return ValueSet.from_sets( 

270 lazy_value.infer() for lazy_value in self._iter_list 

271 ) 

272 

273 

274@argument_clinic('sequence, /', want_value=True, want_arguments=True) 

275def builtins_reversed(sequences, value, arguments): 

276 # While we could do without this variable (just by using sequences), we 

277 # want static analysis to work well. Therefore we need to generated the 

278 # values again. 

279 key, lazy_value = next(arguments.unpack()) 

280 cn = None 

281 if isinstance(lazy_value, LazyTreeValue): 

282 cn = ContextualizedNode(lazy_value.context, lazy_value.data) 

283 ordered = list(sequences.iterate(cn)) 

284 

285 # Repack iterator values and then run it the normal way. This is 

286 # necessary, because `reversed` is a function and autocompletion 

287 # would fail in certain cases like `reversed(x).__iter__` if we 

288 # just returned the result directly. 

289 seq, = value.inference_state.typing_module.py__getattribute__('Iterator').execute_with_values() 

290 return ValueSet([ReversedObject(seq, list(reversed(ordered)))]) 

291 

292 

293@argument_clinic('value, type, /', want_arguments=True, want_inference_state=True) 

294def builtins_isinstance(objects, types, arguments, inference_state): 

295 bool_results = set() 

296 for o in objects: 

297 cls = o.py__class__() 

298 try: 

299 cls.py__bases__ 

300 except AttributeError: 

301 # This is temporary. Everything should have a class attribute in 

302 # Python?! Maybe we'll leave it here, because some numpy objects or 

303 # whatever might not. 

304 bool_results = set([True, False]) 

305 break 

306 

307 mro = list(cls.py__mro__()) 

308 

309 for cls_or_tup in types: 

310 if cls_or_tup.is_class(): 

311 bool_results.add(cls_or_tup in mro) 

312 elif cls_or_tup.name.string_name == 'tuple' \ 

313 and cls_or_tup.get_root_context().is_builtins_module(): 

314 # Check for tuples. 

315 classes = ValueSet.from_sets( 

316 lazy_value.infer() 

317 for lazy_value in cls_or_tup.iterate() 

318 ) 

319 bool_results.add(any(cls in mro for cls in classes)) 

320 else: 

321 _, lazy_value = list(arguments.unpack())[1] 

322 if isinstance(lazy_value, LazyTreeValue): 

323 node = lazy_value.data 

324 message = 'TypeError: isinstance() arg 2 must be a ' \ 

325 'class, type, or tuple of classes and types, ' \ 

326 'not %s.' % cls_or_tup 

327 analysis.add(lazy_value.context, 'type-error-isinstance', node, message) 

328 

329 return ValueSet( 

330 compiled.builtin_from_name(inference_state, str(b)) 

331 for b in bool_results 

332 ) 

333 

334 

335class StaticMethodObject(ValueWrapper): 

336 def py__get__(self, instance, class_value): 

337 return ValueSet([self._wrapped_value]) 

338 

339 

340@argument_clinic('sequence, /') 

341def builtins_staticmethod(functions): 

342 return ValueSet(StaticMethodObject(f) for f in functions) 

343 

344 

345class ClassMethodObject(ValueWrapper): 

346 def __init__(self, class_method_obj, function): 

347 super().__init__(class_method_obj) 

348 self._function = function 

349 

350 def py__get__(self, instance, class_value): 

351 return ValueSet([ 

352 ClassMethodGet(__get__, class_value, self._function) 

353 for __get__ in self._wrapped_value.py__getattribute__('__get__') 

354 ]) 

355 

356 

357class ClassMethodGet(ValueWrapper): 

358 def __init__(self, get_method, klass, function): 

359 super().__init__(get_method) 

360 self._class = klass 

361 self._function = function 

362 

363 def get_signatures(self): 

364 return [sig.bind(self._function) for sig in self._function.get_signatures()] 

365 

366 def py__call__(self, arguments): 

367 return self._function.execute(ClassMethodArguments(self._class, arguments)) 

368 

369 

370class ClassMethodArguments(TreeArgumentsWrapper): 

371 def __init__(self, klass, arguments): 

372 super().__init__(arguments) 

373 self._class = klass 

374 

375 def unpack(self, func=None): 

376 yield None, LazyKnownValue(self._class) 

377 for values in self._wrapped_arguments.unpack(func): 

378 yield values 

379 

380 

381@argument_clinic('sequence, /', want_value=True, want_arguments=True) 

382def builtins_classmethod(functions, value, arguments): 

383 return ValueSet( 

384 ClassMethodObject(class_method_object, function) 

385 for class_method_object in value.py__call__(arguments=arguments) 

386 for function in functions 

387 ) 

388 

389 

390class PropertyObject(AttributeOverwrite, ValueWrapper): 

391 api_type = 'property' 

392 

393 def __init__(self, property_obj, function): 

394 super().__init__(property_obj) 

395 self._function = function 

396 

397 def py__get__(self, instance, class_value): 

398 if instance is None: 

399 return ValueSet([self]) 

400 return self._function.execute_with_values(instance) 

401 

402 @publish_method('deleter') 

403 @publish_method('getter') 

404 @publish_method('setter') 

405 def _return_self(self, arguments): 

406 return ValueSet({self}) 

407 

408 

409@argument_clinic('func, /', want_callback=True) 

410def builtins_property(functions, callback): 

411 return ValueSet( 

412 PropertyObject(property_value, function) 

413 for property_value in callback() 

414 for function in functions 

415 ) 

416 

417 

418def collections_namedtuple(value, arguments, callback): 

419 """ 

420 Implementation of the namedtuple function. 

421 

422 This has to be done by processing the namedtuple class template and 

423 inferring the result. 

424 

425 """ 

426 inference_state = value.inference_state 

427 

428 # Process arguments 

429 name = 'jedi_unknown_namedtuple' 

430 for c in _follow_param(inference_state, arguments, 0): 

431 x = get_str_or_none(c) 

432 if x is not None: 

433 name = x 

434 break 

435 

436 # TODO here we only use one of the types, we should use all. 

437 param_values = _follow_param(inference_state, arguments, 1) 

438 if not param_values: 

439 return NO_VALUES 

440 _fields = list(param_values)[0] 

441 string = get_str_or_none(_fields) 

442 if string is not None: 

443 fields = string.replace(',', ' ').split() 

444 elif isinstance(_fields, iterable.Sequence): 

445 fields = [ 

446 get_str_or_none(v) 

447 for lazy_value in _fields.py__iter__() 

448 for v in lazy_value.infer() 

449 ] 

450 fields = [f for f in fields if f is not None] 

451 else: 

452 return NO_VALUES 

453 

454 # Build source code 

455 code = _NAMEDTUPLE_CLASS_TEMPLATE.format( 

456 typename=name, 

457 field_names=tuple(fields), 

458 num_fields=len(fields), 

459 arg_list=repr(tuple(fields)).replace("'", "")[1:-1], 

460 repr_fmt='', 

461 field_defs='\n'.join(_NAMEDTUPLE_FIELD_TEMPLATE.format(index=index, name=name) 

462 for index, name in enumerate(fields)) 

463 ) 

464 

465 # Parse source code 

466 module = inference_state.grammar.parse(code) 

467 generated_class = next(module.iter_classdefs()) 

468 parent_context = ModuleValue( 

469 inference_state, module, 

470 code_lines=parso.split_lines(code, keepends=True), 

471 ).as_context() 

472 

473 return ValueSet([ClassValue(inference_state, parent_context, generated_class)]) 

474 

475 

476class PartialObject(ValueWrapper): 

477 def __init__(self, actual_value, arguments, instance=None): 

478 super().__init__(actual_value) 

479 self._arguments = arguments 

480 self._instance = instance 

481 

482 def _get_functions(self, unpacked_arguments): 

483 key, lazy_value = next(unpacked_arguments, (None, None)) 

484 if key is not None or lazy_value is None: 

485 debug.warning("Partial should have a proper function %s", self._arguments) 

486 return None 

487 return lazy_value.infer() 

488 

489 def get_signatures(self): 

490 unpacked_arguments = self._arguments.unpack() 

491 funcs = self._get_functions(unpacked_arguments) 

492 if funcs is None: 

493 return [] 

494 

495 arg_count = 0 

496 if self._instance is not None: 

497 arg_count = 1 

498 keys = set() 

499 for key, _ in unpacked_arguments: 

500 if key is None: 

501 arg_count += 1 

502 else: 

503 keys.add(key) 

504 return [PartialSignature(s, arg_count, keys) for s in funcs.get_signatures()] 

505 

506 def py__call__(self, arguments): 

507 funcs = self._get_functions(self._arguments.unpack()) 

508 if funcs is None: 

509 return NO_VALUES 

510 

511 return funcs.execute( 

512 MergedPartialArguments(self._arguments, arguments, self._instance) 

513 ) 

514 

515 def py__doc__(self): 

516 """ 

517 In CPython partial does not replace the docstring. However we are still 

518 imitating it here, because we want this docstring to be worth something 

519 for the user. 

520 """ 

521 callables = self._get_functions(self._arguments.unpack()) 

522 if callables is None: 

523 return '' 

524 for callable_ in callables: 

525 return callable_.py__doc__() 

526 return '' 

527 

528 def py__get__(self, instance, class_value): 

529 return ValueSet([self]) 

530 

531 

532class PartialMethodObject(PartialObject): 

533 def py__get__(self, instance, class_value): 

534 if instance is None: 

535 return ValueSet([self]) 

536 return ValueSet([PartialObject(self._wrapped_value, self._arguments, instance)]) 

537 

538 

539class PartialSignature(SignatureWrapper): 

540 def __init__(self, wrapped_signature, skipped_arg_count, skipped_arg_set): 

541 super().__init__(wrapped_signature) 

542 self._skipped_arg_count = skipped_arg_count 

543 self._skipped_arg_set = skipped_arg_set 

544 

545 def get_param_names(self, resolve_stars=False): 

546 names = self._wrapped_signature.get_param_names()[self._skipped_arg_count:] 

547 return [n for n in names if n.string_name not in self._skipped_arg_set] 

548 

549 

550class MergedPartialArguments(AbstractArguments): 

551 def __init__(self, partial_arguments, call_arguments, instance=None): 

552 self._partial_arguments = partial_arguments 

553 self._call_arguments = call_arguments 

554 self._instance = instance 

555 

556 def unpack(self, funcdef=None): 

557 unpacked = self._partial_arguments.unpack(funcdef) 

558 # Ignore this one, it's the function. It was checked before that it's 

559 # there. 

560 next(unpacked, None) 

561 if self._instance is not None: 

562 yield None, LazyKnownValue(self._instance) 

563 for key_lazy_value in unpacked: 

564 yield key_lazy_value 

565 for key_lazy_value in self._call_arguments.unpack(funcdef): 

566 yield key_lazy_value 

567 

568 

569def functools_partial(value, arguments, callback): 

570 return ValueSet( 

571 PartialObject(instance, arguments) 

572 for instance in value.py__call__(arguments) 

573 ) 

574 

575 

576def functools_partialmethod(value, arguments, callback): 

577 return ValueSet( 

578 PartialMethodObject(instance, arguments) 

579 for instance in value.py__call__(arguments) 

580 ) 

581 

582 

583@argument_clinic('first, /') 

584def _return_first_param(firsts): 

585 return firsts 

586 

587 

588@argument_clinic('seq') 

589def _random_choice(sequences): 

590 return ValueSet.from_sets( 

591 lazy_value.infer() 

592 for sequence in sequences 

593 for lazy_value in sequence.py__iter__() 

594 ) 

595 

596 

597def _dataclass(value, arguments, callback): 

598 """ 

599 Decorator entry points for dataclass. 

600 

601 1. dataclass decorator declaration with parameters 

602 2. dataclass semantics on a class from a dataclass(-like) decorator 

603 """ 

604 for c in _follow_param(value.inference_state, arguments, 0): 

605 if c.is_class(): 

606 # Declare dataclass semantics on a class from a dataclass decorator 

607 should_generate_init = ( 

608 # Customized decorator, init may be disabled 

609 value.init_param_mode 

610 if isinstance(value, DataclassDecorator) 

611 # Bare dataclass decorator, always with init mode 

612 else True 

613 ) 

614 return ValueSet([DataclassWrapper(c, should_generate_init)]) 

615 else: 

616 # @dataclass(init=False) 

617 # dataclass decorator customization 

618 return ValueSet( 

619 [ 

620 DataclassDecorator( 

621 value, 

622 arguments=arguments, 

623 default_init=True, 

624 ) 

625 ] 

626 ) 

627 

628 return NO_VALUES 

629 

630 

631def _dataclass_transform(value, arguments, callback): 

632 """ 

633 Decorator entry points for dataclass_transform. 

634 

635 1. dataclass-like decorator instantiation from a dataclass_transform decorator 

636 2. dataclass_transform decorator declaration with parameters 

637 3. dataclass-like decorator declaration with parameters 

638 4. dataclass-like semantics on a class from a dataclass-like decorator 

639 """ 

640 for c in _follow_param(value.inference_state, arguments, 0): 

641 if c.is_class(): 

642 is_dataclass_transform = ( 

643 value.name.string_name == "dataclass_transform" 

644 # The decorator function from dataclass_transform acting as the 

645 # dataclass decorator. 

646 and not isinstance(value, Decoratee) 

647 # The decorator function from dataclass_transform acting as the 

648 # dataclass decorator with customized parameters 

649 and not isinstance(value, DataclassDecorator) 

650 ) 

651 

652 if is_dataclass_transform: 

653 # Declare base class 

654 return ValueSet([DataclassTransformer(c)]) 

655 else: 

656 # Declare dataclass-like semantics on a class from a 

657 # dataclass-like decorator 

658 should_generate_init = value.init_param_mode 

659 return ValueSet([DataclassWrapper(c, should_generate_init)]) 

660 elif c.is_function(): 

661 # dataclass-like decorator instantiation: 

662 # @dataclass_transform 

663 # def create_model() 

664 return ValueSet( 

665 [ 

666 DataclassDecorator( 

667 value, 

668 arguments=arguments, 

669 default_init=True, 

670 ) 

671 ] 

672 ) 

673 elif ( 

674 # @dataclass_transform 

675 # def create_model(): pass 

676 # @create_model(init=...) 

677 isinstance(value, Decoratee) 

678 ): 

679 # dataclass (or like) decorator customization 

680 return ValueSet( 

681 [ 

682 DataclassDecorator( 

683 value, 

684 arguments=arguments, 

685 default_init=value._wrapped_value.init_param_mode, 

686 ) 

687 ] 

688 ) 

689 else: 

690 # dataclass_transform decorator with parameters; nothing impactful 

691 return ValueSet([value]) 

692 return NO_VALUES 

693 

694 

695class ItemGetterCallable(ValueWrapper): 

696 def __init__(self, instance, args_value_set): 

697 super().__init__(instance) 

698 self._args_value_set = args_value_set 

699 

700 @repack_with_argument_clinic('item, /') 

701 def py__call__(self, item_value_set): 

702 value_set = NO_VALUES 

703 for args_value in self._args_value_set: 

704 lazy_values = list(args_value.py__iter__()) 

705 if len(lazy_values) == 1: 

706 # TODO we need to add the contextualized value. 

707 value_set |= item_value_set.get_item(lazy_values[0].infer(), None) 

708 else: 

709 value_set |= ValueSet([iterable.FakeList( 

710 self._wrapped_value.inference_state, 

711 [ 

712 LazyKnownValues(item_value_set.get_item(lazy_value.infer(), None)) 

713 for lazy_value in lazy_values 

714 ], 

715 )]) 

716 return value_set 

717 

718 

719@argument_clinic('func, /') 

720def _functools_wraps(funcs): 

721 return ValueSet(WrapsCallable(func) for func in funcs) 

722 

723 

724class WrapsCallable(ValueWrapper): 

725 # XXX this is not the correct wrapped value, it should be a weird 

726 # partials object, but it doesn't matter, because it's always used as a 

727 # decorator anyway. 

728 @repack_with_argument_clinic('func, /') 

729 def py__call__(self, funcs): 

730 return ValueSet({Wrapped(func, self._wrapped_value) for func in funcs}) 

731 

732 

733class Wrapped(ValueWrapper, FunctionMixin): 

734 def __init__(self, func, original_function): 

735 super().__init__(func) 

736 self._original_function = original_function 

737 

738 @property 

739 def name(self): 

740 return self._original_function.name 

741 

742 def get_signature_functions(self): 

743 return [self] 

744 

745 

746@argument_clinic('*args, /', want_value=True, want_arguments=True) 

747def _operator_itemgetter(args_value_set, value, arguments): 

748 return ValueSet([ 

749 ItemGetterCallable(instance, args_value_set) 

750 for instance in value.py__call__(arguments) 

751 ]) 

752 

753 

754def _create_string_input_function(func): 

755 @argument_clinic('string, /', want_value=True, want_arguments=True) 

756 def wrapper(strings, value, arguments): 

757 def iterate(): 

758 for value in strings: 

759 s = get_str_or_none(value) 

760 if s is not None: 

761 s = func(s) 

762 yield compiled.create_simple_object(value.inference_state, s) 

763 values = ValueSet(iterate()) 

764 if values: 

765 return values 

766 return value.py__call__(arguments) 

767 return wrapper 

768 

769 

770@argument_clinic('*args, /', want_callback=True) 

771def _os_path_join(args_set, callback): 

772 if len(args_set) == 1: 

773 string = '' 

774 sequence, = args_set 

775 is_first = True 

776 for lazy_value in sequence.py__iter__(): 

777 string_values = lazy_value.infer() 

778 if len(string_values) != 1: 

779 break 

780 s = get_str_or_none(next(iter(string_values))) 

781 if s is None: 

782 break 

783 if not is_first: 

784 string += os.path.sep 

785 string += s 

786 is_first = False 

787 else: 

788 return ValueSet([compiled.create_simple_object(sequence.inference_state, string)]) 

789 return callback() 

790 

791 

792_implemented = { 

793 'builtins': { 

794 'getattr': builtins_getattr, 

795 'type': builtins_type, 

796 'super': builtins_super, 

797 'reversed': builtins_reversed, 

798 'isinstance': builtins_isinstance, 

799 'next': builtins_next, 

800 'iter': builtins_iter, 

801 'staticmethod': builtins_staticmethod, 

802 'classmethod': builtins_classmethod, 

803 'property': builtins_property, 

804 }, 

805 'copy': { 

806 'copy': _return_first_param, 

807 'deepcopy': _return_first_param, 

808 }, 

809 'json': { 

810 'load': lambda value, arguments, callback: NO_VALUES, 

811 'loads': lambda value, arguments, callback: NO_VALUES, 

812 }, 

813 'collections': { 

814 'namedtuple': collections_namedtuple, 

815 }, 

816 'functools': { 

817 'partial': functools_partial, 

818 'partialmethod': functools_partialmethod, 

819 'wraps': _functools_wraps, 

820 }, 

821 '_weakref': { 

822 'proxy': _return_first_param, 

823 }, 

824 'random': { 

825 'choice': _random_choice, 

826 }, 

827 'operator': { 

828 'itemgetter': _operator_itemgetter, 

829 }, 

830 'abc': { 

831 # Not sure if this is necessary, but it's used a lot in typeshed and 

832 # it's for now easier to just pass the function. 

833 'abstractmethod': _return_first_param, 

834 }, 

835 'typing': { 

836 # The _alias function just leads to some annoying type inference. 

837 # Therefore, just make it return nothing, which leads to the stubs 

838 # being used instead. This only matters for 3.7+. 

839 '_alias': lambda value, arguments, callback: NO_VALUES, 

840 # runtime_checkable doesn't really change anything and is just 

841 # adding logs for infering stuff, so we can safely ignore it. 

842 'runtime_checkable': lambda value, arguments, callback: NO_VALUES, 

843 # Python 3.11+ 

844 'dataclass_transform': _dataclass_transform, 

845 }, 

846 'typing_extensions': { 

847 # Python <3.11 

848 'dataclass_transform': _dataclass_transform, 

849 }, 

850 'dataclasses': { 

851 # For now this works at least better than Jedi trying to understand it. 

852 'dataclass': _dataclass 

853 }, 

854 'os.path': { 

855 'dirname': _create_string_input_function(os.path.dirname), 

856 'abspath': _create_string_input_function(os.path.abspath), 

857 'relpath': _create_string_input_function(os.path.relpath), 

858 'join': _os_path_join, 

859 } 

860} 

861 

862 

863def get_metaclass_filters(func): 

864 def wrapper(cls, metaclasses, is_instance): 

865 for metaclass in metaclasses: 

866 if metaclass.py__name__() == 'EnumMeta' \ 

867 and metaclass.get_root_context().py__name__() == 'enum': 

868 filter_ = ParserTreeFilter(parent_context=cls.as_context()) 

869 return [DictFilter({ 

870 name.string_name: EnumInstance(cls, name).name 

871 for name in filter_.values() 

872 })] 

873 return func(cls, metaclasses, is_instance) 

874 return wrapper 

875 

876 

877class EnumInstance(LazyValueWrapper): 

878 def __init__(self, cls, name): 

879 self.inference_state = cls.inference_state 

880 self._cls = cls # Corresponds to super().__self__ 

881 self._name = name 

882 self.tree_node = self._name.tree_name 

883 

884 @safe_property 

885 def name(self): 

886 return ValueName(self, self._name.tree_name) 

887 

888 def _get_wrapped_value(self): 

889 n = self._name.string_name 

890 if n.startswith('__') and n.endswith('__') or self._name.api_type == 'function': 

891 inferred = self._name.infer() 

892 if inferred: 

893 return next(iter(inferred)) 

894 o, = self.inference_state.builtins_module.py__getattribute__('object') 

895 return o 

896 

897 value, = self._cls.execute_with_values() 

898 return value 

899 

900 def get_filters(self, origin_scope=None): 

901 yield DictFilter(dict( 

902 name=compiled.create_simple_object(self.inference_state, self._name.string_name).name, 

903 value=self._name, 

904 )) 

905 for f in self._get_wrapped_value().get_filters(): 

906 yield f 

907 

908 

909def tree_name_to_values(func): 

910 def wrapper(inference_state, context, tree_name): 

911 if tree_name.value == 'sep' and context.is_module() and context.py__name__() == 'os.path': 

912 return ValueSet({ 

913 compiled.create_simple_object(inference_state, os.path.sep), 

914 }) 

915 return func(inference_state, context, tree_name) 

916 return wrapper