Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jedi-0.19.2-py3.11.egg/jedi/inference/value/instance.py: 35%

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

353 statements  

1from abc import abstractproperty 

2 

3from jedi import debug 

4from jedi import settings 

5from jedi.inference import compiled 

6from jedi.inference.compiled.value import CompiledValueFilter 

7from jedi.inference.helpers import values_from_qualified_names, is_big_annoying_library 

8from jedi.inference.filters import AbstractFilter, AnonymousFunctionExecutionFilter 

9from jedi.inference.names import ValueName, TreeNameDefinition, ParamName, \ 

10 NameWrapper 

11from jedi.inference.base_value import Value, NO_VALUES, ValueSet, \ 

12 iterator_to_value_set, ValueWrapper 

13from jedi.inference.lazy_value import LazyKnownValue, LazyKnownValues 

14from jedi.inference.cache import inference_state_method_cache 

15from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper 

16from jedi.inference.value.function import \ 

17 FunctionValue, FunctionMixin, OverloadedFunctionValue, \ 

18 BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass 

19from jedi.inference.value.klass import ClassFilter 

20from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance 

21from jedi.parser_utils import function_is_staticmethod, function_is_classmethod 

22 

23 

24class InstanceExecutedParamName(ParamName): 

25 def __init__(self, instance, function_value, tree_name): 

26 super().__init__( 

27 function_value, tree_name, arguments=None) 

28 self._instance = instance 

29 

30 def infer(self): 

31 return ValueSet([self._instance]) 

32 

33 def matches_signature(self): 

34 return True 

35 

36 

37class AnonymousMethodExecutionFilter(AnonymousFunctionExecutionFilter): 

38 def __init__(self, instance, *args, **kwargs): 

39 super().__init__(*args, **kwargs) 

40 self._instance = instance 

41 

42 def _convert_param(self, param, name): 

43 if param.position_index == 0: 

44 if function_is_classmethod(self._function_value.tree_node): 

45 return InstanceExecutedParamName( 

46 self._instance.py__class__(), 

47 self._function_value, 

48 name 

49 ) 

50 elif not function_is_staticmethod(self._function_value.tree_node): 

51 return InstanceExecutedParamName( 

52 self._instance, 

53 self._function_value, 

54 name 

55 ) 

56 return super()._convert_param(param, name) 

57 

58 

59class AnonymousMethodExecutionContext(BaseFunctionExecutionContext): 

60 def __init__(self, instance, value): 

61 super().__init__(value) 

62 self.instance = instance 

63 

64 def get_filters(self, until_position=None, origin_scope=None): 

65 yield AnonymousMethodExecutionFilter( 

66 self.instance, self, self._value, 

67 until_position=until_position, 

68 origin_scope=origin_scope, 

69 ) 

70 

71 def get_param_names(self): 

72 param_names = list(self._value.get_param_names()) 

73 # set the self name 

74 param_names[0] = InstanceExecutedParamName( 

75 self.instance, 

76 self._value, 

77 param_names[0].tree_name 

78 ) 

79 return param_names 

80 

81 

82class MethodExecutionContext(FunctionExecutionContext): 

83 def __init__(self, instance, *args, **kwargs): 

84 super().__init__(*args, **kwargs) 

85 self.instance = instance 

86 

87 

88class AbstractInstanceValue(Value): 

89 api_type = 'instance' 

90 

91 def __init__(self, inference_state, parent_context, class_value): 

92 super().__init__(inference_state, parent_context) 

93 # Generated instances are classes that are just generated by self 

94 # (No arguments) used. 

95 self.class_value = class_value 

96 

97 def is_instance(self): 

98 return True 

99 

100 def get_qualified_names(self): 

101 return self.class_value.get_qualified_names() 

102 

103 def get_annotated_class_object(self): 

104 return self.class_value # This is the default. 

105 

106 def py__class__(self): 

107 return self.class_value 

108 

109 def py__bool__(self): 

110 # Signalize that we don't know about the bool type. 

111 return None 

112 

113 @abstractproperty 

114 def name(self): 

115 raise NotImplementedError 

116 

117 def get_signatures(self): 

118 call_funcs = self.py__getattribute__('__call__').py__get__(self, self.class_value) 

119 return [s.bind(self) for s in call_funcs.get_signatures()] 

120 

121 def get_function_slot_names(self, name): 

122 # Python classes don't look at the dictionary of the instance when 

123 # looking up `__call__`. This is something that has to do with Python's 

124 # internal slot system (note: not __slots__, but C slots). 

125 for filter in self.get_filters(include_self_names=False): 

126 names = filter.get(name) 

127 if names: 

128 return names 

129 return [] 

130 

131 def execute_function_slots(self, names, *inferred_args): 

132 return ValueSet.from_sets( 

133 name.infer().execute_with_values(*inferred_args) 

134 for name in names 

135 ) 

136 

137 def get_type_hint(self, add_class_info=True): 

138 return self.py__name__() 

139 

140 def py__getitem__(self, index_value_set, contextualized_node): 

141 names = self.get_function_slot_names('__getitem__') 

142 if not names: 

143 return super().py__getitem__( 

144 index_value_set, 

145 contextualized_node, 

146 ) 

147 

148 args = ValuesArguments([index_value_set]) 

149 return ValueSet.from_sets(name.infer().execute(args) for name in names) 

150 

151 def py__iter__(self, contextualized_node=None): 

152 iter_slot_names = self.get_function_slot_names('__iter__') 

153 if not iter_slot_names: 

154 return super().py__iter__(contextualized_node) 

155 

156 def iterate(): 

157 for generator in self.execute_function_slots(iter_slot_names): 

158 yield from generator.py__next__(contextualized_node) 

159 return iterate() 

160 

161 def __repr__(self): 

162 return "<%s of %s>" % (self.__class__.__name__, self.class_value) 

163 

164 

165class CompiledInstance(AbstractInstanceValue): 

166 # This is not really a compiled class, it's just an instance from a 

167 # compiled class. 

168 def __init__(self, inference_state, parent_context, class_value, arguments): 

169 super().__init__(inference_state, parent_context, class_value) 

170 self._arguments = arguments 

171 

172 def get_filters(self, origin_scope=None, include_self_names=True): 

173 class_value = self.get_annotated_class_object() 

174 class_filters = class_value.get_filters( 

175 origin_scope=origin_scope, 

176 is_instance=True, 

177 ) 

178 for f in class_filters: 

179 yield CompiledInstanceClassFilter(self, f) 

180 

181 @property 

182 def name(self): 

183 return compiled.CompiledValueName(self, self.class_value.name.string_name) 

184 

185 def is_stub(self): 

186 return False 

187 

188 

189class _BaseTreeInstance(AbstractInstanceValue): 

190 @property 

191 def array_type(self): 

192 name = self.class_value.py__name__() 

193 if name in ['list', 'set', 'dict'] \ 

194 and self.parent_context.get_root_context().is_builtins_module(): 

195 return name 

196 return None 

197 

198 @property 

199 def name(self): 

200 return ValueName(self, self.class_value.name.tree_name) 

201 

202 def get_filters(self, origin_scope=None, include_self_names=True): 

203 class_value = self.get_annotated_class_object() 

204 if include_self_names: 

205 for cls in class_value.py__mro__(): 

206 if not cls.is_compiled(): 

207 # In this case we're excluding compiled objects that are 

208 # not fake objects. It doesn't make sense for normal 

209 # compiled objects to search for self variables. 

210 yield SelfAttributeFilter(self, class_value, cls.as_context(), origin_scope) 

211 

212 class_filters = class_value.get_filters( 

213 origin_scope=origin_scope, 

214 is_instance=True, 

215 ) 

216 for f in class_filters: 

217 if isinstance(f, ClassFilter): 

218 yield InstanceClassFilter(self, f) 

219 elif isinstance(f, CompiledValueFilter): 

220 yield CompiledInstanceClassFilter(self, f) 

221 else: 

222 # Propably from the metaclass. 

223 yield f 

224 

225 @inference_state_method_cache() 

226 def create_instance_context(self, class_context, node): 

227 new = node 

228 while True: 

229 func_node = new 

230 new = new.search_ancestor('funcdef', 'classdef') 

231 if class_context.tree_node is new: 

232 func = FunctionValue.from_context(class_context, func_node) 

233 bound_method = BoundMethod(self, class_context, func) 

234 if func_node.name.value == '__init__': 

235 context = bound_method.as_context(self._arguments) 

236 else: 

237 context = bound_method.as_context() 

238 break 

239 return context.create_context(node) 

240 

241 def py__getattribute__alternatives(self, string_name): 

242 ''' 

243 Since nothing was inferred, now check the __getattr__ and 

244 __getattribute__ methods. Stubs don't need to be checked, because 

245 they don't contain any logic. 

246 ''' 

247 if self.is_stub(): 

248 return NO_VALUES 

249 

250 name = compiled.create_simple_object(self.inference_state, string_name) 

251 

252 # This is a little bit special. `__getattribute__` is in Python 

253 # executed before `__getattr__`. But: I know no use case, where 

254 # this could be practical and where Jedi would return wrong types. 

255 # If you ever find something, let me know! 

256 # We are inversing this, because a hand-crafted `__getattribute__` 

257 # could still call another hand-crafted `__getattr__`, but not the 

258 # other way around. 

259 if is_big_annoying_library(self.parent_context): 

260 return NO_VALUES 

261 names = (self.get_function_slot_names('__getattr__') 

262 or self.get_function_slot_names('__getattribute__')) 

263 return self.execute_function_slots(names, name) 

264 

265 def py__next__(self, contextualized_node=None): 

266 name = u'__next__' 

267 next_slot_names = self.get_function_slot_names(name) 

268 if next_slot_names: 

269 yield LazyKnownValues( 

270 self.execute_function_slots(next_slot_names) 

271 ) 

272 else: 

273 debug.warning('Instance has no __next__ function in %s.', self) 

274 

275 def py__call__(self, arguments): 

276 names = self.get_function_slot_names('__call__') 

277 if not names: 

278 # Means the Instance is not callable. 

279 return super().py__call__(arguments) 

280 

281 return ValueSet.from_sets(name.infer().execute(arguments) for name in names) 

282 

283 def py__get__(self, instance, class_value): 

284 """ 

285 obj may be None. 

286 """ 

287 # Arguments in __get__ descriptors are obj, class. 

288 # `method` is the new parent of the array, don't know if that's good. 

289 for cls in self.class_value.py__mro__(): 

290 result = cls.py__get__on_class(self, instance, class_value) 

291 if result is not NotImplemented: 

292 return result 

293 

294 names = self.get_function_slot_names('__get__') 

295 if names: 

296 if instance is None: 

297 instance = compiled.builtin_from_name(self.inference_state, 'None') 

298 return self.execute_function_slots(names, instance, class_value) 

299 else: 

300 return ValueSet([self]) 

301 

302 

303class TreeInstance(_BaseTreeInstance): 

304 def __init__(self, inference_state, parent_context, class_value, arguments): 

305 # I don't think that dynamic append lookups should happen here. That 

306 # sounds more like something that should go to py__iter__. 

307 if class_value.py__name__() in ['list', 'set'] \ 

308 and parent_context.get_root_context().is_builtins_module(): 

309 # compare the module path with the builtin name. 

310 if settings.dynamic_array_additions: 

311 arguments = get_dynamic_array_instance(self, arguments) 

312 

313 super().__init__(inference_state, parent_context, class_value) 

314 self._arguments = arguments 

315 self.tree_node = class_value.tree_node 

316 

317 # This can recurse, if the initialization of the class includes a reference 

318 # to itself. 

319 @inference_state_method_cache(default=None) 

320 def _get_annotated_class_object(self): 

321 from jedi.inference.gradual.annotation import py__annotations__, \ 

322 infer_type_vars_for_execution 

323 

324 args = InstanceArguments(self, self._arguments) 

325 for signature in self.class_value.py__getattribute__('__init__').get_signatures(): 

326 # Just take the first result, it should always be one, because we 

327 # control the typeshed code. 

328 funcdef = signature.value.tree_node 

329 if funcdef is None or funcdef.type != 'funcdef' \ 

330 or not signature.matches_signature(args): 

331 # First check if the signature even matches, if not we don't 

332 # need to infer anything. 

333 continue 

334 bound_method = BoundMethod(self, self.class_value.as_context(), signature.value) 

335 all_annotations = py__annotations__(funcdef) 

336 type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations) 

337 if type_var_dict: 

338 defined, = self.class_value.define_generics( 

339 infer_type_vars_for_execution(signature.value, args, all_annotations), 

340 ) 

341 debug.dbg('Inferred instance value as %s', defined, color='BLUE') 

342 return defined 

343 return None 

344 

345 def get_annotated_class_object(self): 

346 return self._get_annotated_class_object() or self.class_value 

347 

348 def get_key_values(self): 

349 values = NO_VALUES 

350 if self.array_type == 'dict': 

351 for i, (key, instance) in enumerate(self._arguments.unpack()): 

352 if key is None and i == 0: 

353 values |= ValueSet.from_sets( 

354 v.get_key_values() 

355 for v in instance.infer() 

356 if v.array_type == 'dict' 

357 ) 

358 if key: 

359 values |= ValueSet([compiled.create_simple_object( 

360 self.inference_state, 

361 key, 

362 )]) 

363 

364 return values 

365 

366 def py__simple_getitem__(self, index): 

367 if self.array_type == 'dict': 

368 # Logic for dict({'foo': bar}) and dict(foo=bar) 

369 # reversed, because: 

370 # >>> dict({'a': 1}, a=3) 

371 # {'a': 3} 

372 # TODO tuple initializations 

373 # >>> dict([('a', 4)]) 

374 # {'a': 4} 

375 for key, lazy_context in reversed(list(self._arguments.unpack())): 

376 if key is None: 

377 values = ValueSet.from_sets( 

378 dct_value.py__simple_getitem__(index) 

379 for dct_value in lazy_context.infer() 

380 if dct_value.array_type == 'dict' 

381 ) 

382 if values: 

383 return values 

384 else: 

385 if key == index: 

386 return lazy_context.infer() 

387 return super().py__simple_getitem__(index) 

388 

389 def __repr__(self): 

390 return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_value, 

391 self._arguments) 

392 

393 

394class AnonymousInstance(_BaseTreeInstance): 

395 _arguments = None 

396 

397 

398class CompiledInstanceName(NameWrapper): 

399 @iterator_to_value_set 

400 def infer(self): 

401 for result_value in self._wrapped_name.infer(): 

402 if result_value.api_type == 'function': 

403 yield CompiledBoundMethod(result_value) 

404 else: 

405 yield result_value 

406 

407 

408class CompiledInstanceClassFilter(AbstractFilter): 

409 def __init__(self, instance, f): 

410 self._instance = instance 

411 self._class_filter = f 

412 

413 def get(self, name): 

414 return self._convert(self._class_filter.get(name)) 

415 

416 def values(self): 

417 return self._convert(self._class_filter.values()) 

418 

419 def _convert(self, names): 

420 return [CompiledInstanceName(n) for n in names] 

421 

422 

423class BoundMethod(FunctionMixin, ValueWrapper): 

424 def __init__(self, instance, class_context, function): 

425 super().__init__(function) 

426 self.instance = instance 

427 self._class_context = class_context 

428 

429 def is_bound_method(self): 

430 return True 

431 

432 @property 

433 def name(self): 

434 return FunctionNameInClass( 

435 self._class_context, 

436 super().name 

437 ) 

438 

439 def py__class__(self): 

440 c, = values_from_qualified_names(self.inference_state, 'types', 'MethodType') 

441 return c 

442 

443 def _get_arguments(self, arguments): 

444 assert arguments is not None 

445 return InstanceArguments(self.instance, arguments) 

446 

447 def _as_context(self, arguments=None): 

448 if arguments is None: 

449 return AnonymousMethodExecutionContext(self.instance, self) 

450 

451 arguments = self._get_arguments(arguments) 

452 return MethodExecutionContext(self.instance, self, arguments) 

453 

454 def py__call__(self, arguments): 

455 if isinstance(self._wrapped_value, OverloadedFunctionValue): 

456 return self._wrapped_value.py__call__(self._get_arguments(arguments)) 

457 

458 function_execution = self.as_context(arguments) 

459 return function_execution.infer() 

460 

461 def get_signature_functions(self): 

462 return [ 

463 BoundMethod(self.instance, self._class_context, f) 

464 for f in self._wrapped_value.get_signature_functions() 

465 ] 

466 

467 def get_signatures(self): 

468 return [sig.bind(self) for sig in super().get_signatures()] 

469 

470 def __repr__(self): 

471 return '<%s: %s>' % (self.__class__.__name__, self._wrapped_value) 

472 

473 

474class CompiledBoundMethod(ValueWrapper): 

475 def is_bound_method(self): 

476 return True 

477 

478 def get_signatures(self): 

479 return [sig.bind(self) for sig in self._wrapped_value.get_signatures()] 

480 

481 

482class SelfName(TreeNameDefinition): 

483 """ 

484 This name calculates the parent_context lazily. 

485 """ 

486 def __init__(self, instance, class_context, tree_name): 

487 self._instance = instance 

488 self.class_context = class_context 

489 self.tree_name = tree_name 

490 

491 @property 

492 def parent_context(self): 

493 return self._instance.create_instance_context(self.class_context, self.tree_name) 

494 

495 def get_defining_qualified_value(self): 

496 return self._instance 

497 

498 def infer(self): 

499 stmt = self.tree_name.search_ancestor('expr_stmt') 

500 if stmt is not None: 

501 if stmt.children[1].type == "annassign": 

502 from jedi.inference.gradual.annotation import infer_annotation 

503 values = infer_annotation( 

504 self.parent_context, stmt.children[1].children[1] 

505 ).execute_annotation() 

506 if values: 

507 return values 

508 return super().infer() 

509 

510 

511class LazyInstanceClassName(NameWrapper): 

512 def __init__(self, instance, class_member_name): 

513 super().__init__(class_member_name) 

514 self._instance = instance 

515 

516 @iterator_to_value_set 

517 def infer(self): 

518 for result_value in self._wrapped_name.infer(): 

519 yield from result_value.py__get__(self._instance, self._instance.py__class__()) 

520 

521 def get_signatures(self): 

522 return self.infer().get_signatures() 

523 

524 def get_defining_qualified_value(self): 

525 return self._instance 

526 

527 

528class InstanceClassFilter(AbstractFilter): 

529 """ 

530 This filter is special in that it uses the class filter and wraps the 

531 resulting names in LazyInstanceClassName. The idea is that the class name 

532 filtering can be very flexible and always be reflected in instances. 

533 """ 

534 def __init__(self, instance, class_filter): 

535 self._instance = instance 

536 self._class_filter = class_filter 

537 

538 def get(self, name): 

539 return self._convert(self._class_filter.get(name)) 

540 

541 def values(self): 

542 return self._convert(self._class_filter.values()) 

543 

544 def _convert(self, names): 

545 return [ 

546 LazyInstanceClassName(self._instance, n) 

547 for n in names 

548 ] 

549 

550 def __repr__(self): 

551 return '<%s for %s>' % (self.__class__.__name__, self._class_filter) 

552 

553 

554class SelfAttributeFilter(ClassFilter): 

555 """ 

556 This class basically filters all the use cases where `self.*` was assigned. 

557 """ 

558 def __init__(self, instance, instance_class, node_context, origin_scope): 

559 super().__init__( 

560 class_value=instance_class, 

561 node_context=node_context, 

562 origin_scope=origin_scope, 

563 is_instance=True, 

564 ) 

565 self._instance = instance 

566 

567 def _filter(self, names): 

568 start, end = self._parser_scope.start_pos, self._parser_scope.end_pos 

569 names = [n for n in names if start < n.start_pos < end] 

570 return self._filter_self_names(names) 

571 

572 def _filter_self_names(self, names): 

573 for name in names: 

574 trailer = name.parent 

575 if trailer.type == 'trailer' \ 

576 and len(trailer.parent.children) == 2 \ 

577 and trailer.children[0] == '.': 

578 if name.is_definition() and self._access_possible(name): 

579 # TODO filter non-self assignments instead of this bad 

580 # filter. 

581 if self._is_in_right_scope(trailer.parent.children[0], name): 

582 yield name 

583 

584 def _is_in_right_scope(self, self_name, name): 

585 self_context = self._node_context.create_context(self_name) 

586 names = self_context.goto(self_name, position=self_name.start_pos) 

587 return any( 

588 n.api_type == 'param' 

589 and n.tree_name.get_definition().position_index == 0 

590 and n.parent_context.tree_node is self._parser_scope 

591 for n in names 

592 ) 

593 

594 def _convert_names(self, names): 

595 return [SelfName(self._instance, self._node_context, name) for name in names] 

596 

597 def _check_flows(self, names): 

598 return names 

599 

600 

601class InstanceArguments(TreeArgumentsWrapper): 

602 def __init__(self, instance, arguments): 

603 super().__init__(arguments) 

604 self.instance = instance 

605 

606 def unpack(self, func=None): 

607 yield None, LazyKnownValue(self.instance) 

608 yield from self._wrapped_arguments.unpack(func)