Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable F821 and F822 by default #177

Closed
wants to merge 12 commits into from
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ Features:
* introduce Y034 (detect common errors where return types are hardcoded, but they
should use `TypeVar`s instead).
* introduce Y035 (`__all__` in a stub has the same semantics as at runtime).
* the plugin now blocks all F821 errors from being reported by
flake8/pyflakes. This check does not make sense for `.pyi` files, where names are
considered defined if they are annotated, even if they are not actually assigned to.
The plugin also now patches flake8 so that it reports F822 in fewer situations, for
similar reasons.

## 22.1.0

Expand Down
36 changes: 21 additions & 15 deletions pyi.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
from pathlib import Path
from typing import TYPE_CHECKING, ClassVar, NamedTuple

from flake8 import checker # type: ignore
from flake8.plugins.pyflakes import FlakesChecker # type: ignore
from flake8 import checker # type: ignore[import]
from flake8.plugins.pyflakes import FlakesChecker # type: ignore[import]
from pyflakes import messages # type: ignore[import]
from pyflakes.checker import ( # type: ignore[import]
PY2,
ClassDefinition,
Expand Down Expand Up @@ -149,21 +150,16 @@ def ANNASSIGN(self, node) -> None:
version, we defer evaluation of the annotations (and values on
module level).
"""
if node.value:
# Only bind the *target* if the assignment has value.
# Otherwise it's not really ast.Store and shouldn't silence
# UndefinedLocal warnings.
self.handleNode(node.target, node)
self.handleNode(node.target, node)
if not isinstance(self.scope, FunctionScope):
self.deferHandleNode(node.annotation, node)
if node.value:
# If the assignment has value, handle the *value*...
if isinstance(self.scope, ModuleScope):
# ...later (if module scope).
self.deferHandleNode(node.value, node)
else:
# ...now.
self.handleNode(node.value, node)
# Handle the *value*...
if isinstance(self.scope, ModuleScope):
# ...later (if module scope).
self.deferHandleNode(node.value, node)
else:
# ...now.
self.handleNode(node.value, node)

def LAMBDA(self, node) -> None:
"""This is likely very brittle, currently works for pyflakes 1.3.0.
Expand Down Expand Up @@ -213,6 +209,16 @@ def handleNodeDelete(self, node) -> None:
"""
return

def report(self, messageClass, *args, **kwargs) -> None:
"""Block pyflakes/flake8 from reporting undefined-name errors (F821).

F821 doesn't doesn't work well in stub files,
where names should be considered "defined" if they are annotated,
even if they are not assigned to a value.
"""
if messageClass is not messages.UndefinedName:
super().report(messageClass, *args, **kwargs)


class PyiAwareFileChecker(checker.FileChecker):
def run_check(self, plugin, **kwargs):
Expand Down
6 changes: 3 additions & 3 deletions tests/__all__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ __all__: list[str] # Y035 "__all__" in a stub file must have a value, as it has
__all__: list[str] = ["foo", "bar", "baz"]
__all__ = ["foo", "bar", "baz"]

foo: int = ...
bar: str = ...
baz: list[set[bytes]] = ...
foo: int
bar: str
baz: list[set[bytes]]
12 changes: 12 additions & 0 deletions tests/definitions.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import TypeAlias

class _SpecialForm: ...

Protocol: _SpecialForm
class MyProtocol(Protocol): ...

class WorkingSet:
def require(self) -> None: ...

working_set: WorkingSet
require: TypeAlias = working_set.require
4 changes: 2 additions & 2 deletions tests/forward_refs.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ from typing import Optional, TypeAlias, Union

MaybeCStr: TypeAlias = Optional[CStr]
CStr: TypeAlias = Union[C, str]
__version__: str = ...
__author__: str = ...
__version__: str
__author__: str

def make_default_c() -> C: ...

Expand Down