(self, name: str, ctx: Context, namespace: str | None = None)
| 7507 | self.all_exports.append(exp.value) |
| 7508 | |
| 7509 | def name_not_defined(self, name: str, ctx: Context, namespace: str | None = None) -> None: |
| 7510 | incomplete = self.is_incomplete_namespace(namespace or self.cur_mod_id) |
| 7511 | if ( |
| 7512 | namespace is None |
| 7513 | and self.type |
| 7514 | and not self.is_func_scope() |
| 7515 | and self.incomplete_type_stack |
| 7516 | and self.incomplete_type_stack[-1] |
| 7517 | and not self.final_iteration |
| 7518 | ): |
| 7519 | # We are processing a class body for the first time, so it is incomplete. |
| 7520 | incomplete = True |
| 7521 | if incomplete: |
| 7522 | # Target namespace is incomplete, so it's possible that the name will be defined |
| 7523 | # later on. Defer current target. |
| 7524 | self.record_incomplete_ref() |
| 7525 | return |
| 7526 | message = f'Name "{name}" is not defined' |
| 7527 | if ( |
| 7528 | not self.msg.prefer_simple_messages() |
| 7529 | and "." not in name |
| 7530 | and not (name.startswith("__") and name.endswith("__")) |
| 7531 | and f"builtins.{name}" not in SUGGESTED_TEST_FIXTURES |
| 7532 | and ctx.line not in self.errors.ignored_lines.get(self.errors.file, {}) |
| 7533 | ): |
| 7534 | alternatives = self._get_names_in_scope() |
| 7535 | alternatives.discard(name) |
| 7536 | matches = best_matches(name, alternatives, n=3) |
| 7537 | if matches: |
| 7538 | message += f"; did you mean {pretty_seq(matches, 'or')}?" |
| 7539 | self.fail(message, ctx, code=codes.NAME_DEFINED) |
| 7540 | |
| 7541 | if f"builtins.{name}" in SUGGESTED_TEST_FIXTURES: |
| 7542 | # The user probably has a missing definition in a test fixture. Let's verify. |
| 7543 | fullname = f"builtins.{name}" |
| 7544 | if self.lookup_fully_qualified_or_none(fullname) is None: |
| 7545 | # Yes. Generate a helpful note. |
| 7546 | self.msg.add_fixture_note(fullname, ctx) |
| 7547 | |
| 7548 | modules_with_unimported_hints = { |
| 7549 | name.split(".", 1)[0] for name in TYPES_FOR_UNIMPORTED_HINTS |
| 7550 | } |
| 7551 | lowercased = {name.lower(): name for name in TYPES_FOR_UNIMPORTED_HINTS} |
| 7552 | for module in modules_with_unimported_hints: |
| 7553 | fullname = f"{module}.{name}".lower() |
| 7554 | if fullname not in lowercased: |
| 7555 | continue |
| 7556 | # User probably forgot to import these types. |
| 7557 | hint = ( |
| 7558 | 'Did you forget to import it from "{module}"?' |
| 7559 | ' (Suggestion: "from {module} import {name}")' |
| 7560 | ).format(module=module, name=lowercased[fullname].rsplit(".", 1)[-1]) |
| 7561 | self.note(hint, ctx, code=codes.NAME_DEFINED) |
| 7562 | |
| 7563 | def _get_names_in_scope(self) -> set[str]: |
| 7564 | """Collect all names visible in the current scope for fuzzy matching suggestions. |
no test coverage detected