orthonym.validation.opsin_grammar#
Note
Internal API. Names and behaviour may change between releases.
OPSIN-grammar pre-validator (a phase).
OPSIN-XML-driven authoritative validator + round-trip-gated suggest_fix. Layered ON TOP OF a phase format_validator heuristics per internal notes.
- Architecture (Plan-02 deliverable):
Module-import-time XML loader : parses opsin/…/regexTokens.xml, expands %name% placeholders to fixed point, and compiles each into a Python re.Pattern. Loud ImportError on adapter mismatch — never silent degradation .
OpsinGrammar.validate(name) -> bool: hot-path API. Layer- cake : format_validator pre-screen first, then OPSIN-XML strict checks for {bracket, hyphen, stereo} surfaces.
OpsinGrammar.suggest_fix(name, source_smiles=None) ( LOCKED signature, name FIRST, source_smiles SECOND): tries the bounded repair tables from internal notes in order [bracket, hyphen, stereo], gates each candidate through validate AND opsin_roundtrip_check(smiles, candidate) (SMILES-first inside the oracle), and returns (repaired, repair_class) on success or (None, None) otherwise. One repair attempt only — no retry loop .
Per-instance _stats counter (,) — never module- global mutable state.
- Anti-pattern hygiene (internal notes):
- /: no _postprocess_name/re.sub chains outside the
explicit _suggest_* table.
- : every _suggest_* regex literal cites its internal notes
row.
- : repairs only re-position / re-bracket / re-hyphenate;
never change parent/locants/substituents.
: _load_opsin_token_regexes raises ImportError on miss. : round-trip oracle is (smiles, name). : read result[“passed”], never truthy-check the dict. : no fictitious “fast OPSIN call” timing claims; the
verified empirical figure on this host is ~1269ms mean.
: default jar_version=”2.9.0”; never assume an older JAR. : per-instance counter only. : no RDKit imports inside _suggest_*.
- class orthonym.validation.opsin_grammar.OpsinGrammar(stats=None)#
Bases:
objectOPSIN-grammar pre-validator with bounded round-trip-gated repair.
- Three responsibilities (internal notes <domain>):
validate(name) -> bool — fast OPSIN-XML-driven check across three surfaces (bracket nesting, stereo position, hyphen placement). Layered ON TOP OF a phase’s format_validator.validate_name_format heuristic pre-screen per.
suggest_fix(name, source_smiles=None) — bounded repair function with the LOCKED signature (name FIRST). Each repair candidate is gated through validate AND opsin_roundtrip_check(smiles, candidate) (SMILES-first inside the oracle). One attempt per repair class; NO retry loop (/).
Per-instance telemetry via self._stats and get_validation_stats.
Construction: OpsinGrammar (or OpsinGrammar(stats=shared_dict) to share counters with an outer container per ref-pass pattern).
- STAT_KEYS: Tuple[str, ...] = ('validate_passed', 'repair_succeeded_bracket', 'repair_succeeded_stereo', 'repair_succeeded_hyphen', 'repair_failed_validate', 'repair_failed_roundtrip', 'no_repair_offered')#
- validate(name)#
Fast OPSIN-grammar pre-validation. Returns True on pass.
- suggest_fix(name, source_smiles=None)#
Bounded round-trip-gated repair (LOCKED signature).
- Parameters:
name (str) – The (validate-failing) IUPAC name to repair. FIRST positional arg per.
source_smiles (str | None) – Original SMILES for the round-trip gate. When None the round-trip gate is replaced by a validate-only check and an INFO log records the degraded path .
- Returns:
(repaired_name, repair_class) if a repair fired AND re-validates AND (when source_smiles is given) round- trips through OPSIN. Otherwise (None, None).
- Return type:
Tuple[str | None, str | None]
Notes
Tries each repair class once in deterministic order [bracket, hyphen, stereo]. NO retry loop (/).
The round-trip oracle is called as opsin_roundtrip_check(source_smiles, candidate) — SMILES-first per. The (smiles, name) arg order to the ORACLE is the OPPOSITE of suggest_fix’s own signature; this is the most common confusion source in the codebase and the grep gate enforces it.
- get_validation_stats()#
Return a defensive copy of the per-instance counters .
- last_repair_class()#
Diagnostic accessor: most recent successful repair class.
- orthonym.validation.opsin_grammar.opsin_grammar_validate(name)#
Module-level convenience wrapper around OpsinGrammar.validate.
Backed by an internal singleton with its own _stats counter (NOT shared with any Orthonym instance per).
- orthonym.validation.opsin_grammar.opsin_grammar_suggest_fix(name, source_smiles=None)#
Module-level convenience wrapper around OpsinGrammar.suggest_fix.
Return-shape divergence: OpsinGrammar.suggest_fix returns Tuple[Optional[str], Optional[str]] (per LOCKED); this helper drops the repair-class slot and returns Optional[str] only, for backward-compatible callers that just want the repaired name. Use the class API directly when the repair class is needed.