Skip to content

sift_client.pytest_plugin

CLASS DESCRIPTION
SiftPytestPluginWarning

Base warning for issues raised by the Sift pytest plugin.

SiftPytestStepDrainError

Raised when mid-session drain fails — signals a likely upstream invariant break.

SiftPytestStepDrainWarning

A step's __exit__ raised while the plugin was draining its stack.

FUNCTION DESCRIPTION
client_has_connection

Verify the SiftClient can reach Sift via /ping.

pytest_addoption

Register every CLI flag and pytest ini key declared in _OPTIONS.

pytest_collection_modifyitems

Stash each item's class chain + parametrize path and cluster siblings.

pytest_configure

Register the Sift gate markers and warn on unknown SIFT_* settings.

pytest_report_header

Emit a session-start header with the SDK version and active mode.

pytest_runtest_makereport

Capture per-phase reports and finalize step status after teardown.

pytest_sessionfinish

Drain any parent steps still open at session end (innermost first).

pytest_terminal_summary

Emit a session-end Sift report summary, adapting per mode.

report_context

Lazy session-scoped Sift ReportContext.

sift_client

Default SiftClient resolved from environment variables and ini keys.

step

Create an outer step for the function when the Sift gate is on.

ATTRIBUTE DESCRIPTION
REPORT_CONTEXT

TYPE: Any

SIFT_REPORT_ID_STASH_KEY

SIFT_REPORT_URL_STASH_KEY

REPORT_CONTEXT module-attribute

REPORT_CONTEXT: Any = None

SIFT_REPORT_ID_STASH_KEY module-attribute

SIFT_REPORT_ID_STASH_KEY = StashKey[str]()

SIFT_REPORT_URL_STASH_KEY module-attribute

SIFT_REPORT_URL_STASH_KEY = StashKey[str]()

SiftPytestPluginWarning

Bases: SiftWarning

Base warning for issues raised by the Sift pytest plugin.

SiftPytestStepDrainError

Bases: RuntimeError

Raised when mid-session drain fails — signals a likely upstream invariant break.

SiftPytestStepDrainWarning

Bases: SiftPytestPluginWarning

A step's __exit__ raised while the plugin was draining its stack.

Surfaced at module-teardown or session-end so the drain can continue and pytest test outcomes stay unaffected; the underlying exception is included in the message for debugging.

client_has_connection

client_has_connection(
    pytestconfig: Config, request: FixtureRequest
) -> bool

Verify the SiftClient can reach Sift via /ping.

Consulted at session start by report_context in online mode. A failed ping raises through report_context and aborts the session with pytest.UsageError. Override this fixture in your conftest to use a different reachability signal (e.g. a cached auth token) for environments where pinging is the wrong check. Returns False in --sift-disabled mode without constructing a client.

pytest_addoption

pytest_addoption(parser: Parser) -> None

Register every CLI flag and pytest ini key declared in _OPTIONS.

One loop drives both surfaces — adding a setting is one entry in the registry, not three edits across this function and a docs table.

pytest_collection_modifyitems

pytest_collection_modifyitems(
    config: Config, items: list[Item]
) -> None

Stash each item's class chain + parametrize path and cluster siblings.

Sorts by (file_path, hierarchy_chain, parametrize_path) so sibling items under a shared parent (package, module, class, or parametrize axis) stay contiguous — otherwise a free function sorting between two class methods would tear down + re-open the class step, producing duplicate parents in the report tree.

pytest_configure

pytest_configure(config: Config) -> None

Register the Sift gate markers and warn on unknown SIFT_* settings.

pytest_report_header

pytest_report_header(config: Config) -> str | None

Emit a session-start header with the SDK version and active mode.

Suppressed under -q (negative verbosity), matching how pytest hides its own platform/plugin header.

pytest_runtest_makereport

pytest_runtest_makereport(item: Item, call: CallInfo[Any])

Capture per-phase reports and finalize step status after teardown.

Stashes both rep_<when> (the CallInfo, kept for pytest plugins that expect that conventional attribute) and _sift_phase_<when> (a SimpleNamespace(call, report) used by _resolve_initial_status). The collection-time skip path is strictly gated on _sift_step being unset so it does not duplicate steps the fixture already created.

pytest_sessionfinish

pytest_sessionfinish(
    session: Session, exitstatus: int
) -> None

Drain any parent steps still open at session end (innermost first).

Wrapped so a failure in the inner drain does not prevent the outer one from running. With module_substep removed, this is the sole place where hierarchy parents close — they persist across all tests and only drain when the session ends.

pytest_terminal_summary

pytest_terminal_summary(
    terminalreporter: Any, exitstatus: int, config: Config
) -> None

Emit a session-end Sift report summary, adapting per mode.

The printed panel is suppressed under -q, but programmatic side effects (stashing the report ref for conftest.py, --sift-open-report) still run so other plugins and CI steps can consume the result. The panel shows the outcome (green/red), step and measurement tallies, and a per-mode action: a report link (online), the upload command (offline), or a disabled note.

report_context

report_context(
    request: FixtureRequest, pytestconfig: Config
) -> Generator[ReportContext, None, None]

Lazy session-scoped Sift ReportContext.

The fixture is no longer autouse; it's instantiated on the first call to request.getfixturevalue("report_context"), which today happens inside the gated step, _hierarchy_parents, and _parametrize_parents fixtures. If every test in the session is excluded via the marker gate, this fixture is never resolved and no ReportContext (or teardown subprocess) is created.

What gets yielded depends on the mode:

  • --sift-disabled: a real ReportContext against a placeholder SiftClient with _simulate=True. Every test-results write returns a synthesized response without contacting Sift; no log file is written; the replay subprocess never spawns. Test code that calls step.measure(...) keeps working because bounds are evaluated as usual and routed through the simulate path.
  • --sift-offline: a real ReportContext, but the session-start ping is skipped, all create/update calls go to the JSONL log file, and the import-test-result-log replay subprocess is not spawned at session end.
  • default (online): verify connectivity via client_has_connection before constructing the context. A failed ping aborts the session with pytest.UsageError and points at --sift-offline and --sift-disabled as escape hatches.

The log-file destination is controlled by --sift-log-file; defaults to a temp file when unset.

sift_client

sift_client(pytestconfig: Config) -> SiftClient

Default SiftClient resolved from environment variables and ini keys.

Each credential is read from its environment variable first. The URIs (SIFT_GRPC_URI, SIFT_REST_URI) additionally fall back to the sift_grpc_uri / sift_rest_uri ini keys, since they are stable per-org values that are safe to commit. SIFT_API_KEY is intentionally env-only — use pytest-dotenv (already a project dependency) to load it from a .env file kept out of version control.

Projects that need custom construction (TLS toggles, custom timeouts, etc.) can override this fixture by defining their own sift_client in their conftest.py; pytest fixture resolution prefers the local definition.

In --sift-offline mode the missing-credential check is relaxed: real env vars and ini values still win when set (so the client is constructible against a real backend even though no calls are made), but anything still missing is filled with a placeholder. In --sift-disabled mode the credential resolution is skipped entirely and placeholders are always used.

step

step(
    request: FixtureRequest,
    pytestconfig: Config,
    _parametrize_parents: None,
) -> Generator[NewStep | None, None, None]

Create an outer step for the function when the Sift gate is on.

Resolves the gate via _sift_enabled_for(request.node, ini_default): sift_exclude marker forces off, sift_include forces on, otherwise the sift_autouse ini default applies. When on, requests the session report_context lazily — the first gated test in the session triggers its creation, subsequent gated tests reuse it. In --sift-disabled mode the report context is backed by a SiftClient(_simulate=True) placeholder, so every write returns a synthesized response without contacting Sift.