cursus.step_catalog.naming¶
Single source of truth for step-name <-> file-name conversion in the step catalog.
Historically each discovery module (script_discovery, builder_discovery, contract_discovery)
and the steps.interfaces loader carried its own PascalCase<->snake_case table of compound
acronyms (XGBoost, PyTorch, LightGBM, …). Those tables drifted (e.g. LightGBM was in one
but not another; contract_discovery had none and mangled PyTorchTraining ->
py_torch_training), silently breaking name resolution on whichever path used the stale
table — the root cause of the TSA/SOPA filename races and the “8 of 40 discovered” class of
bug.
This module centralizes that logic:
COMPOUND_ACRONYMS— the one canonical list of multi-word tokens that must not be split on internal capitals.canonical_to_snake()— PascalCase canonical name -> snake_case file stem (PyTorchTraining->pytorch_training).parts_to_pascal()— snake_case parts -> PascalCase canonical name (the inverse).canonical_key()— case/separator-insensitive key for robust fallback matching.
New frameworks are added in ONE place here. Better still, canonical_key() enables a
normalized directory scan so most new acronyms resolve with no table edit at all.
- is_job_type_variant(step_name)[source]¶
Return True if
step_nameends in a known job-type suffix (foo_training).Matches on a trailing
_<suffix>so it only fires on snake_case variant names and never on a base step whose name merely contains a job word.
- canonical_to_snake(canonical_name)[source]¶
Convert a PascalCase canonical step name to its snake_case file stem.
Compound acronyms are protected (
XGBoostTraining->xgboost_training, notx_g_boost_training); the remaining PascalCase is split on capital boundaries, including runs of capitals followed by a word (MyABCStep->my_abc_step).
- parts_to_pascal(parts)[source]¶
Convert snake_case parts to a PascalCase canonical name (inverse of split).
["xgboost", "training"]->"XGBoostTraining". Parts matching a known compound acronym keep its canonical casing; others are simply capitalized.
- canonical_key(name)[source]¶
Collapse a name/stem to a case- and separator-insensitive key.
"XGBoostTraining","xgboost_training"and"XGBoost_Training"all map to"xgboosttraining". Used as a robust fallback when the exact convention name misses, so a new acronym step still resolves without editingCOMPOUND_ACRONYMS.
- resolve_base_step_name(node_name, known_step_names)[source]¶
Resolve a DAG node name to its base registry step name — ROBUSTLY, without a hardcoded suffix list.
A node is
<StepName>[_<suffix>...]where<suffix>is an arbitrary label (job_type, data-source tag, split name — e.g._training,_munged,_sampling,_tagging,_baseline,_embedding). Since job_type is now open (any lowercase-alnum, deep dive Tranche 3), the suffix is NOT drawn from a fixed set, so matching a trailing token againstJOB_TYPE_SUFFIXESmisses real nodes. Instead: strip trailing_segmentgroups one at a time and return the first prefix that is an actual known step name (matched viacanonical_key(), so compound-acronym casing likeXgboostMtvsXGBoostMTalso resolves). The step registry — not a suffix allowlist — is the authority for what a base name is.Returns the canonical known step name, or
Noneif no prefix matches.
- split_job_type_suffix(node_name, known_step_names)[source]¶
Split a node into
(base_step_name, suffix_or_None)using the registry (robust).('TabularPreprocessing_training', [...]) -> ('TabularPreprocessing', 'training');('CradleDataLoading_munged', [...]) -> ('CradleDataLoading', 'munged');('CradleDataLoading', [...]) -> ('CradleDataLoading', None). Unlike aJOB_TYPE_SUFFIXEScheck, this handles ANY suffix because the base is validated against the actual step registry viaresolve_base_step_name(). Returns(node_name, None)if the node doesn’t resolve to a known base.