solprop.output.provenance#

What executed a run and which code it was: the backend, the git commit, the versions.

BackendRecord is what the backend reported about itself, GitProvenance the commit of a development checkout with its dirty flag, and package_versions() the installed versions. All three are outside the resume key (solprop.output.metadata.RunMetadata.hashed()): they say how a run was executed, not what was computed. Provenance, not source: the commit and the versions are recorded, never the source text.

The manual page is docs/guide/results/provenance.md.

Functions

package_versions()

Return the versions of solprop and of the packages a stored file depends on.

Classes

BackendRecord(name, propagator_mode[, settings])

What executed a run, as the backend's own metadata() reported it.

GitProvenance(commit, branch, dirty)

Which commit of solprop produced a file, and whether it was modified.

class solprop.output.provenance.BackendRecord(name, propagator_mode, settings=<factory>)[source]#

Bases: object

What executed a run, as the backend’s own metadata() reported it.

A saved run has to say what produced it and not only what was computed: the thread configuration alone moved one step by a factor of nine (docs/dev/backends.md section 3.4), and without this record a timing comparison has to read the realised kernel pool out of the backend itself.

It is outside the resume key, like the package versions and the git provenance: a run continued on the other backend agrees with an uninterrupted one to 2.2-2.7e-16 and is the same run. What it records is how, not what.

A resumed file keeps the record it was opened with, creation time and all, so the backend it names is the one that started the run. That is append mode’s rule for the whole record and not a special case for this group. The name may be one this package no longer has, such as numba_cpu: a recorded name is not a request, so an old file’s record reads as it was written, in its backend’s own vocabulary.

Attributes:
namestr

The registry name of the backend, for example "numpy_ref" or "native".

propagator_modestr

Which the backend resolved the contract’s "auto" to, or which was asked for: "tabulate" or "recompute".

settingsdict

Everything else the backend reported, for example its thread counts, its plan flag and its wisdom digest. Free-form because it is a backend’s own vocabulary, and JSON-serialisable because it is written to the file.

Examples

>>> from solprop.output.provenance import BackendRecord
>>> record = BackendRecord.from_metadata(
...     {"backend": "native", "propagator_mode": "recompute",
...      "thread_count": 4}
... )
>>> record.name, record.propagator_mode, record.settings
('native', 'recompute', {'thread_count': 4})
classmethod from_metadata(metadata)[source]#

Return the record a backend’s metadata() describes.

Parameters:
metadatacollections.abc.Mapping

What solprop.backends.protocol.Backend.metadata() returned. backend and propagator_mode are named fields here; everything else becomes settings.

Returns:
BackendRecord

The record.

Raises:
OutputError

If either named field is missing.

name: str#
propagator_mode: str#
settings: Mapping[str, JsonValue]#
class solprop.output.provenance.GitProvenance(commit, branch, dirty)[source]#

Bases: object

Which commit of solprop produced a file, and whether it was modified.

Attributes:
commitstr

Full 40-character hexadecimal commit hash of the running checkout.

branchstr

Branch name, or 'HEAD' when the checkout is detached.

dirtybool

Whether the working tree had uncommitted changes to tracked files. A dirty run is reproducible only up to those changes, which is the point of recording it. It is a separate field rather than a suffix on the hash string, so the commit stays parsable.

Examples

>>> from solprop.output.provenance import GitProvenance
>>> record = GitProvenance(commit="0" * 40, branch="main", dirty=False)
>>> len(record.commit), record.dirty
(40, False)
branch: str#
commit: str#
classmethod detect()[source]#

Return the provenance of the running solprop checkout, if there is one.

An installed release is not a checkout, git may be absent, and the package may sit inside an unrelated repository’s worktree – a virtual environment inside a user’s own project, whose git rev-parse answers with that project’s commit; every one of those returns None rather than a placeholder string, so that a caller can tell “no provenance” from “this commit”. The test that separates the last case from a development checkout is whether the repository found actually tracks this file.

Returns:
GitProvenance or None

The commit, branch and dirty flag, or None when they cannot be read.

Examples

>>> from solprop.output.provenance import GitProvenance
>>> record = GitProvenance.detect()
>>> record is None or len(record.commit) == 40
True
dirty: bool#
solprop.output.provenance.package_versions()[source]#

Return the versions of solprop and of the packages a stored file depends on.

Recorded so that a file can be read years later with the same numerics in view. The versions are deliberately outside the configuration hash: upgrading NumPy must not refuse to resume a run. optmat’s version is here too, for a reader; a run that takes a material from optmat carries it again in its material manifest (materials), where it is part of the key.

Returns:
dict

Version strings keyed by 'solprop', 'numpy', 'scipy', 'h5py', 'optmat' (its full version string) and 'python'.

Examples

>>> from solprop.output.provenance import package_versions
>>> sorted(package_versions())
['h5py', 'numpy', 'optmat', 'python', 'scipy', 'solprop']