tests.conftest module¶
Shared pytest fixtures and cross-file test helpers.
- tests.conftest.PROJECT_ROOT = PosixPath('/home/runner/work/repomatic/repomatic')¶
Root of the repository.
- tests.conftest.IN_GIT_CHECKOUT = True¶
Whether the suite runs from a git checkout, not from an sdist or a tag tarball.
A packager’s source carries no git history, holds a release’s frozen workflows, and, for an sdist, a
pyproject.tomlrewritten and symlinks dereferenced by the build backend. The tests markedrepo_maintenancecheck those properties of a development checkout, sopytest_collection_modifyitems()skips them everywhere else.
- tests.conftest.PACKAGE_DIR = PosixPath('/home/runner/work/repomatic/repomatic/repomatic')¶
Root of the package whose sources the conformance tests scan.
- tests.conftest.PACKAGE_FILES = [PosixPath('/home/runner/work/repomatic/repomatic/repomatic/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/__main__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/awesome_toc.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/broken_links.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cache.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/changelog.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/github.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/lint.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/main.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/release.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/sample.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/setup.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cli/sync.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cloudflare.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/cloudflare_r2.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/compat.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/config.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/data/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/data/awesome_template/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/dep_graph.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/dep_policy.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/dep_report.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/dep_sources.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/uv.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/deps/vulnerable_deps.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/docs.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/file_inventory.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/file_ops.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/forge.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/frontmatter.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/git_ops.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/actions.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/ci_status.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/dev_release.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/gh.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/issue.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/job_timings.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/matrix.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/pr.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/pr_body.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/release_sync.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/releases.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/sponsor.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/status.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/token.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/unsubscribe.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/github/workflow_sync.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/gitignore.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/hashing.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/http.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/humanize.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/images.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/init_project.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/labels.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/lint_repo.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/mailmap.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/matrix_axes.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metadata/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metadata/core.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metadata/env.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metadata/git.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metadata/matrix.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metadata/project.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metric_chart.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/metrics.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/npm.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/pages_redirects.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/pypi.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/pyproject.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/registry.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/attestation.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/binaries_page.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/binary.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/checksums.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/prepare_release.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/version_sync.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/release/virustotal.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/runner_catalog.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/runner_images.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/setup_guide.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/sync_ops.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/tabular.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/templates/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/tooling/__init__.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/tooling/bundle.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/tooling/plugin.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/tooling/tool_registry.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/tooling/tool_runner.py'), PosixPath('/home/runner/work/repomatic/repomatic/repomatic/versions.py')]¶
Every Python module shipped in the package.
Sorted because
@pytest.mark.parametrizederives test IDs from iteration order, andpytest-xdistaborts a run whose workers disagree on them.
- tests.conftest.SITE_ANCHOR_RE = re.compile('https://repomatic\\.net/(?P<page>[\\w-]+)#(?P<anchor>[\\w-]+)')¶
A link into one section of the published documentation.
- tests.conftest.WORKFLOWS_DIR = PosixPath('/home/runner/work/repomatic/repomatic/.github/workflows')¶
Directory holding this repository’s own workflow files.
- tests.conftest.docs_heading_slug(title)[source]¶
The anchor the published Sphinx site derives from a heading.
Follows the docutils section-id algorithm (lowercase, every non-alphanumeric run collapsed to one hyphen, trimmed), which is what the published page exposes as
id=attributes.
- tests.conftest.docs_heading_anchors(page)[source]¶
Anchors a page of
docs/exposes: heading slugs and explicit targets.Heading slugs follow
docs_heading_slug().
- tests.conftest.assert_shipped_text_reads_true_downstream(origin, text)[source]¶
Check a text that travels downstream cites nothing a repository lacks.
A bundled configuration and a generated workflow comment both land in repositories that hold no copy of this project’s
claude.md: theagentcomponent that shipped its sections retired in7.14.0. A pointer to that file is a dead end there. So such a text states its rationale inline, or cites a section of the published documentation, whose anchor is held here to a heading that exists.
- tests.conftest.pytest_configure(config)[source]¶
Register the marker local to this suite.
Not in
[tool.pytest] markers, which must match the template bundled inrepomatic/data/pytest.toml.- Return type:
- tests.conftest.pytest_collection_modifyitems(config, items)[source]¶
Skip the
repo_maintenancetests outside a git checkout.See
IN_GIT_CHECKOUT.- Return type:
- tests.conftest.WORKFLOWS_WITH_CONCURRENCY_BLOCK = ('autofix.yaml', 'changelog.yaml', 'debug.yaml', 'docs.yaml', 'labels.yaml', 'lint.yaml', 'metrics.yaml', 'release.yaml', 'self-maintenance.yaml', 'tests.yaml')¶
Workflows that actually define a concurrency block, read off disk.
Derived rather than hand-listed because two test modules assert against it from opposite directions, and a hand-listed pair drifted apart once already: a workflow can be exempt from the requirement and still carry a block, which no list of intentions can express.
- tests.conftest.WORKFLOWS_WITHOUT_CONCURRENCY_BLOCK = ('_release-build.yaml', '_release-engine.yaml', 'autolock.yaml', 'cancel-runs.yaml', 'unsubscribe.yaml')¶
The complement of
WORKFLOWS_WITH_CONCURRENCY_BLOCK.
- tests.conftest.skip_unless_tool_runs(name)[source]¶
Skip the calling test when a registry tool cannot run on this machine.
A test that lints generated output reads the tool’s verdict off its exit code, and a
uvxresolution that fails offline exits non-zero too. Probing with--versionfirst keeps the two apart, so whatever the real invocation returns afterwards is the tool’s opinion of the content rather than a fetch failure misread as a defect in the generator.Only a developer with no network ever takes the skip: CI is the enforcement point, and a tool it cannot fetch fails the job long before this runs.
- tests.conftest.load_workflow(workflow_name)[source]¶
Load and parse one of this repository’s workflow YAML files.
The one loader behind every test that reads a workflow off disk, so they all parse the same bytes the same way.
- tests.conftest.hermetic_git(monkeypatch)[source]¶
Shield temporary git repos from the developer’s own git configuration.
Commit signing, hooks, templates and identity from the global or system config would otherwise leak into repos a test builds under
tmp_pathand break hermeticity in machine-specific ways.
- class tests.conftest.FakeResponse(data)[source]¶
Bases:
objectMinimal
urlopenresponse double: a byte body behind a context manager.Stands in for the object
repomatic.http.get_jsonreads, so network tests patchrepomatic.http.urlopenwithreturn_value=FakeResponse(...).
- tests.conftest.pat_results(**overrides)[source]¶
Build a
PatPermissionResultswhere every check passes by default.Each keyword names a
PatPermissionResultsfield and replaces its(passed, message)tuple, so a test spells out only the checks whose outcome it cares about and the rest read as the happy path.
- tests.conftest.metadata_from_pyproject(tmp_path, monkeypatch, content)[source]¶
Build a
Metadatareading a throwawaypyproject.tomlholding content.Repointing
Metadata.pyproject_pathis what isolates the instance from the repository’s ownpyproject.toml: the class reads that path lazily, so the patch has to be in place before the first property is touched. The autouse_reset_metadatafixture clears the cached values afterwards.
- tests.conftest.cache_env(monkeypatch, tmp_path)[source]¶
Point the repomatic cache at a per-test directory, auto-purge disabled.
Returns the cache root path so tests can assert on its contents.
- tests.conftest.patch_gh(module, **mock_kwargs)[source]¶
Patch a module’s
ghdispatch points with one shared mock.Read paths go through
gh_api_json(which calls theghmodule’srun_gh_command) while write paths call the name imported into module directly; patching both with the same mock keeps a test’s single call sequence intact across the two layers. Bind the module withfunctools.partialfor a per-file shorthand.
- tests.conftest.attribute_docstrings(body)[source]¶
Yield
(line, owner, text)for each attribute docstring in body.An attribute docstring is the bare string literal following an assignment.
ast.get_docstringcannot see one, yet it is this project’s convention for documenting a dataclass field or a module constant, andautomodule ... :undoc-members:renders it.