templates_resolver#

class BindPolicy(keep_templates_out_of_working_config: bool = True, allow_entry_overwrite: bool = False)[source]#

Bases: object

Central binding policy knobs for the resolver. This is intentionally narrow: “binding” policy, not “reconcile” policy.

allow_entry_overwrite: bool = False#
keep_templates_out_of_working_config: bool = True#
class ExperimentTemplatesResolver(defaults: DefaultsProvider, sm: SampleManagerProtocol, *, specs_registry: ContainerSpecRegistry, policy: BindPolicy = BindPolicy(keep_templates_out_of_working_config=True, allow_entry_overwrite=False))[source]#

Bases: TemplateResolverBase

Binds defaults templates to a specific run context (sm + defaults) and offers pure template selection/expansion utilities.

Design intent#

  • This object should NOT mutate config.

  • It should NOT decide reconciliation strategy (preserve vs overwrite vs prune).

  • It should provide:
    • target membership lists

    • fully-expanded template dicts for a given entry key

    • canonicalization helpers for compound keys

    • stable per-run facts (RunFacts)

About “alignment_reference_channel changes”#

If you allow earlier steps to rename channels, then the “reference channel” may need to track those renames. This resolver addresses that in two ways:

  1. It snapshots the SM-reported reference and then normalizes it through the rename map (resolve_renamed_channel). This prevents a stale reference if SM reports the “old” name but the run applies renames.

  2. If your SM is itself config-dependent and can change during the run, you should instantiate a new resolver after the rename/reconcile step (or at least rebuild facts). This keeps binding coherent with the current working state.

static resolve_renamed_channel(name: str | None, *, renamed_map: Mapping[str, str], max_hops: int = 32) str | None[source]#

Follow rename chains old->new transitively to avoid stale references. Protects against cycles via max_hops.

cell_map_entry_template(channel: str) Dict[str, Any][source]#
cell_map_perf_entry_template(channel: str) Dict[str, Any][source]#
cell_map_target_channels() list[str][source]#
colocalization_entry_template(canonical_pair_key: str) Dict[str, Any][source]#
entry_template(*, section: str, kind: TemplateKind, key: str, **ctx: Any) Dict[str, Any][source]#
expand(obj: Any, *, channel: str, reference: str | None = None) Any[source]#

Recursively substitute ${channel} and ${reference} in strings within obj.

get_template_method(key)[source]#
registration_entry_template(channel: str) Dict[str, Any][source]#
registration_target_channels() list[str][source]#
run_facts() RunFacts[source]#
sample_channel_entry_template(channel: str) dict[str, Any][source]#
stitching_entry_template(channel: str, *, root_layout: str | None) Dict[str, Any][source]#

Returns an expanded stitching template for channel. The caller decides role (layout vs derived) and any canonicalization.

stitching_target_channels() list[str][source]#
tract_map_entry_template(channel: str) Dict[str, Any][source]#
tract_map_target_channels() list[str][source]#
vasculature_binarization_template(channel: str) Dict[str, Any][source]#
vasculature_perf_binarization_template(channel: str) Dict[str, Any][source]#
vasculature_target_channels() list[str][source]#
PAIRS_ORIENTED = True#
property sm: SampleManagerProtocol#
property stitching_template_keys#
class GroupTemplatesResolver(*, defaults: DefaultsProvider, group_base_dir: Path | None, policy: BindPolicy = BindPolicy(keep_templates_out_of_working_config=True, allow_entry_overwrite=False))[source]#

Bases: TemplateResolverBase

class RunFacts(sample_channels: Tuple[str, ...], alignment_reference: str | None, renamed_map: Mapping[str, str], renamed_items: Tuple[Tuple[str, str], ...])[source]#

Bases: object

Snapshot of SM-derived facts used for binding templates in a single resolver instance.

Notes

  • renamed_map provides ergonomic lookup old->new.

  • renamed_items provides deterministic iteration and hash-friendly representation (if needed).

alignment_reference: str | None#
renamed_items: Tuple[Tuple[str, str], ...]#
renamed_map: Mapping[str, str]#
sample_channels: Tuple[str, ...]#
class TemplateResolverBase(*, defaults: DefaultsProvider, policy: BindPolicy = BindPolicy(keep_templates_out_of_working_config=True, allow_entry_overwrite=False))[source]#

Bases: object

section_missing_only_defaults(section_name: str) Dict[str, Any][source]#

Returns the raw defaults dict for a section (caller performs missing-only merge). If keep_templates_out_of_working_config is True, this function does not strip templates here (because the correct strip scope is section-specific). The adjuster can do template skipping in the deep-merge implementation.

property defaults: DefaultsProvider#
property policy: BindPolicy#
get_current_resolver() TemplateResolverBase[source]#
require_dict(parent: Mapping[str, Any], key: str, *, path: tuple[str, ...] = (), allow_missing: bool = False) dict[str, Any][source]#

Extract a dict-valued child from parent[key].

Parameters:
  • parent – Mapping to extract from.

  • key – Key to extract.

  • path – Cosmetic only; dotted path prefix used for error reporting.

  • allow_missing – If True, missing key returns {}. If False (default), missing key raises.

Returns

dict[str, Any]

The dict value at parent[key].

Raises:
  • KeyError – If key is missing and allow_missing is False.

  • ValueError – If key exists but is not a dict.

set_current_resolver(resolver: TemplateResolverBase) TemplateResolverBase | None[source]#