cursus.registry.strategy_registry

Strategy registry — the single source of truth for the builder strategy library.

This is a dependency-free leaf (imports only stdlib at module top) that maps a routing axis + name to a StrategyInfo (the construction-verb handler class + its declarative knobs). Both the runtime router (builder_templates.resolve_handler) and the introspection tool (cursus strategies CLI / strategies MCP) read from this one registry, so the tool can never drift from what the builder actually does.

Routing axes:
  • sagemaker_step_type — Training / CreateModel / Transform / CradleDataLoading / RedshiftDataLoading / MimsModelRegistrationProcessing (and the no-builder rows Base / Lambda).

  • step_assembly — code / step_args / delegation (the Processing sub-discriminator).

Handlers self-register via @register_strategy(...) in core.base.builder_templates; the ensure_strategies_loaded() lazy import triggers those decorations on first read. The registry imports NOTHING from core.base at module top (only a TYPE_CHECKING hint), so it stays a leaf and there is no import cycle with builder_templates (which imports from here).

exception NoBuilderError[source]

Bases: ValueError

Raised when an (axis, name) has no routable strategy (abstract / builder-less type).

class KnobSpec(name, type='str', default=None, required=False, doc='')[source]

Bases: object

Describes one tunable knob a handler accepts.

name: str
type: str = 'str'
default: Any = None
required: bool = False
doc: str = ''
class StrategyInfo(axis, name, handler, knobs=(), preset_knobs=<factory>, routable=True, verb='', implemented=True)[source]

Bases: object

A registry row: a routing (axis, name) -> a handler class + its knobs.

axis: str
name: str
handler: Callable[..., 'PatternHandler'] | None
knobs: Tuple[KnobSpec, ...] = ()
preset_knobs: Dict[str, Any]
routable: bool = True
verb: str = ''
implemented: bool = True
register_strategy(*, axis, name, knobs=(), preset_knobs=None, routable=True, verb='', implemented=True)[source]

Decorator: register a handler class under (axis, name). Returns the class unchanged.

register_no_builder(*, axis, name, verb='')[source]

Register a non-routable row (e.g. Base / Lambda — abstract or builder-less types).

ensure_strategies_loaded()[source]

Import the handler module so its @register_strategy decorations execute (Edge B).

The only heavy import in this module; guarded + lazy so the registry stays a leaf.

resolve_strategy(axis, name)[source]

Return the routable StrategyInfo for (axis, name), else raise NoBuilderError.

list_strategies(axis=None)[source]

All registered strategies, optionally filtered by axis.

knobs_for(axis, name)[source]

The declarative knobs the strategy at (axis, name) accepts.

axes()[source]

The routing axes that have registered strategies.

axis_name_for_step_type(sagemaker_step_type, step_assembly=None)[source]

Map a step’s (sagemaker_step_type, step_assembly) onto the registry (axis, name) key.

This is the single source of the routing rule — builder_templates.resolve_handler calls it to bind the handler at build time, and the introspection tool calls it for for_step_type — so the tool’s “what would this step bind?” answer can never diverge from the actual router.

Routing is by sagemaker_step_type ONLY (never by step name); Processing is the one type sub-discriminated by step_assembly (code | step_args | delegation, default code).

knob_to_dict(knob)[source]

A KnobSpec as a plain, JSON-serializable dict.

strategy_to_dict(info)[source]

A StrategyInfo as a plain, JSON-serializable dict (handler rendered as its class name).

find_strategies(name, axis=None)[source]

All registered strategies whose name matches, optionally constrained to one axis.

Names are unique within an axis but a bare name may (in principle) appear on more than one axis, so callers that need exactly one row should disambiguate with axis.