Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/inference/value/instance.py: 36%

353 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1from abc import abstractproperty 

2 

3from parso.tree import search_ancestor 

4 

5from jedi import debug 

6from jedi import settings 

7from jedi.inference import compiled 

8from jedi.inference.compiled.value import CompiledValueFilter 

9from jedi.inference.helpers import values_from_qualified_names, is_big_annoying_library 

10from jedi.inference.filters import AbstractFilter, AnonymousFunctionExecutionFilter 

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

12 NameWrapper 

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

14 iterator_to_value_set, ValueWrapper 

15from jedi.inference.lazy_value import LazyKnownValue, LazyKnownValues 

16from jedi.inference.cache import inference_state_method_cache 

17from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper 

18from jedi.inference.value.function import \ 

19 FunctionValue, FunctionMixin, OverloadedFunctionValue, \ 

20 BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass 

21from jedi.inference.value.klass import ClassFilter 

22from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance 

23from jedi.parser_utils import function_is_staticmethod, function_is_classmethod 

24 

25 

26class InstanceExecutedParamName(ParamName): 

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

28 super().__init__( 

29 function_value, tree_name, arguments=None) 

30 self._instance = instance 

31 

32 def infer(self): 

33 return ValueSet([self._instance]) 

34 

35 def matches_signature(self): 

36 return True 

37 

38 

39class AnonymousMethodExecutionFilter(AnonymousFunctionExecutionFilter): 

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

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

42 self._instance = instance 

43 

44 def _convert_param(self, param, name): 

45 if param.position_index == 0: 

46 if function_is_classmethod(self._function_value.tree_node): 

47 return InstanceExecutedParamName( 

48 self._instance.py__class__(), 

49 self._function_value, 

50 name 

51 ) 

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

53 return InstanceExecutedParamName( 

54 self._instance, 

55 self._function_value, 

56 name 

57 ) 

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

59 

60 

61class AnonymousMethodExecutionContext(BaseFunctionExecutionContext): 

62 def __init__(self, instance, value): 

63 super().__init__(value) 

64 self.instance = instance 

65 

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

67 yield AnonymousMethodExecutionFilter( 

68 self.instance, self, self._value, 

69 until_position=until_position, 

70 origin_scope=origin_scope, 

71 ) 

72 

73 def get_param_names(self): 

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

75 # set the self name 

76 param_names[0] = InstanceExecutedParamName( 

77 self.instance, 

78 self._value, 

79 param_names[0].tree_name 

80 ) 

81 return param_names 

82 

83 

84class MethodExecutionContext(FunctionExecutionContext): 

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

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

87 self.instance = instance 

88 

89 

90class AbstractInstanceValue(Value): 

91 api_type = 'instance' 

92 

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

94 super().__init__(inference_state, parent_context) 

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

96 # (No arguments) used. 

97 self.class_value = class_value 

98 

99 def is_instance(self): 

100 return True 

101 

102 def get_qualified_names(self): 

103 return self.class_value.get_qualified_names() 

104 

105 def get_annotated_class_object(self): 

106 return self.class_value # This is the default. 

107 

108 def py__class__(self): 

109 return self.class_value 

110 

111 def py__bool__(self): 

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

113 return None 

114 

115 @abstractproperty 

116 def name(self): 

117 raise NotImplementedError 

118 

119 def get_signatures(self): 

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

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

122 

123 def get_function_slot_names(self, name): 

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

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

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

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

128 names = filter.get(name) 

129 if names: 

130 return names 

131 return [] 

132 

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

134 return ValueSet.from_sets( 

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

136 for name in names 

137 ) 

138 

139 def get_type_hint(self, add_class_info=True): 

140 return self.py__name__() 

141 

142 def py__getitem__(self, index_value_set, contextualized_node): 

143 names = self.get_function_slot_names('__getitem__') 

144 if not names: 

145 return super().py__getitem__( 

146 index_value_set, 

147 contextualized_node, 

148 ) 

149 

150 args = ValuesArguments([index_value_set]) 

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

152 

153 def py__iter__(self, contextualized_node=None): 

154 iter_slot_names = self.get_function_slot_names('__iter__') 

155 if not iter_slot_names: 

156 return super().py__iter__(contextualized_node) 

157 

158 def iterate(): 

159 for generator in self.execute_function_slots(iter_slot_names): 

160 yield from generator.py__next__(contextualized_node) 

161 return iterate() 

162 

163 def __repr__(self): 

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

165 

166 

167class CompiledInstance(AbstractInstanceValue): 

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

169 # compiled class. 

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

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

172 self._arguments = arguments 

173 

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

175 class_value = self.get_annotated_class_object() 

176 class_filters = class_value.get_filters( 

177 origin_scope=origin_scope, 

178 is_instance=True, 

179 ) 

180 for f in class_filters: 

181 yield CompiledInstanceClassFilter(self, f) 

182 

183 @property 

184 def name(self): 

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

186 

187 def is_stub(self): 

188 return False 

189 

190 

191class _BaseTreeInstance(AbstractInstanceValue): 

192 @property 

193 def array_type(self): 

194 name = self.class_value.py__name__() 

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

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

197 return name 

198 return None 

199 

200 @property 

201 def name(self): 

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

203 

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

205 class_value = self.get_annotated_class_object() 

206 if include_self_names: 

207 for cls in class_value.py__mro__(): 

208 if not cls.is_compiled(): 

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

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

211 # compiled objects to search for self variables. 

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

213 

214 class_filters = class_value.get_filters( 

215 origin_scope=origin_scope, 

216 is_instance=True, 

217 ) 

218 for f in class_filters: 

219 if isinstance(f, ClassFilter): 

220 yield InstanceClassFilter(self, f) 

221 elif isinstance(f, CompiledValueFilter): 

222 yield CompiledInstanceClassFilter(self, f) 

223 else: 

224 # Propably from the metaclass. 

225 yield f 

226 

227 @inference_state_method_cache() 

228 def create_instance_context(self, class_context, node): 

229 new = node 

230 while True: 

231 func_node = new 

232 new = search_ancestor(new, 'funcdef', 'classdef') 

233 if class_context.tree_node is new: 

234 func = FunctionValue.from_context(class_context, func_node) 

235 bound_method = BoundMethod(self, class_context, func) 

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

237 context = bound_method.as_context(self._arguments) 

238 else: 

239 context = bound_method.as_context() 

240 break 

241 return context.create_context(node) 

242 

243 def py__getattribute__alternatives(self, string_name): 

244 ''' 

245 Since nothing was inferred, now check the __getattr__ and 

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

247 they don't contain any logic. 

248 ''' 

249 if self.is_stub(): 

250 return NO_VALUES 

251 

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

253 

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

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

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

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

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

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

260 # other way around. 

261 if is_big_annoying_library(self.parent_context): 

262 return NO_VALUES 

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

264 or self.get_function_slot_names('__getattribute__')) 

265 return self.execute_function_slots(names, name) 

266 

267 def py__next__(self, contextualized_node=None): 

268 name = u'__next__' 

269 next_slot_names = self.get_function_slot_names(name) 

270 if next_slot_names: 

271 yield LazyKnownValues( 

272 self.execute_function_slots(next_slot_names) 

273 ) 

274 else: 

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

276 

277 def py__call__(self, arguments): 

278 names = self.get_function_slot_names('__call__') 

279 if not names: 

280 # Means the Instance is not callable. 

281 return super().py__call__(arguments) 

282 

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

284 

285 def py__get__(self, instance, class_value): 

286 """ 

287 obj may be None. 

288 """ 

289 # Arguments in __get__ descriptors are obj, class. 

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

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

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

293 if result is not NotImplemented: 

294 return result 

295 

296 names = self.get_function_slot_names('__get__') 

297 if names: 

298 if instance is None: 

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

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

301 else: 

302 return ValueSet([self]) 

303 

304 

305class TreeInstance(_BaseTreeInstance): 

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

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

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

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

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

311 # compare the module path with the builtin name. 

312 if settings.dynamic_array_additions: 

313 arguments = get_dynamic_array_instance(self, arguments) 

314 

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

316 self._arguments = arguments 

317 self.tree_node = class_value.tree_node 

318 

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

320 # to itself. 

321 @inference_state_method_cache(default=None) 

322 def _get_annotated_class_object(self): 

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

324 infer_type_vars_for_execution 

325 

326 args = InstanceArguments(self, self._arguments) 

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

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

329 # control the typeshed code. 

330 funcdef = signature.value.tree_node 

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

332 or not signature.matches_signature(args): 

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

334 # need to infer anything. 

335 continue 

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

337 all_annotations = py__annotations__(funcdef) 

338 type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations) 

339 if type_var_dict: 

340 defined, = self.class_value.define_generics( 

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

342 ) 

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

344 return defined 

345 return None 

346 

347 def get_annotated_class_object(self): 

348 return self._get_annotated_class_object() or self.class_value 

349 

350 def get_key_values(self): 

351 values = NO_VALUES 

352 if self.array_type == 'dict': 

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

354 if key is None and i == 0: 

355 values |= ValueSet.from_sets( 

356 v.get_key_values() 

357 for v in instance.infer() 

358 if v.array_type == 'dict' 

359 ) 

360 if key: 

361 values |= ValueSet([compiled.create_simple_object( 

362 self.inference_state, 

363 key, 

364 )]) 

365 

366 return values 

367 

368 def py__simple_getitem__(self, index): 

369 if self.array_type == 'dict': 

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

371 # reversed, because: 

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

373 # {'a': 3} 

374 # TODO tuple initializations 

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

376 # {'a': 4} 

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

378 if key is None: 

379 values = ValueSet.from_sets( 

380 dct_value.py__simple_getitem__(index) 

381 for dct_value in lazy_context.infer() 

382 if dct_value.array_type == 'dict' 

383 ) 

384 if values: 

385 return values 

386 else: 

387 if key == index: 

388 return lazy_context.infer() 

389 return super().py__simple_getitem__(index) 

390 

391 def __repr__(self): 

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

393 self._arguments) 

394 

395 

396class AnonymousInstance(_BaseTreeInstance): 

397 _arguments = None 

398 

399 

400class CompiledInstanceName(NameWrapper): 

401 @iterator_to_value_set 

402 def infer(self): 

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

404 if result_value.api_type == 'function': 

405 yield CompiledBoundMethod(result_value) 

406 else: 

407 yield result_value 

408 

409 

410class CompiledInstanceClassFilter(AbstractFilter): 

411 def __init__(self, instance, f): 

412 self._instance = instance 

413 self._class_filter = f 

414 

415 def get(self, name): 

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

417 

418 def values(self): 

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

420 

421 def _convert(self, names): 

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

423 

424 

425class BoundMethod(FunctionMixin, ValueWrapper): 

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

427 super().__init__(function) 

428 self.instance = instance 

429 self._class_context = class_context 

430 

431 def is_bound_method(self): 

432 return True 

433 

434 @property 

435 def name(self): 

436 return FunctionNameInClass( 

437 self._class_context, 

438 super().name 

439 ) 

440 

441 def py__class__(self): 

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

443 return c 

444 

445 def _get_arguments(self, arguments): 

446 assert arguments is not None 

447 return InstanceArguments(self.instance, arguments) 

448 

449 def _as_context(self, arguments=None): 

450 if arguments is None: 

451 return AnonymousMethodExecutionContext(self.instance, self) 

452 

453 arguments = self._get_arguments(arguments) 

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

455 

456 def py__call__(self, arguments): 

457 if isinstance(self._wrapped_value, OverloadedFunctionValue): 

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

459 

460 function_execution = self.as_context(arguments) 

461 return function_execution.infer() 

462 

463 def get_signature_functions(self): 

464 return [ 

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

466 for f in self._wrapped_value.get_signature_functions() 

467 ] 

468 

469 def get_signatures(self): 

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

471 

472 def __repr__(self): 

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

474 

475 

476class CompiledBoundMethod(ValueWrapper): 

477 def is_bound_method(self): 

478 return True 

479 

480 def get_signatures(self): 

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

482 

483 

484class SelfName(TreeNameDefinition): 

485 """ 

486 This name calculates the parent_context lazily. 

487 """ 

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

489 self._instance = instance 

490 self.class_context = class_context 

491 self.tree_name = tree_name 

492 

493 @property 

494 def parent_context(self): 

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

496 

497 def get_defining_qualified_value(self): 

498 return self._instance 

499 

500 def infer(self): 

501 stmt = search_ancestor(self.tree_name, 'expr_stmt') 

502 if stmt is not None: 

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

504 from jedi.inference.gradual.annotation import infer_annotation 

505 values = infer_annotation( 

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

507 ).execute_annotation() 

508 if values: 

509 return values 

510 return super().infer() 

511 

512 

513class LazyInstanceClassName(NameWrapper): 

514 def __init__(self, instance, class_member_name): 

515 super().__init__(class_member_name) 

516 self._instance = instance 

517 

518 @iterator_to_value_set 

519 def infer(self): 

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

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

522 

523 def get_signatures(self): 

524 return self.infer().get_signatures() 

525 

526 def get_defining_qualified_value(self): 

527 return self._instance 

528 

529 

530class InstanceClassFilter(AbstractFilter): 

531 """ 

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

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

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

535 """ 

536 def __init__(self, instance, class_filter): 

537 self._instance = instance 

538 self._class_filter = class_filter 

539 

540 def get(self, name): 

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

542 

543 def values(self): 

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

545 

546 def _convert(self, names): 

547 return [ 

548 LazyInstanceClassName(self._instance, n) 

549 for n in names 

550 ] 

551 

552 def __repr__(self): 

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

554 

555 

556class SelfAttributeFilter(ClassFilter): 

557 """ 

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

559 """ 

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

561 super().__init__( 

562 class_value=instance_class, 

563 node_context=node_context, 

564 origin_scope=origin_scope, 

565 is_instance=True, 

566 ) 

567 self._instance = instance 

568 

569 def _filter(self, names): 

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

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

572 return self._filter_self_names(names) 

573 

574 def _filter_self_names(self, names): 

575 for name in names: 

576 trailer = name.parent 

577 if trailer.type == 'trailer' \ 

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

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

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

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

582 # filter. 

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

584 yield name 

585 

586 def _is_in_right_scope(self, self_name, name): 

587 self_context = self._node_context.create_context(self_name) 

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

589 return any( 

590 n.api_type == 'param' 

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

592 and n.parent_context.tree_node is self._parser_scope 

593 for n in names 

594 ) 

595 

596 def _convert_names(self, names): 

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

598 

599 def _check_flows(self, names): 

600 return names 

601 

602 

603class InstanceArguments(TreeArgumentsWrapper): 

604 def __init__(self, instance, arguments): 

605 super().__init__(arguments) 

606 self.instance = instance 

607 

608 def unpack(self, func=None): 

609 yield None, LazyKnownValue(self.instance) 

610 yield from self._wrapped_arguments.unpack(func)