assert-no-pytest-plugin-declarations
Assert that no conftest declares a pytest plugin.
Why
pytest loads a plugin once. Whether a given pytest_plugins line is
doing anything is therefore decided by files other than the one it is
written in — by a module in another directory, or by a conftest further
up the path that has already asked for the same module. Reading the
line tells you nothing about whether it is load-bearing, and no amount
of reading the file around it will either.
A fixture has two ways to reach a suite that do not have that problem.
It can be inherited, by sitting in a conftest above the suite that wants
it. Or it can be imported, by a from ... import ... written in the
conftest that needs it. Both are ordinary Python that ordinary tools
follow: pylint reports the import nothing uses, mypy resolves it, and
the sibling tool assert-pytest-fixture-name-is-needed reads the name
it binds. A pytest_plugins line is a second mechanism for the same
job that none of the three can see through.
It also holds package dependencies up, silently. A declaration that registers no fixture at all still imports its module, and so keeps that module's own imports load-bearing with nothing anywhere saying so. The line cannot be deleted without a reader first working out, across the whole tree, what would stop being imported if it went.
So the rule is the whole of it. Not a redeclaration, not a duplicate of one further up: any declaration at all.
Installation
pip install assert-no-pytest-plugin-declarations
Usage
# Every test tree this repository publishes
assert-no-pytest-plugin-declarations test
# The same, leaving out tests somebody else wrote
assert-no-pytest-plugin-declarations test \
--exclude 'test/vendor/*'
Options
| Option | Effect |
|---|---|
--exclude PATTERNS |
Comma-separated globs to leave out. |
--annotate |
Print each finding as a GitHub Actions ::error annotation. |
--quiet |
Print nothing; report through the exit code. |
--count |
Print only how many findings there were. |
--verbose |
Print the files read, the findings and a summary. |
--fail-fast |
Stop at the first finding. |
--warn-only |
Always exit 0. |
Exit codes
| Code | Meaning |
|---|---|
| 0 | No file declares a pytest plugin |
| 1 | A file declares a pytest plugin |
| 2 | A tree was missing, unreadable, or would not parse |
What counts as a declaration
Any assignment to the name pytest_plugins, whatever it is assigned:
| Written as | Example |
|---|---|
| A list | pytest_plugins = ["fixtures.aws"] |
| A string | pytest_plugins = "fixtures.aws" |
| An annotation | pytest_plugins: list[str] = [] |
| An addition | pytest_plugins += ["fixtures.aws"] |
| One target of several | pytest_plugins = names = [] |
The value is never inspected, because the declaration this tool most wants to refuse is the one whose value cannot be worked out by reading: a name built elsewhere, or a list a loop appends to. An empty list is a finding like any other. It registers nothing today and is an invitation to the next person to add an entry rather than a conftest.
What is walked
A directory argument is read recursively for *.py files. .git,
__pycache__ and node_modules are skipped, and everything else you
want left out goes in --exclude. Each file is read on its own and
needs nothing from any other, so a single file is as valid an argument
as a tree.
Every Python file is read, not only files named conftest.py. pytest
honours the name in a conftest and in a test module, and a line that
sits anywhere else is one that starts working the day the file is
renamed or its contents are moved.
GitHub Actions
- name: Assert no conftest declares a pytest plugin
uses: 10U-Labs/assert-no-pytest-plugin-declarations@latest
with:
trees: test
annotate defaults to true there, so each finding lands on the line it
names in the diff.
License
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file assert_no_pytest_plugin_declarations-20260902062339.tar.gz.
File metadata
- Download URL: assert_no_pytest_plugin_declarations-20260902062339.tar.gz
- Upload date:
- Size: 31.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c85114ccaf00107aa051f9ceac462d416bac65535b32b099269339cf8ece706a
|
|
| MD5 |
ac16be70314eabedfeec5e1bba9e4bfb
|
|
| BLAKE2b-256 |
68f6984567c9b4bdf376631ae6d3be9638d9d82ba908d933a1ba78a57becb1f0
|
Provenance
The following attestation bundles were made for assert_no_pytest_plugin_declarations-20260902062339.tar.gz:
Publisher:
release.yml on 10U-Labs/assert-no-pytest-plugin-declarations
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
assert_no_pytest_plugin_declarations-20260902062339.tar.gz -
Subject digest:
c85114ccaf00107aa051f9ceac462d416bac65535b32b099269339cf8ece706a - Sigstore transparency entry: 2683819655
- Sigstore integration time:
-
Permalink:
10U-Labs/assert-no-pytest-plugin-declarations@440c8d40c0cea298ac4b073830c552c04eadcf8b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/10U-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@440c8d40c0cea298ac4b073830c552c04eadcf8b -
Trigger Event:
push
-
Statement type:
File details
Details for the file assert_no_pytest_plugin_declarations-20260902062339-py3-none-any.whl.
File metadata
- Download URL: assert_no_pytest_plugin_declarations-20260902062339-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17da8858a05fd6cf6a986be5161e627e5dcab839eb3c72019f2e12ab81479818
|
|
| MD5 |
a72ada259c193ea7e0a576519f67120a
|
|
| BLAKE2b-256 |
a9bd7f39cec138301e097eecfa979ab527f6bbffe2b7efd780b2a4eb51bd93b2
|
Provenance
The following attestation bundles were made for assert_no_pytest_plugin_declarations-20260902062339-py3-none-any.whl:
Publisher:
release.yml on 10U-Labs/assert-no-pytest-plugin-declarations
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
assert_no_pytest_plugin_declarations-20260902062339-py3-none-any.whl -
Subject digest:
17da8858a05fd6cf6a986be5161e627e5dcab839eb3c72019f2e12ab81479818 - Sigstore transparency entry: 2683819719
- Sigstore integration time:
-
Permalink:
10U-Labs/assert-no-pytest-plugin-declarations@440c8d40c0cea298ac4b073830c552c04eadcf8b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/10U-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@440c8d40c0cea298ac4b073830c552c04eadcf8b -
Trigger Event:
push
-
Statement type: