stricttest v0.2.0 /python.src.stricttest.plugin
On this page

The pytest11 entry point: hook ordering that binds the floor before conftest import, marker registration, and the autouse cwd and push-guard fixtures.

#python.src.stricttest.plugin

#python.src.stricttest.plugin

The pytest plugin entry point (pytest11).

Installing stricttest IS adoption. Every hook below binds unconditionally once the project's safety keys validate; there is no opt-in switch and no runtime degradation path -- a project either declares its stance and gets the floor, or the session aborts.

Ordering matters and is deliberate:

  1. pytest_load_initial_conftests -- the earliest hook that already has a

parsed ini file. Validation, the TMPDIR refusal, the env-poisoning floor and the socket guard all bind HERE, before any conftest module is imported. A conftest that reads HOME at import time therefore sees the throwaway one.

  1. pytest_configure -- marker registration and a second TMPDIR check now

that --basetemp is fully resolved.

  1. pytest_collection_modifyitems / pytest_xdist_node_collection_finished

-- the bare-run threshold, once the selected test count is known.

#settings

python
def settings() -> Settings

The resolved settings for this session (raises if not yet configured).

#pytest_addoption

python
def pytest_addoption(parser)

#pytest_load_initial_conftests

python
def pytest_load_initial_conftests(early_config, parser, args)

Bind the whole floor before any conftest module is imported.

#pytest_configure

python
def pytest_configure(config)

#pytest_unconfigure

python
def pytest_unconfigure(config)

Tear down the throwaway env directory for this process.

#pytest_collection_modifyitems

python
def pytest_collection_modifyitems(config, items)

Refuse a bare full-ish run outside the sandbox.

trylast so this runs AFTER pytest's own -k / -m deselection, which mutates items in place -- the count then reflects the SELECTED tests, so a -k slice of a big file stays under the threshold and runs bare instead of being refused on the pre-deselection total.

Enforcement is split by execution topology:

  • Single process (no xdist): items is the full set here -- enforce.
  • xdist worker (PYTEST_XDIST_WORKER set): a shard; defer to the

controller so the error surfaces once, not once per worker.

  • xdist controller (numprocesses set): items is empty here because

workers do the collecting -- defer to pytest_xdist_node_collection_finished which sees the real count.

#pytest_xdist_node_collection_finished

python
def pytest_xdist_node_collection_finished(node, ids)

xdist controller: enforce the threshold once collection lands.

The controller does not collect items itself; each worker reports its collected ids here. All workers collect the same full set, so the first report carries the true test count -- enforce on it.

optionalhook so the plugin loads cleanly in projects without xdist.

#_stricttest_chdir_into_tmp

python
def _stricttest_chdir_into_tmp(request, tmp_path, monkeypatch)

Autouse: never let a test run with the process cwd at the real repo.

A test whose process cwd is the real repo can make every unanchored git command (status/commit/push, file generation, scaffolding) operate on the development repo. Chdir-ing each test into its own tmp_path makes implicit repo-cwd reliance a visible failure instead of silent real-repo pollution. Fixtures that chdir into their own tmp_path (the same tmp_path object) compose cleanly -- they land in the same directory. Tests that genuinely need the repo cwd must anchor explicitly, or opt out with @pytest.mark.repo_cwd.

#_stricttest_guard_nonlocal_push

python
def _stricttest_guard_nonlocal_push()

Autouse guard: block any real git push to a non-local remote.

Search