orthonym.routing#

Note

Internal API. Names and behaviour may change between releases.

Orthonym Routing Module.

Class-first dispatcher routing input mol -> handler before naming pipeline (a phase,..04).

Public exports per internal notes: - ClassFirstRouter — per-instance class-first dispatcher . - ClassDispatchResult — frozen dataclass returned by dispatch . - StoutClass — StrEnum of dispatch class identifiers . - ClassDispatchEntry — frozen dataclass per DISPATCH_TABLE row . - DISPATCH_TABLE — OrderedDict[StoutClass, ClassDispatchEntry];

module-level frozen post-import .

  • dispatch / get_dispatch_stats / reset_dispatch_stats — module-level convenience wrappers .

Internal helpers (_register_dispatch, _is_*, _handle_*, _invoke_audit_log) are PRIVATE and intentionally not exported per internal notes (no public plugin API; + extracts one if needed).

class orthonym.routing.ClassFirstRouter(*, _audit_log=None)#

Bases: object

: Class-first dispatcher; replaces the implicit cascade in _name_impl.

Three responsibilities (158-internal notes <domain>):

  1. dispatch — walks DISPATCH_TABLE in priority order; first-match-wins. Returns a frozen ClassDispatchResult whose handler field the caller invokes to produce the name string. The dispatcher does NOT call the handler itself per +.

  2. get_dispatch_stats — per-instance histogram counter accessor. Returns a defensive copy so callers cannot mutate internal state.

  3. reset_dispatch_stats — explicit reset for batch-run boundaries.

Construction: ClassFirstRouter with no args. Reads ORTHONYM_DISPATCH_AUDIT env var by default for the audit-log gate ; the constructor kwarg _audit_log overrides for testing.

STAT_KEYS: tuple = ('salt', 'radical', 'zwitterion', 'anion_retained', 'cation_retained', 'cation_quaternary', 'ester_anion_zwitterion', 'mixed_sign_zwitterion', 'anion_small', 'poly_anion', 'multi_component_neutral', 'multiplicative', 'carbohydrate_lookup', 'natural_product', 'peptide', 'retained_name', 'amino_acid', 'skeletal_replacement', 'cyclophane', 'decomposition_pre_general', 'general', 'inorganic_acid', 'organometallic', 'lipid', 'mononuclear_hydride', 'chalcogen_chain', 'polyazane', 'free_homonuclear_g14_hydride', 'dinuclear_hydride', 'ketene', 'ring_chalcogen_oxide', 'hydro_fused_peroxol', 'thioimide', 'nitramide_substituted', 'cyclic_polyester', 'azinic_derivative', 'heterone', 'sulfine', 'cumulative_zwitterion', 'ylide', 'pseudoketone_hetero', 'acyl_chalcogenchain_pseudoketone', 'lambda5_phosphanimine', 'heteroimine', 'lambda_sulfane_imine_oxide', 'polychalcogen_oxide', 'catenated_hydride', 'heterochalcogen_aba', 'homonuclear_pnictogen_chain', 'pnictogen_carboxylic_acid', 'mononuclear_hydride_added_carbon', 'inositol', 'nucleoside')#
dispatch(mol, smiles, canonical_smiles, features=None, **kwargs)#

: two-tier predicate evaluation; first-match-wins.

Walks DISPATCH_TABLE in priority order (sorted-by-priority). **kwargs is forwarded verbatim to predicate calls so callers can thread _skip_decomposition (option (b)) and _style (RETAINED_NAME / AMINO_ACID predicates) without bloating the ClassDispatchEntry shape.

Returns:

ClassDispatchResult; caller invokes result.handler(...).

Raises:

RuntimeError – if no entry matched (impossible by construction; GENERAL lambda *_: True always matches as the catch-all). Defensive raise per honest-fail-on-data.

Return type:

ClassDispatchResult

get_dispatch_stats()#

: defensive copy of the (StoutClass -> int) histogram.

reset_dispatch_stats()#

: explicit reset for batch-run boundaries.

class orthonym.routing.ClassDispatchResult(class_id, handler, audit_record, tier)#

Bases: object

a phase: returned by ClassFirstRouter.dispatch.

Caller invokes result.handler(...) to get the name string. Frozen so a single dispatch result can be safely passed across recursive call boundaries (fresh-instance pattern).

class_id: StoutClass#
handler: Callable[[...], str | None]#
audit_record: dict#
tier: int#
class orthonym.routing.StoutClass(*values)#

Bases: _StrEnumBase

a phase dispatch class identifiers (internal notes).

Per internal notes + the audit Path-(b) reconciliation: 18 outer-cascade entries (rows 1-18 of the audit) + 1 GENERAL catch-all = 19 enum members.

sibling-phase slots are commented out (the audit) and inserted by

a phase / 162 / 163 as 1-line _register_dispatch(...) additions.

SALT = 'salt'#
RADICAL = 'radical'#
ZWITTERION = 'zwitterion'#
ANION_RETAINED = 'anion_retained'#
CATION_RETAINED = 'cation_retained'#
CATION_QUATERNARY = 'cation_quaternary'#
ESTER_ANION_ZWITTERION = 'ester_anion_zwitterion'#
MIXED_SIGN_ZWITTERION = 'mixed_sign_zwitterion'#
ANION_SMALL = 'anion_small'#
POLY_ANION = 'poly_anion'#
MULTI_COMPONENT_NEUTRAL = 'multi_component_neutral'#
MULTIPLICATIVE = 'multiplicative'#
CARBOHYDRATE_LOOKUP = 'carbohydrate_lookup'#
NATURAL_PRODUCT = 'natural_product'#
PEPTIDE = 'peptide'#
RETAINED_NAME = 'retained_name'#
AMINO_ACID = 'amino_acid'#
SKELETAL_REPLACEMENT = 'skeletal_replacement'#
CYCLOPHANE = 'cyclophane'#
DECOMPOSITION_PRE_GENERAL = 'decomposition_pre_general'#
GENERAL = 'general'#
INORGANIC_ACID = 'inorganic_acid'#
ORGANOMETALLIC = 'organometallic'#
LIPID = 'lipid'#
MONONUCLEAR_HYDRIDE = 'mononuclear_hydride'#
CHALCOGEN_CHAIN = 'chalcogen_chain'#
POLYAZANE = 'polyazane'#
FREE_HOMONUCLEAR_G14_HYDRIDE = 'free_homonuclear_g14_hydride'#
DINUCLEAR_HYDRIDE = 'dinuclear_hydride'#
KETENE = 'ketene'#
RING_CHALCOGEN_OXIDE = 'ring_chalcogen_oxide'#
HYDRO_FUSED_PEROXOL = 'hydro_fused_peroxol'#
THIOIMIDE = 'thioimide'#
NITRAMIDE_SUBSTITUTED = 'nitramide_substituted'#
CYCLIC_POLYESTER = 'cyclic_polyester'#
AZINIC_DERIVATIVE = 'azinic_derivative'#
HETERONE = 'heterone'#
SULFINE = 'sulfine'#
CUMULATIVE_ZWITTERION = 'cumulative_zwitterion'#
YLIDE = 'ylide'#
PSEUDOKETONE_HETERO = 'pseudoketone_hetero'#
ACYL_CHALCOGENCHAIN_PSEUDOKETONE = 'acyl_chalcogenchain_pseudoketone'#
LAMBDA5_PHOSPHANIMINE = 'lambda5_phosphanimine'#
HETEROIMINE = 'heteroimine'#
LAMBDA_SULFANE_IMINE_OXIDE = 'lambda_sulfane_imine_oxide'#
POLYCHALCOGEN_OXIDE = 'polychalcogen_oxide'#
CATENATED_HYDRIDE = 'catenated_hydride'#
HETEROCHALCOGEN_ABA = 'heterochalcogen_aba'#
HOMONUCLEAR_PNICTOGEN_CHAIN = 'homonuclear_pnictogen_chain'#
PNICTOGEN_CARBOXYLIC_ACID = 'pnictogen_carboxylic_acid'#
MONONUCLEAR_HYDRIDE_ADDED_CARBON = 'mononuclear_hydride_added_carbon'#
INOSITOL = 'inositol'#
NUCLEOSIDE = 'nucleoside'#
class orthonym.routing.ClassDispatchEntry(class_id, priority, tier, predicate, handler, iupac_section, description, side_effect_inventory=())#

Bases: object

a phase +: frozen dataclass row of DISPATCH_TABLE.

side_effect_inventory MUST be ```` per the hard invariant; the integrity test test_side_effect_inventory_is_empty (Plan-03) asserts this for every entry. explicitly bans any predicate that mutates mol, MolecularFeatures, module-global state, or thread-local state.

class_id: StoutClass#
priority: int#

spaced in 100s for insertability

tier: int#
predicate: Callable[[...], bool]#
handler: Callable[[...], str | None]#
iupac_section: str#
description: str#
side_effect_inventory: Tuple[str, ...] = ()#
orthonym.routing.dispatch(mol, smiles, canonical_smiles, features=None, **kwargs)#

module-level wrapper for callers that don’t carry a router instance.

Uses a lazily-initialized module-default router. Per internal notes +, per-instance counters are preferred for telemetry; this convenience wrapper is for one-off non-stat-tracking callers.

orthonym.routing.get_dispatch_stats()#

+: stats from the module-default router.

orthonym.routing.reset_dispatch_stats()#

+: reset module-default router stats.