From 2283105755a0a6940820771d038eb240bc3653ae Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Tue, 4 Mar 2025 13:40:10 +0100
Subject: [PATCH 1/2] add coverage-conditional, rejig some config stuff
---
flake8_async/__init__.py | 7 ++++---
flake8_async/visitors/helpers.py | 2 +-
flake8_async/visitors/visitor123.py | 3 +--
flake8_async/visitors/visitor91x.py | 2 +-
pyproject.toml | 32 +++++++++++++++++++++++++++++
tests/test_config_and_args.py | 20 +++++++++++++++++-
tox.ini | 31 +++-------------------------
7 files changed, 61 insertions(+), 36 deletions(-)
diff --git a/flake8_async/__init__.py b/flake8_async/__init__.py
index d5e42ff8..92af9654 100644
--- a/flake8_async/__init__.py
+++ b/flake8_async/__init__.py
@@ -138,7 +138,7 @@ def __init__(
self.module: cst.Module = cst_parse_module_native(source)
@classmethod
- def from_filename(cls, filename: str | PathLike[str]) -> Plugin: # pragma: no cover
+ def from_filename(cls, filename: str | PathLike[str]) -> Plugin:
# only used with --runslow
with tokenize.open(filename) as f:
source = f.read()
@@ -204,7 +204,7 @@ def add_options(option_manager: OptionManager | ArgumentParser):
'lines with "# noqa" at the end.'
),
)
- else: # if run as a flake8 plugin
+ else: # pragma: no-cov-no-flake8
Plugin.standalone = False
# Disable ASYNC9xx calls by default
option_manager.extend_default_ignore(default_disabled_error_codes)
@@ -380,7 +380,7 @@ def get_matching_codes(
}
assert all_codes
- if options.autofix and not Plugin.standalone:
+ if options.autofix and not Plugin.standalone: # pragma: no-cov-no-flake8
print("Cannot autofix when run as a flake8 plugin.", file=sys.stderr)
sys.exit(1)
autofix_codes = set(get_matching_codes(options.autofix, all_codes))
@@ -457,6 +457,7 @@ def parse_async200_dict(raw_value: str) -> dict[str, str]:
# not run if flake8 is installed
+# TODO: this is not tested at all atm, I'm not even sure if it works
def parse_per_file_disable( # pragma: no cover
raw_value: str,
) -> dict[str, tuple[str, ...]]:
diff --git a/flake8_async/visitors/helpers.py b/flake8_async/visitors/helpers.py
index 642c62bd..4646fc4f 100644
--- a/flake8_async/visitors/helpers.py
+++ b/flake8_async/visitors/helpers.py
@@ -371,7 +371,7 @@ def with_has_call(
"""
if isinstance(base, str):
- base = (base,) # pragma: no cover
+ base = (base,)
# build matcher, using SaveMatchedNode to save the base and the function name.
matcher = m.Call(
diff --git a/flake8_async/visitors/visitor123.py b/flake8_async/visitors/visitor123.py
index 58237c18..32fd5a06 100644
--- a/flake8_async/visitors/visitor123.py
+++ b/flake8_async/visitors/visitor123.py
@@ -78,8 +78,7 @@ def visit_ExceptHandler(self, node: ast.ExceptHandler):
self.exception_group_names = {node.name}
# ast.TryStar added in py311
- # we run strict codecov on all python versions, this one doesn't run on bool:
- if code is None: # pragma: no branch
+ if code is None:
code = "ASYNC911" if self.has_yield else "ASYNC910"
return (
diff --git a/pyproject.toml b/pyproject.toml
index 30bbbd85..ae0b6180 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,6 +14,34 @@ force-exclude = "tests/autofix_files/.*.py"
[tool.codespell]
ignore-words-list = 'spawnve'
+[tool.coverage.coverage_conditional_plugin.rules]
+no-cov-has-flake8 = "is_installed('flake8')"
+no-cov-no-flake8 = "not is_installed('flake8')"
+no-cov-py-lt-311 = "sys.version_info < (3, 11)"
+
+[tool.coverage.paths]
+source = [
+ "flake8_async",
+ "*/site-packages/flake8_async"
+]
+
+[tool.coverage.report]
+exclude_lines = [
+ # Have to re-enable the standard pragma
+ "pragma: no cover",
+ # Don't complain about abstract methods, they aren't run:
+ "@(abc\\.)?abstractmethod",
+ # Don't check guarded type imports
+ "if (typing.)?TYPE_CHECKING:"
+]
+fail_under = 100
+skip_covered = true
+skip_empty = true
+
+[tool.coverage.run]
+branch = true
+plugins = ["coverage_conditional_plugin"]
+
[tool.isort]
only_modified = true
profile = "black"
@@ -45,6 +73,10 @@ reportUnnecessaryTypeIgnoreComment = false
reportUnusedCallResult = false
strict = ["*.py", "tests/*.py", "flake8_async/**/*.py"]
+[tool.pytest.ini_options]
+filterwarnings = ["error"]
+testpaths = ["tests"]
+
[tool.ruff]
extend-exclude = [
".*",
diff --git a/tests/test_config_and_args.py b/tests/test_config_and_args.py
index a999a095..3d3c03ec 100644
--- a/tests/test_config_and_args.py
+++ b/tests/test_config_and_args.py
@@ -282,6 +282,24 @@ def test_async200_from_config_subprocess(tmp_path: Path):
assert res.stdout == err_msg.encode("ascii")
+def test_trio200_warning(tmp_path: Path):
+ fpath = tmp_path / "foo.py"
+ fpath.touch()
+ res = subprocess.run(
+ ["flake8-async", "--trio200-blocking-calls=foo->bar", "foo.py"],
+ cwd=tmp_path,
+ capture_output=True,
+ check=False,
+ encoding="utf8",
+ )
+ assert res.returncode == 0
+ assert res.stderr.endswith(
+ "UserWarning: trio200-blocking-calls has been deprecated in favor of "
+ "async200-blocking-calls\n warnings.warn(\n"
+ )
+ assert not res.stdout
+
+
@pytest.mark.skipif(flake8 is None, reason="flake8 is not installed")
def test_async200_from_config_subprocess_cli_ignore(tmp_path: Path):
_ = _test_async200_from_config_common(tmp_path)
@@ -297,7 +315,7 @@ def test_async200_from_config_subprocess_cli_ignore(tmp_path: Path):
assert res.returncode == 0
-def test_900_default_off(capsys: pytest.CaptureFixture[str]):
+def test_900_default_off():
res = subprocess.run(
["flake8-async", "tests/eval_files/async900.py"],
capture_output=True,
diff --git a/tox.ini b/tox.ini
index ab012d9c..fcaf8747 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,14 +11,15 @@ deps =
flake8_7: flake8>=7.0
flake8_6: flake8>=6.0, <7.0
pytest
- pytest-cov
+ coverage
+ coverage-conditional-plugin
pytest-xdist
hypothesis
# 0.3.3 adds py313 support
hypothesmith >= 0.3.3
trio
commands =
- pytest {posargs:-n auto}
+ coverage run -m pytest {posargs:-n auto}
[testenv:docs]
description = Generate docs locally
@@ -32,29 +33,3 @@ skip_install = True
commands =
make clean
make html
-
-# Settings for other tools
-[pytest]
-addopts =
- --cov=flake8_async
- --cov-branch
- --cov-report=term-missing:skip-covered
- --cov-fail-under=100
-filterwarnings =
- error
-
-[coverage:paths]
-source =
- flake8_async
- */site-packages/flake8_async
-
-[coverage:report]
-exclude_lines =
- # Have to re-enable the standard pragma
- pragma: no cover
-
- # Don't complain about abstract methods, they aren't run:
- @(abc\.)?abstractmethod
-
- # Don't check guarded type imports
- if (typing.)?TYPE_CHECKING:
From 77ce3a339492205dd71e70098d1d81f2ef08b13e Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Tue, 4 Mar 2025 15:28:28 +0100
Subject: [PATCH 2/2] add back pytest-cov
---
tox.ini | 1 +
1 file changed, 1 insertion(+)
diff --git a/tox.ini b/tox.ini
index fcaf8747..f9578884 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,6 +11,7 @@ deps =
flake8_7: flake8>=7.0
flake8_6: flake8>=6.0, <7.0
pytest
+ pytest-cov # to make it easy to pass --no-cov
coverage
coverage-conditional-plugin
pytest-xdist