NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
A plugin for flake8 to enable linting .pyi stub files.
Last release 4 months ago
11 May 2026
Release timing varies
gaps range from 8 days to 12 months
Nearly every release is documented
notes for 44 of 44 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
45 releases · first in 2016
Previously, flake8-pyi monkey patched flake8's F821 (undefined name) check to avoid false positives in stub files. This monkey patch has been removed.
--no-pyi-aware-file-checker option.@override in stub filesIntroduce Y067: Don't use Incomplete | None = None.
New error codes:
Incomplete | None = None.Other changes:
math.inf or enum members.flake8_pyi package rather than a single pyi.py file.One column per quarter.
Incomplete | None = Nonemath.inf or enum members.flake8_pyi package rather than a single pyi.py file.Don't emit Y053 for long strings inside Literal slices or metadata strings inside Annotated slices.
Bugfixes:
Literal slices or metadata strings inside Annotated slices.Other changes:
flake8-pyi no longer supports being run using Python 3.8. As a result, it not longer depends on the third-party ast_decompiler package.Allow the use of typing_extensions.TypeVar in stubs. typing_extensions.TypeVar has the *default* parameter, which only exists on Python 3.13+ when usi
Bugfixes
typing_extensions.TypeVar in stubs. typing_extensions.TypeVar has the default parameter, which only exists on Python 3.13+ when using typing.TypeVar.Other changes
Y066: When using if/else with sys.version_info, put the code for new Python versions first.
New error codes:
sys.version_info, put the code for new Python versions first.Fix Y026 false positive: allow simple assignment to None in class scopes if the class is known to be an enum class.
Bugfixes:
None in class scopes if the class is known to be an enum class.None in class scopes
if the class is known to be an enum class.Y064: Use simpler syntax to define final literal types. For example, use x: Final = 42 instead of x: Final[Literal[42]]
New error codes:
x: Final = 42 instead of x: Final[Literal[42]]Incomplete in parameter and return annotations.Bugfixes:
tuple[Unpack[Ts]].Y063: Use PEP 570 syntax to mark positional-only arguments, rather than the older Python 3.7-compatible syntax described in PEP 484.
New error codes:
Y062: Disallow duplicate elements inside Literal[] slices.
New error codes:
Literal[] slices.Other features:
typing_extensions now that typeshed has dropped support for Python 3.7.Bugfixes:
Literal[] slicestyping_extensions now that typeshed has
dropped support for Python 3.7.Y053 will no longer be emitted for the argument to @typing_extensions.deprecated.
New error codes:
Iterator rather than Generator as the return value for simple __iter__ methods, and AsyncIterator rather than AsyncGenerator as the return value for simple __aiter__ methods.Generic[] should always be the last base class, if it is present in the bases of a class.Generic[].None inside a Literal[] slice. For example, use Literal["foo"] | None instead of Literal["foo", None].Other changes:
pyi.__version__ and pyi.PyiTreeChecker.version attributes has been removed. Use flake8 --version from the command line, or importlib.metadata.version("flake8_pyi") at runtime, to determine the version of flake8-pyi installed at runtime.from typing_extensions import AbstractSet as well as from typing import AbstractSet.typing_extensions.builtins.type, abc.ABCMeta and/or enum.EnumMeta. Classes that have one or more of these as bases are metaclasses, and PEP 673 forbids the use of typing(_extensions).Self for metaclasses. While reliably determining whether a class is a metaclass in all cases would be impossible for flake8-pyi, the new heuristics should reduce the number of false positives from this check.typing_extensions.Text now causes Y039 to be emitted rather than Y023.@typing_extensions.deprecated.pyi.__version__ and pyi.PyiTreeChecker.version
attributes has been removed. Use flake8 --version from the command line, or
importlib.metadata.version("flake8_pyi") at runtime, to determine the
version of flake8-pyi installed at runtime.Iterator rather than Generator as the return value
for simple __iter__ methods, and AsyncIterator rather than
AsyncGenerator as the return value for simple __aiter__ methodsGeneric[] should always be the last base class, if it is
present in the bases of a class.Generic[]None inside a Literal[] slice.
For example, use Literal["foo"] | None instead of Literal["foo", None]from typing_extensions import AbstractSet as well as
from typing import AbstractSet.typing_extensions.builtins.type, abc.ABCMeta and/or enum.EnumMeta. Classes that have one
or more of these as bases are metaclasses, and PEP 673
forbids the use of typing(_extensions).Self
for metaclasses. While reliably determining whether a class is a metaclass in
all cases would be impossible for flake8-pyi, the new heuristics should
reduce the number of false positives from this check.@typing_extensions.deprecated.typing_extensions.Text now causes Y039 to be emitted
rather than Y023.Introduce Y090, which warns if you have an annotation such as tuple[int] or Tuple[int]. These mean "a tuple of length 1, in which the sole element is
Introduce Y090, which warns if you have an annotation such as tuple[int] or Tuple[int]. These mean "a tuple of length 1, in which the sole element is of type int". This is sometimes what you want, but more usually you'll want tuple[int, ...], which means "a tuple of arbitrary (possibly 0) length, in which all elements are of type int".
This error code is disabled by default due to the risk of false-positive errors. To enable it, use the --extend-select=Y090 option.
Y011 now ignores sentinel and _typeshed.sentinel in default values.
Y090: This check warns if you have an annotation such as tuple[int] or
Tuple[int]. These mean "a tuple of length 1, in which the sole element is
of type int". This is sometimes what you want, but more usually you'll want
tuple[int, ...], which means "a tuple of arbitrary (possibly 0) length, in
which all elements are of type int".
This error code is disabled by default due to the risk of false-positive
errors. To enable it, use the --extend-select=Y090 option.
sentinel and _typeshed.sentinel in default values.Introduce Y057: Do not use typing.ByteString or collections.abc.ByteString. These types have unclear semantics, and are deprecated; use typing_extensi…
Features:
TypeVar instead of returning typing_extensions.Selftyping.ByteString or collections.abc.ByteString. These types have unclear semantics, and are deprecated; use typing_extensions.Buffer or a union such as bytes | bytearray | memoryview instead. See PEP 688 for more details.When flake8-pyi is installed, pyflakes will now complain about forward references in default values for function and method parameters (the same as pyflakes does when it checks .py files). Unlike in .py files, forward references in default values are legal in stub files. However, they are never necessary, and are considered bad style. (Forward references for parameter annotations are still allowed.)
Contributed by tomasr8.
When flake8-pyi is installed, pyflakes's F822 check now produces many fewer false positives when flake8 is run on .pyi files. It now understands that x: int in a stub file is sufficient for x to be considered "bound", and that "x" can therefore be included in __all__.
Bugfixes:
if sys.version_info >= (3, 10) check). This bug has now been fixed.Other changes:
flake8-pyi no longer supports being run with flake8 <5.0.4.
flake8-pyi no longer supports being run with flake8 <5.0.4.
The way in which flake8-pyi modifies pyflakes runs has been improved:
When flake8-pyi is installed, pyflakes now correctly recognises an annotation as being equivalent to a binding assignment in a stub file, reducing false positives from flake8's F821 error code.
When flake8-pyi is installed, there are now fewer pyflakes positives from class
definitions that have forward references in the bases tuple for the purpose of
creating recursive or circular type definitions. These are invalid in .py files,
but are supported in stub files.
When flake8-pyi is installed, pyflakes will also complain about code which (in combination with flake8-pyi) it previously had no issue with. For example, it will now complain about this code:
class Foo(Bar): ...
class Bar: ...
Although the above code is legal in a stub file, it is considered poor style, and the forward reference serves no purpose (there is no recursive or circular definition). As such, it is now disallowed by pyflakes when flake8-pyi is installed.
Contributed by tomasr8.
Introduce Y056: Various type checkers have different levels of support for method
calls on __all__. Use __all__ += ["foo", "bar"] instead, as this is known to be
supported by all major type checkers.
Introduce Y055: Unions of the form type[X] | type[Y] can be simplified to type[X | Y]. Similarly, Union[type[X], type[Y]] can be simplified to type[Un
type[X] | type[Y] can be simplified to type[X | Y]. Similarly, Union[type[X], type[Y]] can be simplified to type[Union[X, Y]]. Contributed by tomasr8.type[X] | type[Y] can be simplified to type[X | Y].
Similarly, Union[type[X], type[Y]] can be simplified to type[Union[X, Y]].
(Contributed by tomasr8).Update error messages for Y019 and Y034 to recommend using typing_extensions.Self rather than _typeshed.Self.
Update error messages for Y019 and Y034 to recommend using typing_extensions.Self rather than _typeshed.Self.
typing_extensions.Self rather than _typeshed.Self.Y053: Disallow string or bytes literals with length >50 characters. Previously this rule only applied to parameter default values; it now applies ever
New error codes:
Other changes:
list, dict, tuple and set literals) are now allowed as default values.Y011/Y014/Y015: Allow math constants math.inf, math.nan, math.e, math.pi, math.tau, and their negatives in default values. Some other semantically equ
Y011/Y014/Y015: Allow math constants math.inf, math.nan, math.e, math.pi, math.tau, and their negatives in default values. Some other semantically equivalent values, such as x = inf (from math import inf), or x = np.inf (import numpy as np), should be rewritten to x = math.inf. Contributed by XuehaiPan.
Y011/Y014/Y015: Increase the maximum character length of literal numbers in default values from 7 to 10, allowing hexadecimal representation of 32-bit
Y052: Disallow default values in global or class namespaces where the assignment does not have a type annotation. Stubs should be explicit about the t
New error codes:
__all__ and __match_args__.Other changes:
len(str(default)) > 7. If a function has a default value where the string representation is greater than 7 characters, it is likely to be an implementation detail or a constant that varies depending on the system you're running on, such as sys.maxsize.str or bytes defaults where the default is >50 characters long, for similar reasons.ast.Attribute nodes as default values for a small number of special cases, such as sys.maxsize and sys.executable.Do not emit Y020 (quoted annotations) for strings in parameter defaults.
Bugfixes:
Other changes:
_typeshed.Unused is allowed as an annotation for parameters in __(a)exit__ methods. Contributed by Avasamtyping.Match and typing.Pattern have been added to the list of imports banned by Y022. Use re.Match and re.Pattern instead.None, bools, ints, floats, complex numbers, strings and bytes are all now allowed as default values for parameter annotations or assignments.typing aliasesNone, bools,
ints, floats, complex numbers, strings and bytes are all now allowed
as default values for parameter annotations or assignments.typing.Match and typing.Pattern have been added to the list of banned imports
Use re.Match and re.Pattern instead._typeshed.Unused is allowed as an annotation for
parameters in __(a)exit__ methods. Contributed by
AvasamSpecify encoding when opening files. Prevents UnicodeDecodeError on Windows when the file contains non-CP1252 characters. Contributed by Avasam.
Bugfixes:
UnicodeDecodeError on Windows
when the file contains non-CP1252 characters.
Contributed by Avasam.float | int, complex | float or complex | int)
in all contexts outside of type aliases. This was incorrect. PEP 484 only
specifies that type checkers should treat int as an implicit subtype of
float in the specific context of parameter annotations for functions and
methods. Y041 has therefore been revised to only emit errors on "redundant
numeric unions" in the context of parameter annotations.Other changes:
Do not emit Y020 for empty strings. Y020 concerns "quoted annotations", but an empty string can never be a quoted annotation.
Bugfixes:
__slots__ definitions
inside class blocks.__slots__ definitions as well as __match_args__ and
__all__ definitions.Other changes:
FutureWarning if run with flake8<5,
warning that the plugin would soon become incompatible with flake8<5. Due to
some issues that mean that some users are unable to upgrade to flake8>=5,
however, flake8-pyi no longer intends to remove support for running the
plugin with flake8<5 before Python 3.7 has reached end-of-life. As such, the
FutureWarning is no longer emitted.Y047: Detect unused TypeAlias declarations.
New error codes:
TypeAlias declarations.TypedDict definitions.typing_extensions.Never for argument annotations over
typing.NoReturn.Literal types and builtin supertypes
(e.g. Literal["foo"] | str, or Literal[5] | int).Other enhancements:
mypy_extensions.TypedDict.Add support for flake8 >= 5.0.0.
Y048: Function bodies should contain exactly one statement.
New error codes:
Protocols.Bugfixes:
... or pass statement.Other changes:
Introduce Y041: Ban redundant numeric unions (int | float, int | complex, float | complex).
New error codes:
int | float, int | complex,
float | complex).from __future__ import annotations import.
Contributed by Torsten Wörtwein.(Async)Iterable from __(a)iter__ methods.Other enhancements and behaviour changes:
typing.Literal, typing.Union, and PEP 604 unions. It now also
emits an error for any subscription on the right-hand side of a simple assignment, as
well as for assignments to typing.Any and None.typing_extensions.overload and typing_extensions.NamedTuple.(Async)Iterator
returns (Async)Iterable from __(a)iter__. These classes should nearly always return
Self from these methods.int | float, int | complex,
float | complex)from __future__ import annotations import
(Contributed by Torsten Wörtwein)(Async)Iterable from __(a)iter__ methodstyping.Literal, typing.Union, and PEP 604 unions. It now also
emits an error for any subscription on the right-hand side of a simple assignment, as
well as for assignments to typing.Any and None.(Async)Iterator
returns (Async)Iterable from __(a)iter__. These classes should nearly always return
Self from these methods.typing_extensions.overload and typing_extensions.NamedTuple.Relax Y020 check slightly, enabling the idiom __all__ += ["foo", "bar"] to be used in a stub file.
Behaviour changes:
__all__ += ["foo", "bar"] to be used
in a stub file.__all__ += ["foo", "bar"] to be used
in a stub file.Introduce Y039: Use str instead of typing.Text for Python 3 stubs.
Features:
str instead of typing.Text for Python 3 stubs.builtins.object (as well as the unqualified object) is acceptable as an annotation for an __(a)exit__ method argument.__repr__ and __str__ methods that return builtins.str (as opposed to the unqualified str).object in Python 3 stubs.str instead of typing.Text for Python 3 stubsobject in Python 3 stubs__repr__ and __str__ methods that return
builtins.str (as opposed to the unqualified str).builtins.object (as well as the unqualified object) is
acceptable as an annotation for an __(a)exit__ method argument.Expand Y027 check to prohibit importing any objects from the typing module that are aliases for objects living in collections.abc (except for typing.A
Features:
collections.abc (except for typing.AbstractSet, which is special-cased).from collections.abc import Set as AbstractSet instead of from typing import AbstractSet.Bugfixes:
from collections.abc import Set as AbstractSet instead of
from typing import AbstractSettyping module that are
aliases for objects living collections.abc (except for typing.AbstractSet, which
is special-cased).Introduce Y036 (check for badly defined __exit__ and __aexit__ methods).
Features:
__exit__ and __aexit__ methods).typing.Union and typing.Optional).
Contributed by Oleg Höfling.Behaviour changes:
__match_args__ inside class definitions, as well as __all__
in the global scope.Bugfixes:
typing.TypeAlias) to reduce false-positive errors
emitted when the plugin encountered variable aliases in a stub file.__exit__ and __aexit__ methodstyping.Union and typing.Optional
(Contributed by Oleg Höfling)__match_args__ inside class definitions, as well as __all__
in the global scope.typing.TypeAlias) to reduce false-positive errors
emitted when the plugin encountered variable aliases in a stub file.fix bug where incorrect quoted annotations were not detected within if blocks
Bugfixes:
if blocksBehaviour changes:
__match_args__ assignments inside a class definition.Final.fix bugs in several error codes so that e.g. _T = typing.TypeVar("_T") is recognised as a TypeVar definition (previously only _T = TypeVar("_T") was r
Bugfixes:
_T = typing.TypeVar("_T") is
recognised as a TypeVar definition (previously only _T = TypeVar("_T") was
recognised).foo = False at the module level did not trigger a Y015 error.TypeVars were erroneously flagged as unused if they were only used in
a typing.Union subscript.Features:
object to Any for the second argument in __eq__ and
__ne__ methods).TypeVars instead).__all__ in a stub has the same semantics as at runtime).extend Y001 to cover ParamSpec and TypeVarTuple in addition to TypeVar
sys.version_info checks__init__ methods) and Y091 (disallow raise
statements). The previous checks were disabled by default.typing aliases)typing over typing_extensions)typing.NamedTuple to collections.namedtuple)collections.abc.Set)__repr__ or __str__)Literal['foo', 'bar'] instead of Literal['foo'] | Literal['bar'])attrs is no longer a dependencyast_decompiler has been added as a dependency on Python 3.8 and 3.7TypeVarsTypeVars that should be _typeshed.Self, but aren'ttyping aliasestyping over typing_extensionstyping.NamedTuple to collections.namedtupleTypeAlias for type aliasescollections.abc.SetNamedTuples__repr__ or __str__Literal['foo', 'bar'] instead of Literal['foo'] | Literal['bar']TypedDicts where possibleParamSpec and TypeVarTuple in addition to TypeVar.__init__ methods) and Y091 (disallow raise
statements). The previous checks were disabled by default.sys.version_info checks.attrs is no longer a dependency.ast_decompiler has been added as a dependency on Python 3.8 and 3.7.Pre-release. If all goes well 22.1.0 will follow soon with the exact same code.
Pre-release. If all goes well 22.1.0 will follow soon with the exact same code.
sys.version_info checks__init__ methods) and Y091 (disallow raise
statements). The previous checks were disabled by default.typing aliases)typing over typing_extensions)typing.NamedTuple to collections.namedtuple)collections.abc.Set)__repr__ or __str__)Literal['foo', 'bar'] instead of Literal['foo'] | Literal['bar'])attrs is no longer a dependencyast_decompiler has been added as a dependency on Python 3.8 and 3.7### Other Changes * Support Python 3.9.
Y015: Attribute must not have a default value other than ...
...raise### Other Changes * Update pyflakes dependency.
Y012: Class body must not contain pass
pass...--stdin-display-name as the filename when reading from stdin.Y011: Allow only simple default values
Release herp derp, don't use.
Release herp derp, don't use.
### New Error Codes * Y001: Y010 * Y090 (disabled by default)
Handle del statements in stub files.
del statements in stub files.Handle annotated assignments in 3.6+ with forward reference support.
Handle forward references during subclassing on module level.
First published version
First published version
Your coding agent can read these notes before it upgrades. Set up the MCP server →