Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jedi/api/completion.py: 14%

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

396 statements  

1import re 

2from textwrap import dedent 

3from inspect import Parameter 

4 

5from parso.python.token import PythonTokenTypes 

6from parso.python import tree 

7from parso.tree import search_ancestor, Leaf 

8from parso import split_lines 

9 

10from jedi import debug 

11from jedi import settings 

12from jedi.api import classes 

13from jedi.api import helpers 

14from jedi.api import keywords 

15from jedi.api.strings import complete_dict 

16from jedi.api.file_name import complete_file_name 

17from jedi.inference import imports 

18from jedi.inference.base_value import ValueSet 

19from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names 

20from jedi.inference.context import get_global_filters 

21from jedi.inference.value import TreeInstance 

22from jedi.inference.docstring_utils import DocstringModule 

23from jedi.inference.names import ParamNameWrapper, SubModuleName 

24from jedi.inference.gradual.conversion import convert_values, convert_names 

25from jedi.parser_utils import cut_value_at_position 

26from jedi.plugins import plugin_manager 

27 

28 

29class ParamNameWithEquals(ParamNameWrapper): 

30 def get_public_name(self): 

31 return self.string_name + '=' 

32 

33 

34def _get_signature_param_names(signatures, positional_count, used_kwargs): 

35 # Add named params 

36 for call_sig in signatures: 

37 for i, p in enumerate(call_sig.params): 

38 kind = p.kind 

39 if i < positional_count and kind == Parameter.POSITIONAL_OR_KEYWORD: 

40 continue 

41 if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) \ 

42 and p.name not in used_kwargs: 

43 yield ParamNameWithEquals(p._name) 

44 

45 

46def _must_be_kwarg(signatures, positional_count, used_kwargs): 

47 if used_kwargs: 

48 return True 

49 

50 must_be_kwarg = True 

51 for signature in signatures: 

52 for i, p in enumerate(signature.params): 

53 kind = p.kind 

54 if kind is Parameter.VAR_POSITIONAL: 

55 # In case there were not already kwargs, the next param can 

56 # always be a normal argument. 

57 return False 

58 

59 if i >= positional_count and kind in (Parameter.POSITIONAL_OR_KEYWORD, 

60 Parameter.POSITIONAL_ONLY): 

61 must_be_kwarg = False 

62 break 

63 if not must_be_kwarg: 

64 break 

65 return must_be_kwarg 

66 

67 

68def filter_names(inference_state, completion_names, stack, like_name, fuzzy, 

69 imported_names, cached_name): 

70 comp_dct = set() 

71 if settings.case_insensitive_completion: 

72 like_name = like_name.lower() 

73 for name in completion_names: 

74 string = name.string_name 

75 if string in imported_names and string != like_name: 

76 continue 

77 if settings.case_insensitive_completion: 

78 string = string.lower() 

79 if helpers.match(string, like_name, fuzzy=fuzzy): 

80 new = classes.Completion( 

81 inference_state, 

82 name, 

83 stack, 

84 len(like_name), 

85 is_fuzzy=fuzzy, 

86 cached_name=cached_name, 

87 ) 

88 k = (new.name, new.complete) # key 

89 if k not in comp_dct: 

90 comp_dct.add(k) 

91 tree_name = name.tree_name 

92 if tree_name is not None: 

93 definition = tree_name.get_definition() 

94 if definition is not None and definition.type == 'del_stmt': 

95 continue 

96 yield new 

97 

98 

99def _remove_duplicates(completions, other_completions): 

100 names = {d.name for d in other_completions} 

101 return [c for c in completions if c.name not in names] 

102 

103 

104def get_user_context(module_context, position): 

105 """ 

106 Returns the scope in which the user resides. This includes flows. 

107 """ 

108 leaf = module_context.tree_node.get_leaf_for_position(position, include_prefixes=True) 

109 return module_context.create_context(leaf) 

110 

111 

112def get_flow_scope_node(module_node, position): 

113 node = module_node.get_leaf_for_position(position, include_prefixes=True) 

114 while not isinstance(node, (tree.Scope, tree.Flow)): 

115 node = node.parent 

116 

117 return node 

118 

119 

120@plugin_manager.decorate() 

121def complete_param_names(context, function_name, decorator_nodes): 

122 # Basically there's no way to do param completion. The plugins are 

123 # responsible for this. 

124 return [] 

125 

126 

127class Completion: 

128 def __init__(self, inference_state, module_context, code_lines, position, 

129 signatures_callback, fuzzy=False): 

130 self._inference_state = inference_state 

131 self._module_context = module_context 

132 self._module_node = module_context.tree_node 

133 self._code_lines = code_lines 

134 

135 # The first step of completions is to get the name 

136 self._like_name = helpers.get_on_completion_name(self._module_node, code_lines, position) 

137 # The actual cursor position is not what we need to calculate 

138 # everything. We want the start of the name we're on. 

139 self._original_position = position 

140 self._signatures_callback = signatures_callback 

141 

142 self._fuzzy = fuzzy 

143 

144 # Return list of completions in this order: 

145 # - Beginning with what user is typing 

146 # - Public (alphabet) 

147 # - Private ("_xxx") 

148 # - Dunder ("__xxx") 

149 def complete(self): 

150 leaf = self._module_node.get_leaf_for_position( 

151 self._original_position, 

152 include_prefixes=True 

153 ) 

154 string, start_leaf, quote = _extract_string_while_in_string(leaf, self._original_position) 

155 

156 prefixed_completions = complete_dict( 

157 self._module_context, 

158 self._code_lines, 

159 start_leaf or leaf, 

160 self._original_position, 

161 None if string is None else quote + string, 

162 fuzzy=self._fuzzy, 

163 ) 

164 

165 if string is not None and not prefixed_completions: 

166 prefixed_completions = list(complete_file_name( 

167 self._inference_state, self._module_context, start_leaf, quote, string, 

168 self._like_name, self._signatures_callback, 

169 self._code_lines, self._original_position, 

170 self._fuzzy 

171 )) 

172 if string is not None: 

173 if not prefixed_completions and '\n' in string: 

174 # Complete only multi line strings 

175 prefixed_completions = self._complete_in_string(start_leaf, string) 

176 return prefixed_completions 

177 

178 cached_name, completion_names = self._complete_python(leaf) 

179 

180 imported_names = [] 

181 if leaf.parent is not None and leaf.parent.type in ['import_as_names', 'dotted_as_names']: 

182 imported_names.extend(extract_imported_names(leaf.parent)) 

183 

184 completions = list(filter_names(self._inference_state, completion_names, 

185 self.stack, self._like_name, 

186 self._fuzzy, imported_names, cached_name=cached_name)) 

187 

188 return ( 

189 # Removing duplicates mostly to remove False/True/None duplicates. 

190 _remove_duplicates(prefixed_completions, completions) 

191 + sorted(completions, key=lambda x: (not x.name.startswith(self._like_name), 

192 x.name.startswith('__'), 

193 x.name.startswith('_'), 

194 x.name.lower())) 

195 ) 

196 

197 def _complete_python(self, leaf): 

198 """ 

199 Analyzes the current context of a completion and decides what to 

200 return. 

201 

202 Technically this works by generating a parser stack and analysing the 

203 current stack for possible grammar nodes. 

204 

205 Possible enhancements: 

206 - global/nonlocal search global 

207 - yield from / raise from <- could be only exceptions/generators 

208 - In args: */**: no completion 

209 - In params (also lambda): no completion before = 

210 """ 

211 grammar = self._inference_state.grammar 

212 self.stack = stack = None 

213 self._position = ( 

214 self._original_position[0], 

215 self._original_position[1] - len(self._like_name) 

216 ) 

217 cached_name = None 

218 

219 try: 

220 self.stack = stack = helpers.get_stack_at_position( 

221 grammar, self._code_lines, leaf, self._position 

222 ) 

223 except helpers.OnErrorLeaf as e: 

224 value = e.error_leaf.value 

225 if value == '.': 

226 # After ErrorLeaf's that are dots, we will not do any 

227 # completions since this probably just confuses the user. 

228 return cached_name, [] 

229 

230 # If we don't have a value, just use global completion. 

231 return cached_name, self._complete_global_scope() 

232 

233 allowed_transitions = \ 

234 list(stack._allowed_transition_names_and_token_types()) 

235 

236 if 'if' in allowed_transitions: 

237 leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) 

238 previous_leaf = leaf.get_previous_leaf() 

239 

240 indent = self._position[1] 

241 if not (leaf.start_pos <= self._position <= leaf.end_pos): 

242 indent = leaf.start_pos[1] 

243 

244 if previous_leaf is not None: 

245 stmt = previous_leaf 

246 while True: 

247 stmt = search_ancestor( 

248 stmt, 'if_stmt', 'for_stmt', 'while_stmt', 'try_stmt', 

249 'error_node', 

250 ) 

251 if stmt is None: 

252 break 

253 

254 type_ = stmt.type 

255 if type_ == 'error_node': 

256 first = stmt.children[0] 

257 if isinstance(first, Leaf): 

258 type_ = first.value + '_stmt' 

259 # Compare indents 

260 if stmt.start_pos[1] == indent: 

261 if type_ == 'if_stmt': 

262 allowed_transitions += ['elif', 'else'] 

263 elif type_ == 'try_stmt': 

264 allowed_transitions += ['except', 'finally', 'else'] 

265 elif type_ == 'for_stmt': 

266 allowed_transitions.append('else') 

267 

268 completion_names = [] 

269 

270 kwargs_only = False 

271 if any(t in allowed_transitions for t in (PythonTokenTypes.NAME, 

272 PythonTokenTypes.INDENT)): 

273 # This means that we actually have to do type inference. 

274 

275 nonterminals = [stack_node.nonterminal for stack_node in stack] 

276 

277 nodes = _gather_nodes(stack) 

278 if nodes and nodes[-1] in ('as', 'def', 'class'): 

279 # No completions for ``with x as foo`` and ``import x as foo``. 

280 # Also true for defining names as a class or function. 

281 return cached_name, list(self._complete_inherited(is_function=True)) 

282 elif "import_stmt" in nonterminals: 

283 level, names = parse_dotted_names(nodes, "import_from" in nonterminals) 

284 

285 only_modules = not ("import_from" in nonterminals and 'import' in nodes) 

286 completion_names += self._get_importer_names( 

287 names, 

288 level, 

289 only_modules=only_modules, 

290 ) 

291 elif nonterminals[-1] in ('trailer', 'dotted_name') and nodes[-1] == '.': 

292 dot = self._module_node.get_leaf_for_position(self._position) 

293 if dot.type == "endmarker": 

294 # This is a bit of a weird edge case, maybe we can somehow 

295 # generalize this. 

296 dot = leaf.get_previous_leaf() 

297 cached_name, n = self._complete_trailer(dot.get_previous_leaf()) 

298 completion_names += n 

299 elif self._is_parameter_completion(): 

300 completion_names += self._complete_params(leaf) 

301 else: 

302 # Apparently this looks like it's good enough to filter most cases 

303 # so that signature completions don't randomly appear. 

304 # To understand why this works, three things are important: 

305 # 1. trailer with a `,` in it is either a subscript or an arglist. 

306 # 2. If there's no `,`, it's at the start and only signatures start 

307 # with `(`. Other trailers could start with `.` or `[`. 

308 # 3. Decorators are very primitive and have an optional `(` with 

309 # optional arglist in them. 

310 if nodes[-1] in ['(', ','] \ 

311 and nonterminals[-1] in ('trailer', 'arglist', 'decorator'): 

312 signatures = self._signatures_callback(*self._position) 

313 if signatures: 

314 call_details = signatures[0]._call_details 

315 used_kwargs = list(call_details.iter_used_keyword_arguments()) 

316 positional_count = call_details.count_positional_arguments() 

317 

318 completion_names += _get_signature_param_names( 

319 signatures, 

320 positional_count, 

321 used_kwargs, 

322 ) 

323 

324 kwargs_only = _must_be_kwarg(signatures, positional_count, used_kwargs) 

325 

326 if not kwargs_only: 

327 completion_names += self._complete_global_scope() 

328 completion_names += self._complete_inherited(is_function=False) 

329 

330 if not kwargs_only: 

331 current_line = self._code_lines[self._position[0] - 1][:self._position[1]] 

332 completion_names += self._complete_keywords( 

333 allowed_transitions, 

334 only_values=not (not current_line or current_line[-1] in ' \t.;' 

335 and current_line[-3:] != '...') 

336 ) 

337 

338 return cached_name, completion_names 

339 

340 def _is_parameter_completion(self): 

341 tos = self.stack[-1] 

342 if tos.nonterminal == 'lambdef' and len(tos.nodes) == 1: 

343 # We are at the position `lambda `, where basically the next node 

344 # is a param. 

345 return True 

346 if tos.nonterminal in 'parameters': 

347 # Basically we are at the position `foo(`, there's nothing there 

348 # yet, so we have no `typedargslist`. 

349 return True 

350 # var args is for lambdas and typed args for normal functions 

351 return tos.nonterminal in ('typedargslist', 'varargslist') and tos.nodes[-1] == ',' 

352 

353 def _complete_params(self, leaf): 

354 stack_node = self.stack[-2] 

355 if stack_node.nonterminal == 'parameters': 

356 stack_node = self.stack[-3] 

357 if stack_node.nonterminal == 'funcdef': 

358 context = get_user_context(self._module_context, self._position) 

359 node = search_ancestor(leaf, 'error_node', 'funcdef') 

360 if node is not None: 

361 if node.type == 'error_node': 

362 n = node.children[0] 

363 if n.type == 'decorators': 

364 decorators = n.children 

365 elif n.type == 'decorator': 

366 decorators = [n] 

367 else: 

368 decorators = [] 

369 else: 

370 decorators = node.get_decorators() 

371 function_name = stack_node.nodes[1] 

372 

373 return complete_param_names(context, function_name.value, decorators) 

374 return [] 

375 

376 def _complete_keywords(self, allowed_transitions, only_values): 

377 for k in allowed_transitions: 

378 if isinstance(k, str) and k.isalpha(): 

379 if not only_values or k in ('True', 'False', 'None'): 

380 yield keywords.KeywordName(self._inference_state, k) 

381 

382 def _complete_global_scope(self): 

383 context = get_user_context(self._module_context, self._position) 

384 debug.dbg('global completion scope: %s', context) 

385 flow_scope_node = get_flow_scope_node(self._module_node, self._position) 

386 filters = get_global_filters( 

387 context, 

388 self._position, 

389 flow_scope_node 

390 ) 

391 completion_names = [] 

392 for filter in filters: 

393 completion_names += filter.values() 

394 return completion_names 

395 

396 def _complete_trailer(self, previous_leaf): 

397 inferred_context = self._module_context.create_context(previous_leaf) 

398 values = infer_call_of_leaf(inferred_context, previous_leaf) 

399 debug.dbg('trailer completion values: %s', values, color='MAGENTA') 

400 

401 # The cached name simply exists to make speed optimizations for certain 

402 # modules. 

403 cached_name = None 

404 if len(values) == 1: 

405 v, = values 

406 if v.is_module(): 

407 if len(v.string_names) == 1: 

408 module_name = v.string_names[0] 

409 if module_name in ('numpy', 'tensorflow', 'matplotlib', 'pandas'): 

410 cached_name = module_name 

411 

412 return cached_name, self._complete_trailer_for_values(values) 

413 

414 def _complete_trailer_for_values(self, values): 

415 user_context = get_user_context(self._module_context, self._position) 

416 

417 return complete_trailer(user_context, values) 

418 

419 def _get_importer_names(self, names, level=0, only_modules=True): 

420 names = [n.value for n in names] 

421 i = imports.Importer(self._inference_state, names, self._module_context, level) 

422 return i.completion_names(self._inference_state, only_modules=only_modules) 

423 

424 def _complete_inherited(self, is_function=True): 

425 """ 

426 Autocomplete inherited methods when overriding in child class. 

427 """ 

428 leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) 

429 cls = tree.search_ancestor(leaf, 'classdef') 

430 if cls is None: 

431 return 

432 

433 # Complete the methods that are defined in the super classes. 

434 class_value = self._module_context.create_value(cls) 

435 

436 if cls.start_pos[1] >= leaf.start_pos[1]: 

437 return 

438 

439 filters = class_value.get_filters(is_instance=True) 

440 # The first dict is the dictionary of class itself. 

441 next(filters) 

442 for filter in filters: 

443 for name in filter.values(): 

444 # TODO we should probably check here for properties 

445 if (name.api_type == 'function') == is_function: 

446 yield name 

447 

448 def _complete_in_string(self, start_leaf, string): 

449 """ 

450 To make it possible for people to have completions in doctests or 

451 generally in "Python" code in docstrings, we use the following 

452 heuristic: 

453 

454 - Having an indented block of code 

455 - Having some doctest code that starts with `>>>` 

456 - Having backticks that doesn't have whitespace inside it 

457 """ 

458 

459 def iter_relevant_lines(lines): 

460 include_next_line = False 

461 for l in code_lines: 

462 if include_next_line or l.startswith('>>>') or l.startswith(' '): 

463 yield re.sub(r'^( *>>> ?| +)', '', l) 

464 else: 

465 yield None 

466 

467 include_next_line = bool(re.match(' *>>>', l)) 

468 

469 string = dedent(string) 

470 code_lines = split_lines(string, keepends=True) 

471 relevant_code_lines = list(iter_relevant_lines(code_lines)) 

472 if relevant_code_lines[-1] is not None: 

473 # Some code lines might be None, therefore get rid of that. 

474 relevant_code_lines = ['\n' if c is None else c for c in relevant_code_lines] 

475 return self._complete_code_lines(relevant_code_lines) 

476 match = re.search(r'`([^`\s]+)', code_lines[-1]) 

477 if match: 

478 return self._complete_code_lines([match.group(1)]) 

479 return [] 

480 

481 def _complete_code_lines(self, code_lines): 

482 module_node = self._inference_state.grammar.parse(''.join(code_lines)) 

483 module_value = DocstringModule( 

484 in_module_context=self._module_context, 

485 inference_state=self._inference_state, 

486 module_node=module_node, 

487 code_lines=code_lines, 

488 ) 

489 return Completion( 

490 self._inference_state, 

491 module_value.as_context(), 

492 code_lines=code_lines, 

493 position=module_node.end_pos, 

494 signatures_callback=lambda *args, **kwargs: [], 

495 fuzzy=self._fuzzy 

496 ).complete() 

497 

498 

499def _gather_nodes(stack): 

500 nodes = [] 

501 for stack_node in stack: 

502 if stack_node.dfa.from_rule == 'small_stmt': 

503 nodes = [] 

504 else: 

505 nodes += stack_node.nodes 

506 return nodes 

507 

508 

509_string_start = re.compile(r'^\w*(\'{3}|"{3}|\'|")') 

510 

511 

512def _extract_string_while_in_string(leaf, position): 

513 def return_part_of_leaf(leaf): 

514 kwargs = {} 

515 if leaf.line == position[0]: 

516 kwargs['endpos'] = position[1] - leaf.column 

517 match = _string_start.match(leaf.value, **kwargs) 

518 if not match: 

519 return None, None, None 

520 start = match.group(0) 

521 if leaf.line == position[0] and position[1] < leaf.column + match.end(): 

522 return None, None, None 

523 return cut_value_at_position(leaf, position)[match.end():], leaf, start 

524 

525 if position < leaf.start_pos: 

526 return None, None, None 

527 

528 if leaf.type == 'string': 

529 return return_part_of_leaf(leaf) 

530 

531 leaves = [] 

532 while leaf is not None: 

533 if leaf.type == 'error_leaf' and ('"' in leaf.value or "'" in leaf.value): 

534 if len(leaf.value) > 1: 

535 return return_part_of_leaf(leaf) 

536 prefix_leaf = None 

537 if not leaf.prefix: 

538 prefix_leaf = leaf.get_previous_leaf() 

539 if prefix_leaf is None or prefix_leaf.type != 'name' \ 

540 or not all(c in 'rubf' for c in prefix_leaf.value.lower()): 

541 prefix_leaf = None 

542 

543 return ( 

544 ''.join(cut_value_at_position(l, position) for l in leaves), 

545 prefix_leaf or leaf, 

546 ('' if prefix_leaf is None else prefix_leaf.value) 

547 + cut_value_at_position(leaf, position), 

548 ) 

549 if leaf.line != position[0]: 

550 # Multi line strings are always simple error leaves and contain the 

551 # whole string, single line error leaves are atherefore important 

552 # now and since the line is different, it's not really a single 

553 # line string anymore. 

554 break 

555 leaves.insert(0, leaf) 

556 leaf = leaf.get_previous_leaf() 

557 return None, None, None 

558 

559 

560def complete_trailer(user_context, values): 

561 completion_names = [] 

562 for value in values: 

563 for filter in value.get_filters(origin_scope=user_context.tree_node): 

564 completion_names += filter.values() 

565 

566 if not value.is_stub() and isinstance(value, TreeInstance): 

567 completion_names += _complete_getattr(user_context, value) 

568 

569 python_values = convert_values(values) 

570 for c in python_values: 

571 if c not in values: 

572 for filter in c.get_filters(origin_scope=user_context.tree_node): 

573 completion_names += filter.values() 

574 return completion_names 

575 

576 

577def _complete_getattr(user_context, instance): 

578 """ 

579 A heuristic to make completion for proxy objects work. This is not 

580 intended to work in all cases. It works exactly in this case: 

581 

582 def __getattr__(self, name): 

583 ... 

584 return getattr(any_object, name) 

585 

586 It is important that the return contains getattr directly, otherwise it 

587 won't work anymore. It's really just a stupid heuristic. It will not 

588 work if you write e.g. `return (getatr(o, name))`, because of the 

589 additional parentheses. It will also not work if you move the getattr 

590 to some other place that is not the return statement itself. 

591 

592 It is intentional that it doesn't work in all cases. Generally it's 

593 really hard to do even this case (as you can see below). Most people 

594 will write it like this anyway and the other ones, well they are just 

595 out of luck I guess :) ~dave. 

596 """ 

597 names = (instance.get_function_slot_names('__getattr__') 

598 or instance.get_function_slot_names('__getattribute__')) 

599 functions = ValueSet.from_sets( 

600 name.infer() 

601 for name in names 

602 ) 

603 for func in functions: 

604 tree_node = func.tree_node 

605 if tree_node is None or tree_node.type != 'funcdef': 

606 continue 

607 

608 for return_stmt in tree_node.iter_return_stmts(): 

609 # Basically until the next comment we just try to find out if a 

610 # return statement looks exactly like `return getattr(x, name)`. 

611 if return_stmt.type != 'return_stmt': 

612 continue 

613 atom_expr = return_stmt.children[1] 

614 if atom_expr.type != 'atom_expr': 

615 continue 

616 atom = atom_expr.children[0] 

617 trailer = atom_expr.children[1] 

618 if len(atom_expr.children) != 2 or atom.type != 'name' \ 

619 or atom.value != 'getattr': 

620 continue 

621 arglist = trailer.children[1] 

622 if arglist.type != 'arglist' or len(arglist.children) < 3: 

623 continue 

624 context = func.as_context() 

625 object_node = arglist.children[0] 

626 

627 # Make sure it's a param: foo in __getattr__(self, foo) 

628 name_node = arglist.children[2] 

629 name_list = context.goto(name_node, name_node.start_pos) 

630 if not any(n.api_type == 'param' for n in name_list): 

631 continue 

632 

633 # Now that we know that these are most probably completion 

634 # objects, we just infer the object and return them as 

635 # completions. 

636 objects = context.infer_node(object_node) 

637 return complete_trailer(user_context, objects) 

638 return [] 

639 

640 

641def search_in_module(inference_state, module_context, names, wanted_names, 

642 wanted_type, complete=False, fuzzy=False, 

643 ignore_imports=False, convert=False): 

644 for s in wanted_names[:-1]: 

645 new_names = [] 

646 for n in names: 

647 if s == n.string_name: 

648 if n.tree_name is not None and n.api_type in ('module', 'namespace') \ 

649 and ignore_imports: 

650 continue 

651 new_names += complete_trailer( 

652 module_context, 

653 n.infer() 

654 ) 

655 debug.dbg('dot lookup on search %s from %s', new_names, names[:10]) 

656 names = new_names 

657 

658 last_name = wanted_names[-1].lower() 

659 for n in names: 

660 string = n.string_name.lower() 

661 if complete and helpers.match(string, last_name, fuzzy=fuzzy) \ 

662 or not complete and string == last_name: 

663 if isinstance(n, SubModuleName): 

664 names = [v.name for v in n.infer()] 

665 else: 

666 names = [n] 

667 if convert: 

668 names = convert_names(names) 

669 for n2 in names: 

670 if complete: 

671 def_ = classes.Completion( 

672 inference_state, n2, 

673 stack=None, 

674 like_name_length=len(last_name), 

675 is_fuzzy=fuzzy, 

676 ) 

677 else: 

678 def_ = classes.Name(inference_state, n2) 

679 if not wanted_type or wanted_type == def_.type: 

680 yield def_ 

681 

682 

683def extract_imported_names(node): 

684 imported_names = [] 

685 

686 if node.type in ['import_as_names', 'dotted_as_names', 'import_as_name']: 

687 for index, child in enumerate(node.children): 

688 if child.type == 'name': 

689 if (index > 0 and node.children[index - 1].type == "keyword" 

690 and node.children[index - 1].value == "as"): 

691 continue 

692 imported_names.append(child.value) 

693 elif child.type == 'import_as_name': 

694 imported_names.extend(extract_imported_names(child)) 

695 

696 return imported_names