Releases: sco1/flake8-annotations
Release v2.6.0
Changelog
[v2.6.0]
Added
- #98 Add
--dispatch-decorators
to support suppression of all errors from functions decorated by decorators such asfunctools.singledispatch
andfunctools.singledispatchmethod
. - #99 Add
--overload-decorators
to support generic aliasing of thetyping.overload
decorator.
Fixed
- #106 Fix incorrect parsing of multiline docstrings with less than two lines of content, causing incorrect line numbers for yielded errors in Python versions prior to 3.8
Additional Details
Generic Functions
Per #98, the functools.singledispatch
and functools.singledispatchmethod
decorators transform a function into a single-dispatch generic function.
For example:
import functools
@functools.singledispatch
def foo(a):
print(a)
@foo.register
def _(a: list) -> None:
for idx, thing in enumerate(a):
print(idx, thing)
Is correctly annotated but would previously yield linting errors for foo
. In the spirit of the purpose of these decorators, linting errors are now suppressed for functions decorated with these decorators. The --dispatch-decorators
configuration option has been added, which specifies a comma-separated list of decorators to be considered as dispatch decorators.
Decorators are matched based on their attribute name. For example, "singledispatch"
will match any of the following:
import functools; @functools.singledispatch
import functools as fnctls; @fnctls.singledispatch
from functools import singledispatch; @singledispatch
By default, linting errors are suppressed for functions decorated by singledispatch
or singledispatchmethod
.
typing.overload
decorator aliasing
Per #99, handling of the typing.overload
has been made generic, removing the caveat from the initial implementation. The --overload-decorators
configuration option has been added, which specifies a comma-separated list of decorators to be considered as typing.overload
decorators.
Decorators are now matched based on their attribute name. For example, "overload"
will match any of the following:
import typing; @typing.overload
import typing as t; @t.overload
from typing import overload; @overload
By default, linting errors are suppressed for functions decorated by overload
, which should be a transparent change from v2.4 (#97).
Release v2.5.0
Changelog
[v2.5.0]
Added
- #103 add
--allow-untyped-nested
to suppress all errors from dynamically typted nested functions. A function is considered dynamically typed if it does not contain any type hints.
Additional Details
Per #102, nested functions can fall into an interesting spot semantically for a project. They're distinct enough from private/secret functions that one may not want to strictly enforce annotation (e.g. decorator definitions) but there does not exist a mechanism to do so without either noqa
or just allowing all dynamically typed functions (via --allow-untyped-defs
). The --allow-untyped-nested
flag allows for this stricter subset of dynamic functions.
Release v2.4.1
[v2.4.1]
Fixed
- #100 Fix incorrect positioning of posonlyargs in the
Function
argument list, causing incorrect classification of the type of missing argument.
Release v2.4.0
[v2.4.0]
Fixed
- #92 Fix inconsistent linting behavior between function-level type comments and their equivalent PEP 3107-style function annotations of class methods and classmethods.
- #94 Fix improper handling of the closing definition in a series of
typing.overload
decorated functions.
Additional Details
Function-level type comment changes
Per #92, there exists a discrepancy in behavior between linting of functions with PEP 3107-style annotations and PEP 484-style function-level type comments. Because PEP 484 does not describe a method to provide partial function-level type comments, there is a potential for ambiguity in the context of both class methods and classmethods when aligning type comments to method arguments.
These two class methods, for example, should lint equivalently:
def bar(self, a):
# type: (int) -> int
...
def bar(self, a: int) -> int
...
When this example type comment is parsed by ast
and then matched with the method's arguments, it associates the int
hint to self
rather than a
, so a dummy hint needs to be provided in situations where self
or class
are not hinted in the type comment in order to achieve equivalent linting results to PEP-3107 style annotations.
A dummy ast.Ellipses
constant is injected into the parsed node if the following criteria are met:
- The function node is either a class method or classmethod
- The number of hinted args is at least 1 less than the number of function args
typing.overload
decorator handling
Per #94, the typing.overload
was being handled too literally (aka: ignored) by the linter, resulting in emitted linting errors that do not align with the purpose of the decorator.
For example, this code:
import typing
@typing.overload
def foo(a: int) -> int:
...
def foo(a):
...
Would raise linting errors for missing annotations for the arguments & return of the non-decorated foo
definition; this interpretation disagrees with the purpose of the decorator.
Per the documentation:
A series of
@overload
-decorated definitions must be followed by exactly one non-@overload
-decorated definition (for the same function/method)
Errors for missing annotations for non-@overload
-decorated functions are now ignored if they meet this criteria.
NOTE: If importing directly, the typing.overload
decorator will not be recognized if it is imported with an alias (e.g. from typing import overload as please_dont_do_this
). Aliasing of the typing
module is supported (e.g. import typing as t; @t.overload
)
Release v2.3.0
[v2.3.0]
Added
- #87 Add
--mypy-init-return
to allow omission of a return type hint for__init__
if at least one argument is annotated.
Additional Details
To help provide compatibility with Mypy for maintainers that wish to do so, the --mypy-init-return
flag has been introduced to mimic Mypy's allowance for the omission of return type hints for __init__
methods that are not dynamically typed (at least one argument is annotated). With this flag set, ANN200
level errors will be suppressed for __init__
methods if at least one argument is explicitly annotated.
For example, from Mypy's documentation:
class C1: # Return annotated
def __init__(self) -> None:
self.var = 42
class C2: # Return annotated
def __init__(self, arg: int):
self.var = arg
class C3:
def __init__(self): # Return not annotated
# This body is not type checked
self.var = 42 + 'abc'
NOTE: By default, Mypy does not enforce annotations for self
in class methods, so to completely mimic Mypy's behavior with flake8-annotations
ANN101
will need to be added to the repository's ignored linting codes.
See Mypy's documentation for additional details: https://mypy.readthedocs.io/en/stable/class_basics.html?#annotating-init-methods
Release v2.2.1
Release v2.2.0
[v2.2.0]
Added
- #87 Add
--allow-untyped-defs
to suppress all errors from dynamically typed functions. A function is considered dynamically typed if it does not contain any type hints.
Fixed
Release v2.1.0
v2.1.0
Added
- #68 Add
--suppress-dummy-args
configuration option to suppress ANN000 level errors for dummy arguments, defined as"_"
Release v2.0.1
v2.0.1
Added
- #71 Add
pep8-naming
to linting toolchain - Expand pre-commit hooks
- Add
black
- Add
check-merge-conflict
- Add
check-toml
- Add
check-yaml
- Add
end-of-file-fixer
- Add
mixed-line-ending
- Add
python-check-blanket-noqa
- Add
Changed
- Add argument names to
Argument
andFunction
__repr__
methods to make the string more helpful to read
Fixed
- #70 Fix incorrect column index for missing return annotations when other annotations are present on the same line of source
- #69 Fix misclassification of
None
returning functions when they contained nested functions with non-None
returns (thanks @isidentical!) - #67 Fix methods of nested classes being improperly classified as "regular" functions (thanks @isidentical!)
Additional Details
The previous approach being taken for nesting as to use a generic_visit() on the node to visit any nested functions. However, from the bugs reported (#67, #69) it was made clear that this approach was too generic & a method for either restricting or keeping track of the depth of this generic visit was required.
Both the FunctionVisitor
and ReturnVisitor
classes have been rearchitected to keep track of the parent context of the nodes being visited in order to properly classify methods of nested classes and return values of nested functions, respectively.
You can view a full writeup here on discuss.python.org.
Release v2.0.0
[v2.0.0]
Changed
- #64 Change prefix from
TYP
toANN
in order to deconflict withflake8-typing-imports
Additional Details
Per #64, due to prefix shadowing of TYP
between flake8-annotations
and flake8-typing-imports
, it's been suggested that the prefix for this repository be changed to ANN
so the plugins can coexist peacefully.