Skip to main content

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

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file assert_no_pytest_plugin_declarations-20260902062339.tar.gz.

File metadata

File hashes

Hashes for assert_no_pytest_plugin_declarations-20260902062339.tar.gz
Algorithm Hash digest
SHA256 c85114ccaf00107aa051f9ceac462d416bac65535b32b099269339cf8ece706a
MD5 ac16be70314eabedfeec5e1bba9e4bfb
BLAKE2b-256 68f6984567c9b4bdf376631ae6d3be9638d9d82ba908d933a1ba78a57becb1f0

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file assert_no_pytest_plugin_declarations-20260902062339-py3-none-any.whl.

File metadata

File hashes

Hashes for assert_no_pytest_plugin_declarations-20260902062339-py3-none-any.whl
Algorithm Hash digest
SHA256 17da8858a05fd6cf6a986be5161e627e5dcab839eb3c72019f2e12ab81479818
MD5 a72ada259c193ea7e0a576519f67120a
BLAKE2b-256 a9bd7f39cec138301e097eecfa979ab527f6bbffe2b7efd780b2a4eb51bd93b2

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

20260902062339 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page