Skip to content

Resources

matchlab.resources

Resources, the parts of a step that cannot be serialised.

Every step is built from a class, a settings dict, and a resources dict. Settings reach the plan document and the step's fingerprint. Resources reach neither. A document records a resource's name, never its value, so a plan travels without its credentials and matchlab.document.load asks for the named objects again.

A fingerprint cannot see a resource, so a resource must not change what a step computes. A source is the exception. Its resource is where the rows come from. A source fingerprint hashes those rows, so a change at the origin still moves it.

Two names in this module are easy to confuse.

Resource is an object you build at a call site. It pairs a value with the name a document records for it.

FromResources marks a field in a methodology's class body. It declares that the field is filled from the step's *_resources argument.

A step's constructor brings the two together. It records the name for the document and passes the value into the marked field.

Classes:

  • Resource

    A value paired with the name a document records for it.

Functions:

  • resource_fields

    The fields marked FromResources, inherited ones included.

  • as_resources

    Normalise a *_resources argument, wrapping any bare values.

  • values_of

    The real objects, keyed by the field each fills.

  • names_of

    Field name to resource name, for the fields that have one.

Attributes:

IS_RESOURCE module-attribute

IS_RESOURCE: Final = _IsResource()

FromResources module-attribute

FromResources: TypeAlias = Annotated[T, IS_RESOURCE]

Mark a field as a resource rather than a setting.

Every field of a location or methodology is a setting unless you mark it:

class RelationalDB(Location):
    sql: SQLQuery                    # a setting
    client: FromResources[DBClient]  # a resource

The mark is what a step reads to decide which fields to leave out of the settings it serialises and hashes. Passing a field in the wrong argument raises ResourceError.

Pydantic cannot validate most resource types. Add model_config = ConfigDict(arbitrary_types_allowed=True) to the class that needs it.

Resource

Resource(name: str, value: T)

Bases: Generic[T]


              flowchart TD
              matchlab.resources.Resource[Resource]

              

              click matchlab.resources.Resource href "" "matchlab.resources.Resource"
            

A value paired with the name a document records for it.

Share one Resource between steps that need the same object. Give two locations reading one warehouse the same Resource.

Name a value so a document can ask for it again.

Parameters:

  • name

    (str) –

    What matchlab.document.load looks this up by.

  • value

    (T) –

    The real object, used as-is in this process.

Raises:

Methods:

  • anonymous

    Wrap a value passed without a name.

Attributes:

name instance-attribute

name: str | None = name

value instance-attribute

value: T = value

is_anonymous property

is_anonymous: bool

Whether this resource was passed without a name, so cannot be dumped.

anonymous classmethod

anonymous(value: T) -> Resource[T]

Wrap a value passed without a name.

The step works for the whole life of the process. Only dump refuses it, because a document has no name to record.

resource_fields

resource_fields(methodology_class: type[BaseModel]) -> frozenset[str]

The fields marked FromResources, inherited ones included.

as_resources

as_resources(supplied: dict[str, Any] | None) -> dict[str, Resource]

Normalise a *_resources argument, wrapping any bare values.

A caller can pass client=engine as readily as client=Resource("wh", engine).

values_of

values_of(resources: dict[str, Resource]) -> dict[str, Any]

The real objects, keyed by the field each fills.

names_of

names_of(resources: dict[str, Resource]) -> dict[str, str]

Field name to resource name, for the fields that have one.

What a document records. Anonymous resources are missing from the result, which is how dump spots them.