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

Drop support for Python 3.7 #393

Merged
merged 3 commits into from
Jun 17, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#
# flake8-bugbear rules that cause too many false positives:
# B905 "`zip()` without an explicit `strict=True` parameter --
# the `strict` parameter was introduced in Python 3.10; we support Python 3.7
# the `strict` parameter was introduced in Python 3.10; we support Python 3.8
# B907 "Use !r inside f-strings instead of manual quotes" --
# produces false positives if you're surrounding things with double quotes

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
timeout-minutes: 5
strategy:
matrix:
python-version: ["3.7", "3.11"]
python-version: ["3.8", "3.11"]
fail-fast: false
steps:
- uses: actions/checkout@v3
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
strategy:
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
fail-fast: false
steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
rev: 23.3.0 # must match pyproject.toml
hooks:
- id: black
language_version: python3.7
language_version: python3.8
- repo: https://github.com/pycqa/isort
rev: 5.12.0 # must match pyproject.toml
hooks:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Bugfixes:
multiple definitions in the same file (e.g. across two branches of an `if
sys.version_info >= (3, 10)` check). This bug has now been fixed.

Other changes:
* flake8-pyi no longer supports being run on Python 3.7.

## 23.5.0

* flake8-pyi no longer supports being run with flake8 <5.0.4.
Expand Down
29 changes: 9 additions & 20 deletions pyi.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,9 @@ def _has_bad_hardcoded_returns(
):
return False

if not _non_kw_only_args_of(method.args): # weird, but theoretically possible
if (
not method.args.posonlyargs and not method.args.args
): # weird, but theoretically possible
AlexWaygood marked this conversation as resolved.
Show resolved Hide resolved
return False

method_name, returns = method.name, method.returns
Expand Down Expand Up @@ -585,13 +587,6 @@ def _is_bad_TypedDict(node: ast.Call) -> bool:
)


def _non_kw_only_args_of(args: ast.arguments) -> list[ast.arg]:
"""Return a list containing the pos-only args and pos-or-kwd args of `args`"""
# pos-only args don't exist on 3.7
pos_only_args: list[ast.arg] = getattr(args, "posonlyargs", [])
return pos_only_args + args.args


def _is_assignment_which_must_have_a_value(
target_name: str | None, *, in_class: bool
) -> bool:
Expand Down Expand Up @@ -1581,7 +1576,7 @@ def _check_exit_method( # noqa: C901
self, node: ast.FunctionDef | ast.AsyncFunctionDef, method_name: str
) -> None:
all_args = node.args
non_kw_only_args = _non_kw_only_args_of(all_args)
non_kw_only_args = all_args.posonlyargs + all_args.args
num_args = len(non_kw_only_args)
varargs = all_args.vararg

Expand Down Expand Up @@ -1747,7 +1742,7 @@ def _visit_synchronous_method(self, node: ast.FunctionDef) -> None:
if all_args.kwonlyargs:
return

non_kw_only_args = _non_kw_only_args_of(all_args)
non_kw_only_args = all_args.posonlyargs + all_args.args

# Raise an error for defining __str__ or __repr__ on a class, but only if:
# 1). The method is not decorated with @abstractmethod
Expand Down Expand Up @@ -1785,17 +1780,11 @@ def _Y019_error(
) -> None:
cleaned_method = deepcopy(node)
cleaned_method.decorator_list.clear()
first_arg = _non_kw_only_args_of(cleaned_method.args)[0]
first_arg.annotation = None
non_kw_only_args = cleaned_method.args.posonlyargs + cleaned_method.args.args
non_kw_only_args[0].annotation = None
new_syntax = _unparse_func_node(cleaned_method)
new_syntax = re.sub(rf"\b{typevar_name}\b", "Self", new_syntax)
self.error(
# pass the node for the first argument to `self.error`,
# rather than the function node,
# as linenos differ in Python 3.7 and 3.8+ for decorated functions
node.args.args[0],
Y019.format(typevar_name=typevar_name, new_syntax=new_syntax),
)
self.error(node, Y019.format(typevar_name=typevar_name, new_syntax=new_syntax))

def _check_instance_method_for_bad_typevars(
self,
Expand Down Expand Up @@ -1904,7 +1893,7 @@ def visit_arg(self, node: ast.arg) -> None:
self.generic_visit(node)

def visit_arguments(self, node: ast.arguments) -> None:
args = _non_kw_only_args_of(node)
args = node.posonlyargs + node.args
defaults = [None] * (len(args) - len(node.defaults)) + node.defaults
assert len(args) == len(defaults)
for arg, default in zip(args, defaults):
Expand Down
13 changes: 6 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ maintainers = [
description = "A plugin for flake8 to enable linting .pyi stub files."
license = { text = "MIT" }
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.8"
keywords = [
"flake8",
"pyi",
Expand All @@ -38,7 +38,6 @@ classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand All @@ -61,12 +60,12 @@ dependencies = [

[project.optional-dependencies]
dev = [
"black==23.3.0", # Must match .pre-commit-config.yaml
"flake8-bugbear==23.6.5; python_version >= '3.8'",
"black==23.3.0", # Must match .pre-commit-config.yaml
"flake8-bugbear==23.6.5",
"flake8-noqa==1.3.1",
"isort==5.12.0; python_version >= '3.8'", # Must match .pre-commit-config.yaml
"isort==5.12.0", # Must match .pre-commit-config.yaml
"mypy==1.3.0",
"pre-commit-hooks==4.4.0", # Must match .pre-commit-config.yaml
"pre-commit-hooks==4.4.0", # Must match .pre-commit-config.yaml
"pytest==7.3.2",
"types-pyflakes<4",
]
Expand All @@ -84,7 +83,7 @@ skip = ["tests/imports.pyi"]
skip_gitignore = true

[tool.black]
target-version = ['py37']
target-version = ['py38']
skip-magic-trailing-comma = true
force-exclude = ".*\\.pyi"

Expand Down
7 changes: 7 additions & 0 deletions tests/defaults.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,10 @@ def f38(x: bytes = b"a_very_long_byte_stringgggggggggggggggggggggggggggggggggggg

foo: str = "a_very_long_stringgggggggggggggggggggggggggggggggggggggggggggggg" # Y053 String and bytes literals >50 characters long are not permitted
bar: bytes = b"a_very_long_byte_stringggggggggggggggggggggggggggggggggggggg" # Y053 String and bytes literals >50 characters long are not permitted

# Tests for PEP-570 syntax
def f39(x: "int", /) -> None: ... # Y020 Quoted annotations should never be used in stubs
Copy link
Collaborator

Choose a reason for hiding this comment

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

beautiful

def f40(x: int, /) -> None: ...
def f41(x: int, /, y: "int") -> None: ... # Y020 Quoted annotations should never be used in stubs
def f42(x: str = "y", /) -> None: ...
def f43(x: str = os.pathsep, /) -> None: ... # Y011 Only simple default values allowed for typed arguments
7 changes: 0 additions & 7 deletions tests/defaults_py38.pyi

This file was deleted.

11 changes: 2 additions & 9 deletions tests/quotes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,7 @@ class DocstringAndPass:
"""Docstring""" # Y021 Docstrings should not be included in stubs
pass # Y012 Class body must not contain "pass"

# These two shouldn't trigger Y020 -- empty strings can't be "quoted annotations"
# These three shouldn't trigger Y020 -- empty strings can't be "quoted annotations"
k = "" # Y052 Need type annotation for "k"
el = r"" # Y052 Need type annotation for "el"

# The following should also pass,
# But we can't test for it in CI, because the error message is *very* slightly different on 3.7
#
# On 3.7:
# m = u"" # Y015 Bad default value. Use "m = ..." instead of "m = ''"
# On 3.8+:
# m = u"" # Y015 Bad default value. Use "m = ..." instead of "m = u''"
m = u"" # Y052 Need type annotation for "m"