exlab_wizard.controller.metadata_assembly#

Shared metadata value-assembly. Backend Spec §10 / §11.3; design spec §5.

This module owns the two pure value-assembly steps that turn a creation request into a ReadmeContext and a CreationJson. Both the CreationController and the sample-data seeder call them, so the on-disk metadata they produce can never drift between the two paths.

The helpers take explicit parameters instead of reading a controller self: a Config, the equipment id, the core fields, the partitioned readme_extra, a lightweight TemplateDesc (a stand-in for ResolvedTemplate so this module never imports Copier), and injected created / created_by / created_at_iso values (so the output is deterministic and the controller keeps stamping wall-clock time while the seeder stamps a fixed clock).

Importantly this module MUST NOT import exlab_wizard.controller.creation – the pure helpers it needs were moved here (_readme_decls_from_template / _readme_decls_from_config / _os_username) and creation.py re-imports them from this module.

Functions

build_creation_json(*, config, equipment_id, ...)

Assemble the §11.3 CreationJson payload.

build_readme_context(*, config, ...)

Compose the §10 four-layer ReadmeContext.

Classes

TemplateDesc(name, version, source_path[, ...])

Dependency-light stand-in for ResolvedTemplate.

class exlab_wizard.controller.metadata_assembly.TemplateDesc(name, version, source_path, run_scope=None, provenance_path='', extra_readme_fields=<factory>, plugin_order=<factory>)[source]#

Bases: object

Dependency-light stand-in for ResolvedTemplate. Design spec §5.

Carries only the template provenance the assembly helpers need, so a caller can supply it without resolving a Copier template (the seeder passes a sentinel; the controller adapts its ResolvedTemplate).

name#

Template name – maps to ResolvedTemplate.name.

version#

Template version – maps to ResolvedTemplate.exlab_version.

source_path#

Stringified template source path – maps to str(ResolvedTemplate.path).

run_scope#

The run-scope tag persisted on creation.json’s template block; None for project/equipment templates.

provenance_path#

Path (relative to the instance dir, POSIX) of the frozen verbatim template copy written under .exlab-wizard/templates/... at creation time; empty when no copy was made.

extra_readme_fields#

_exlab_readme.fields entries (free-form dicts) used to build the template-layer field declarations.

plugin_order#

Plugin slug ordering (unused by these helpers but kept for symmetry with ResolvedTemplate).

Parameters:
extra_readme_fields: list[dict[str, Any]]#
name: str#
plugin_order: list[str]#
provenance_path: str = ''#
run_scope: RunScope | None = None#
source_path: str#
version: str#
exlab_wizard.controller.metadata_assembly.build_creation_json(*, config, equipment_id, operator, level, run_kind_value, lims_block, template, variables, dst, nas_root, plugins_applied, created_at_iso, sync_status=SyncStatus.PENDING)[source]#

Assemble the §11.3 CreationJson payload.

Redesign §3.1: creation.json always carries the orchestrator block. Redesign §3.3: the block carries the producing equipment’s label so a receiving orchestrator can auto-discover the relayed equipment without a per-equipment config of its own. sync_status is injectable (controller passes PENDING; the seeder passes the per-run scenario) and created_at is the injected created_at_iso.

Parameters:
Return type:

CreationJson

exlab_wizard.controller.metadata_assembly.build_readme_context(*, config, equipment_id, level, label, operator, objective, readme_extra, template, short_id, run_name, run_kind_value, created, created_by)[source]#

Compose the §10 four-layer ReadmeContext.

Maps the template’s _exlab_readme.fields and the config readme.defaults into typed field declarations, partitions the operator-supplied readme_extra values across the template / config / custom layers by id, and fills the auto-managed system block (Backend Spec §10.6) from the injected created / created_by.

Parameters:
Return type:

ReadmeContext