Releases: sco1/flake8-annotations
Release v2.6.1
Changelog
[v2.6.1]
Changed
- Remove the explicitly pinned minor version ceiling for flake8.
Release v2.6.0
Changelog
[v2.6.0]
Added
- #98 Add
--dispatch-decoratorsto support suppression of all errors from functions decorated by decorators such asfunctools.singledispatchandfunctools.singledispatchmethod. - #99 Add
--overload-decoratorsto support generic aliasing of thetyping.overloaddecorator.
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.singledispatchimport functools as fnctls; @fnctls.singledispatchfrom 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.overloadimport typing as t; @t.overloadfrom 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-nestedto 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
Functionargument 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.overloaddecorated 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-returnto 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-defsto 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-argsconfiguration option to suppress ANN000 level errors for dummy arguments, defined as"_"
Release v2.0.1
v2.0.1
Added
- #71 Add
pep8-namingto 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
ArgumentandFunction__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
Nonereturning functions when they contained nested functions with non-Nonereturns (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.