Skip to content

Commit 7840da6

Browse files
authored
Refactor _check_import_or_attribute [alt] (#440)
1 parent 1685c7f commit 7840da6

File tree

1 file changed

+62
-59
lines changed

1 file changed

+62
-59
lines changed

pyi.py

Lines changed: 62 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,63 @@ def _is_metaclass(node: ast.ClassDef) -> bool:
848848
return any(_is_metaclass_base(base) for base in node.bases)
849849

850850

851+
def _check_import_or_attribute(
852+
node: ast.Attribute | ast.ImportFrom, module_name: str, object_name: str
853+
) -> str | None:
854+
"""If `node` represents a bad import, return the approriate error message.
855+
856+
Else, return None.
857+
"""
858+
fullname = f"{module_name}.{object_name}"
859+
860+
# Y057 errors
861+
if fullname in {"typing.ByteString", "collections.abc.ByteString"}:
862+
return Y057.format(module=module_name)
863+
864+
# Y024 errors
865+
if fullname == "collections.namedtuple":
866+
return Y024
867+
868+
if module_name in _TYPING_MODULES:
869+
# Y022 errors
870+
if object_name in _BAD_Y022_IMPORTS:
871+
good_cls_name, slice_contents = _BAD_Y022_IMPORTS[object_name]
872+
params = "" if slice_contents is None else f"[{slice_contents}]"
873+
return Y022.format(
874+
good_syntax=f'"{good_cls_name}{params}"',
875+
bad_syntax=f'"{fullname}{params}"',
876+
)
877+
878+
# Y037 errors
879+
if object_name == "Optional":
880+
return Y037.format(
881+
old_syntax=fullname, example='"int | None" instead of "Optional[int]"'
882+
)
883+
if object_name == "Union":
884+
return Y037.format(
885+
old_syntax=fullname, example='"int | str" instead of "Union[int, str]"'
886+
)
887+
888+
# Y039 errors
889+
if object_name == "Text":
890+
return Y039.format(module=module_name)
891+
892+
# Y023 errors
893+
if module_name == "typing_extensions":
894+
if object_name in _BAD_TYPINGEXTENSIONS_Y023_IMPORTS:
895+
return Y023.format(
896+
good_syntax=f'"typing.{object_name}"',
897+
bad_syntax=f'"typing_extensions.{object_name}"',
898+
)
899+
if object_name == "ClassVar":
900+
return Y023.format(
901+
good_syntax='"typing.ClassVar[T]"',
902+
bad_syntax='"typing_extensions.ClassVar[T]"',
903+
)
904+
905+
return None
906+
907+
851908
@dataclass
852909
class NestingCounter:
853910
"""Class to help the PyiVisitor keep track of internal state"""
@@ -916,67 +973,12 @@ def __init__(self, filename: str) -> None:
916973
def __repr__(self) -> str:
917974
return f"{self.__class__.__name__}(filename={self.filename!r})"
918975

919-
def _check_import_or_attribute(
920-
self, node: ast.Attribute | ast.ImportFrom, module_name: str, object_name: str
921-
) -> None:
922-
fullname = f"{module_name}.{object_name}"
923-
924-
# Y057 errors
925-
if fullname in {"typing.ByteString", "collections.abc.ByteString"}:
926-
error_message = Y057.format(module=module_name)
927-
928-
# Y022 errors
929-
elif module_name in _TYPING_MODULES and object_name in _BAD_Y022_IMPORTS:
930-
good_cls_name, slice_contents = _BAD_Y022_IMPORTS[object_name]
931-
params = "" if slice_contents is None else f"[{slice_contents}]"
932-
error_message = Y022.format(
933-
good_syntax=f'"{good_cls_name}{params}"',
934-
bad_syntax=f'"{fullname}{params}"',
935-
)
936-
937-
# Y037 errors
938-
elif module_name in _TYPING_MODULES and object_name == "Optional":
939-
error_message = Y037.format(
940-
old_syntax=fullname, example='"int | None" instead of "Optional[int]"'
941-
)
942-
elif module_name in _TYPING_MODULES and object_name == "Union":
943-
error_message = Y037.format(
944-
old_syntax=fullname, example='"int | str" instead of "Union[int, str]"'
945-
)
946-
947-
# Y039 errors
948-
elif module_name in _TYPING_MODULES and object_name == "Text":
949-
error_message = Y039.format(module=module_name)
950-
951-
# Y023 errors
952-
elif module_name == "typing_extensions":
953-
if object_name in _BAD_TYPINGEXTENSIONS_Y023_IMPORTS:
954-
error_message = Y023.format(
955-
good_syntax=f'"typing.{object_name}"',
956-
bad_syntax=f'"typing_extensions.{object_name}"',
957-
)
958-
elif object_name == "ClassVar":
959-
error_message = Y023.format(
960-
good_syntax='"typing.ClassVar[T]"',
961-
bad_syntax='"typing_extensions.ClassVar[T]"',
962-
)
963-
else:
964-
return
965-
966-
# Y024 errors
967-
elif fullname == "collections.namedtuple":
968-
error_message = Y024
969-
970-
else:
971-
return
972-
973-
self.error(node, error_message)
974-
975976
def visit_Attribute(self, node: ast.Attribute) -> None:
976977
self.generic_visit(node)
977-
self._check_import_or_attribute(
978+
if error_msg := _check_import_or_attribute(
978979
node=node, module_name=unparse(node.value), object_name=node.attr
979-
)
980+
):
981+
self.error(node, error_msg)
980982

981983
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
982984
self.generic_visit(node)
@@ -1000,7 +1002,8 @@ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
10001002
self.error(node, Y025)
10011003

10021004
for object_name in imported_names:
1003-
self._check_import_or_attribute(node, module_name, object_name)
1005+
if error_msg := _check_import_or_attribute(node, module_name, object_name):
1006+
self.error(node, error_msg)
10041007

10051008
if module_name in _TYPING_MODULES and "AbstractSet" in imported_names:
10061009
self.error(node, Y038.format(module=module_name))

0 commit comments

Comments
 (0)