Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Features:
* Support Python 3.11.
* Support `typing_extensions.overload` and `typing_extensions.NamedTuple`. (The latter
is not yet released, but will be in the next version of `typing_extensions`.)
* Introduce Y044: Discourage unnecessary `from __future__ import annotations` import.
Contributed by Torsten Wörtwein.

## 22.5.1

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ currently emitted:
| Y040 | Never explicitly inherit from `object`, as all classes implicitly inherit from `object` in Python 3. This error code is incompatible with stubs supporting Python 2.
| Y041 | Y041 detects redundant numeric unions. For example, PEP 484 specifies that type checkers should treat `int` as an implicit subtype of `float`, so `int` is redundant in the union `int \| float`. In the same way, `int` is redundant in the union `int \| complex`, and `float` is redundant in the union `float \| complex`.
| Y043 | Do not use names ending in "T" for private type aliases. (The "T" suffix implies that an object is a `TypeVar`.)
| Y044 | `from __future__ import annotations` has no effect in stub files, as forward references in stubs are enabled by default.

Many error codes enforce modern conventions, and some cannot yet be used in
all cases:
Expand Down
5 changes: 5 additions & 0 deletions pyi.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,10 @@ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
for obj in imported_objects
):
return self.error(node, Y025)
elif module_name == "__future__" and any(
obj.name == "annotations" for obj in imported_objects
):
return self.error(node, Y044)

for obj in imported_objects:
self._check_import_or_attribute(
Expand Down Expand Up @@ -1669,3 +1673,4 @@ def parse_options(
Y040 = 'Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3'
Y041 = 'Y041 Use "{implicit_supertype}" instead of "{implicit_subtype} | {implicit_supertype}" (see "The numeric tower" in PEP 484)'
Y043 = 'Y043 Bad name for a type alias (the "T" suffix implies a TypeVar)'
Y044 = 'Y044 "from __future__ import annotations" has no effect in stub files.'
3 changes: 3 additions & 0 deletions tests/imports.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# Note: DO NOT RUN ISORT ON THIS FILE.
# It's excluded in our pyproject.toml.

# BAD IMPORTS (Y044)
from __future__ import annotations # Y044 "from __future__ import annotations" has no effect in stub files.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also move it to the bad imports. I put it up there as I think __future__ imports have to be the very first import.

Copy link
Collaborator

@AlexWaygood AlexWaygood Jul 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having it here is fine, I think.


# GOOD IMPORTS
import typing
import typing_extensions
Expand Down