orthonym.assembly.composition_primitives#
Note
Internal API. Names and behaviour may change between releases.
a phase (-03 / internal notes) — shared name-composition primitives.
Single source of truth for the IUPAC / / string-composition
grammar, called by BOTH the legacy fragment assembler
(handlers/_handler_shared.py:_assemble_fragments) and the Name-Tree
serializer (name_tree_to_string._assemble_explicit_fields). There is ONE
implementation of each rule — not two — so the legacy path and the production
flip path cannot drift (; the no-band-aid mandate in
internal notes).
The five core helpers (_estimate_parent_size_from_name,
_build_unsaturation_infix, _build_hydrocarbon_name, _join_prefixes,
_join_prefix_to_name) were LIFTED VERBATIM from composer.py (a phase)
— their bodies are unchanged so the legacy carrier stays byte-identical.
composer.py re-exports them under their original names for back-compat.
Leaf-module invariant (Pitfall 4): this module imports ONLY from
naming_utils and rules.locant_validation (both confirmed leaves) plus the
data.chain_names table — it MUST NOT import composer or NameFragment,
so the serializer can import it at module load without an
assembly -> composer -> assembly cycle.
- orthonym.assembly.composition_primitives.prefix_locant_order_key(locant)#
Order one locant within a multiplied prefix’s locant set.
(the Blue Book): “Italic capital and lower-case letter locants
are lower than Greek letter locants, which, in turn, are lower than numerals”; :3193: “Primed locants are placed immediately after the corresponding unprimed locants in a set arranged in ascending order; locants consisting of a number and a lower-case letter… are placed immediately after the corresponding numeric locant”. So the italic element locants
N,N',N2,O,Slead (in their own order: letter, then prime or superscript), then the numerals by value, a letter-suffixed numeral (3a) and a primed one (4') right after their numeral. The Blue Book’s mixed sets: ‘N,*N*,2-trimethyl…propanamide (PIN)’ (:21624), ‘N,1,4-triphenyl-1*H*- 1,2,4-triazol-4-ium-3-aminide (PIN)’ (:42460).
- orthonym.assembly.composition_primitives.combine_identical_prefix_groups(entries)#
Merge the prefix groups of one substitutive name that carry the SAME prefix.
entriesis an iterable of(name, locants)in citation order, where anamemay occur more than once because different producers collected it – the ring or chain carbons in one list, the nitrogens of an amide or amine suffix in another. Returns[(name, locants),...]with every identicalnamecombined into ONE group at its first position, the locants ordered byprefix_locant_order_key().(the Blue Book) (b) (:7067): the basic multiplying prefixes
“indicate a multiplicity of:… simple substituent prefixes”, and (a) (:7104) ‘bis’, etc., of substituted ones – a multiplicity of the PREFIX, not of the atom kind it sits on. The Blue Book’s PINs cite one group across italic and numeric locants: ‘N,2-dimethylpropanamide’ and ‘N,*N*,2-trimethyl-3- {…}propanamide (PIN)’ (:21624), ‘N,4-dimethyl-N-(3-methylphenyl)benzamide (PIN)’ (:32879), ‘N,1-bis(4-chlorophenyl)methanimine (PIN)’ (:26524), ‘N,1,4-triphenyl-1*H*-1,2,4-triazol-4-ium-3-aminide (PIN)’ (:42460), and across differently numbered nitrogens ‘*N*1,*N*3-dimethylpropanediamide (PIN)’ (:2889). This is the grouping only; each producer keeps its own formatter (marks, multiplier) and its own citation order.
- orthonym.assembly.composition_primitives.identical_prefixes_grouped()#
False while:func:identical_prefixes_cited_apart is active: the producers then cite each source’s prefix groups on their own (‘N,N-diphenyl-6-phenyl’) instead of one group per identical prefix (‘N,N,6-triphenyl’).
- class orthonym.assembly.composition_primitives.identical_prefixes_cited_apart#
Bases:
objectContext: name with identical prefixes of different atoms cited apart.
‘Different isotopic modifications on otherwise identical
substituents’ (the Blue Book): “When two substituent groups are isotopically modified in different ways so that they cannot be combined together using multiplicative terms such as ‘di-’, ‘bis-’, etc., they are cited separately” (:43758). The isotope decorator names the isotope-STRIPPED skeleton, where the groups look identical and are multiplied (‘N,N,6-triphenyl’); when a label sits on one member only, no descriptor can be placed on that name, and the skeleton is named again inside this context so the members stand apart.
- orthonym.assembly.composition_primitives.apply_mononuclear_enclosing(prefix_texts, is_mononuclear)#
Apply the mononuclear enclosing rule (the Blue Book).
For a mononuclear parent hydride with >= 2 substituents: the FIRST cited substituent is bare; the SECOND AND FURTHER are EACH enclosed in parentheses (
bromo(chloro)(fluoro)methane). Carve-out: when ANY simple prefix carries a multiplicative prefix (dichloro/trifluoro/…) ALL prefixes are left bare/unenclosed — the common-PIN formbromodichlorofluoromethane(the PROTECT caseC(Br)(Cl)(Cl)F).THE single implementation of this rule:
_handler_shared._assemble_fragmentsused to carry a second, near-identical inline copy (differing only in two comment words) and therefore a second copy of the compound-hyphen test; it now calls this function.
- orthonym.assembly.composition_primitives.resolve_suffix_prefix_collision(suffix_locants, prefix_pairs, is_ring, parent_size)#
Remove prefix locants that collide with a suffix locant, suffix wins).
Mirrors
_assemble_fragments:963-1015. Returnsprefix_pairsunchanged when the parent is not a ring, there is no suffix locant, or no collision is detected (the general_acyclic-chain no-op path).
- orthonym.assembly.composition_primitives.is_ring_parent_name(parent_text)#
True when the parent stem names a ring system (the collision gate).
Same keyword scan the legacy
_assemble_fragmentsuses inline at_handler_shared.py:966-974— extracted so the serializer applies the identical ring test.