11"""Connected-component naming pipeline."""
22
33from collections .abc import Callable
4- from typing import Literal , Protocol , overload
54
65from .assembly_parts import AssemblyParts , NameAtomBinding , SubstituentItem
76from .chains import find_all_carbon_paths , find_ring_systems , get_cyclic_atoms
1716from .name_bindings import binding_trace_data , refresh_name_atom_bindings
1817from .naming_audit import UnnamedAtomError , assert_component_fully_named
1918from .naming_context import ComponentNamingState , NamingIntent
19+ from .naming_protocols import RecursiveSubgraphNamer
2020from .parent_pipeline import build_parent_assembly_plan , resolve_retained_parent
2121from .parent_selection import select_principal_parent
2222from .principal_groups import (
4848 assembly_substituent_tree ,
4949 assembly_trace_segments ,
5050 bond_ids_within ,
51+ build_shortcut_tree_node ,
5152 decision_trace_data ,
5253 functional_group_trace_data ,
5354 trace_decision ,
5455)
5556
56-
57- class SubgraphNamer (Protocol ):
58- """Recursive subgraph namer with simple and traced/tree return modes."""
59-
60- @overload
61- def __call__ (
62- self ,
63- mol : Molecule ,
64- start_idx : int ,
65- exclude_atoms : set [int ],
66- * ,
67- upstream_atom : int | None = None ,
68- return_trace : Literal [False ] = False ,
69- return_tree : Literal [False ] = False ,
70- decision_trace : DecisionTrace | None = None ,
71- ) -> str : ...
72-
73- @overload
74- def __call__ (
75- self ,
76- mol : Molecule ,
77- start_idx : int ,
78- exclude_atoms : set [int ],
79- * ,
80- upstream_atom : int | None = None ,
81- return_trace : Literal [True ],
82- return_tree : Literal [False ] = False ,
83- decision_trace : DecisionTrace | None = None ,
84- ) -> tuple [str , list [dict ]]: ...
85-
86- @overload
87- def __call__ (
88- self ,
89- mol : Molecule ,
90- start_idx : int ,
91- exclude_atoms : set [int ],
92- * ,
93- upstream_atom : int | None = None ,
94- return_trace : Literal [True ],
95- return_tree : Literal [True ],
96- decision_trace : DecisionTrace | None = None ,
97- ) -> tuple [str , list [dict ], dict | None ]: ...
98-
99- @overload
100- def __call__ (
101- self ,
102- mol : Molecule ,
103- start_idx : int ,
104- exclude_atoms : set [int ],
105- * ,
106- upstream_atom : int | None = None ,
107- return_trace : Literal [False ] = False ,
108- return_tree : Literal [True ],
109- decision_trace : DecisionTrace | None = None ,
110- ) -> tuple [str , dict | None ]: ...
111-
112-
11357SpiroSubgraphNamer = Callable [[Molecule , int , set [int ]], SpiroAssembly ]
11458ParentAssembler = Callable [..., str ]
11559
@@ -133,7 +77,7 @@ def collect_component_branch_substituents(
13377 base_exclude : set [int ],
13478 sub_exclude : set [int ],
13579 * ,
136- name_subgraph : SubgraphNamer ,
80+ name_subgraph : RecursiveSubgraphNamer ,
13781 name_spiro_subgraph : SpiroSubgraphNamer ,
13882 emit_metadata : bool = True ,
13983) -> None :
@@ -298,7 +242,7 @@ def name_component(
298242 return_trace : bool = False ,
299243 return_tree : bool = False ,
300244 decision_trace : DecisionTrace | None = None ,
301- name_subgraph : SubgraphNamer ,
245+ name_subgraph : RecursiveSubgraphNamer ,
302246 name_spiro_subgraph : SpiroSubgraphNamer ,
303247 assemble_parent_name : ParentAssembler ,
304248 token_debug : bool = False ,
@@ -332,11 +276,11 @@ def name_component(
332276 },
333277 )
334278 if return_trace and return_tree :
335- return name , [], _shortcut_tree (name , component_atoms , bindings , token_spans )
279+ return name , [], _component_shortcut_tree (name , component_atoms , bindings , token_spans )
336280 if return_trace :
337281 return name , []
338282 if return_tree :
339- return name , _shortcut_tree (name , component_atoms , bindings , token_spans )
283+ return name , _component_shortcut_tree (name , component_atoms , bindings , token_spans )
340284 return name
341285
342286 def name_component_again (next_mol : Molecule , next_atoms : set [int ], is_substituent : bool = False ):
@@ -376,11 +320,11 @@ def name_component_again(next_mol: Molecule, next_atoms: set[int], is_substituen
376320 },
377321 )
378322 if return_trace and return_tree :
379- return name , [], _shortcut_tree (name , component_atoms , bindings , token_spans )
323+ return name , [], _component_shortcut_tree (name , component_atoms , bindings , token_spans )
380324 if return_trace :
381325 return name , []
382326 if return_tree :
383- return name , _shortcut_tree (name , component_atoms , bindings , token_spans )
327+ return name , _component_shortcut_tree (name , component_atoms , bindings , token_spans )
384328 return name
385329
386330 state = ComponentNamingState (component_atoms = set (component_atoms ), is_substituent = is_substituent )
@@ -431,11 +375,11 @@ def name_component_again(next_mol: Molecule, next_atoms: set[int], is_substituen
431375 },
432376 )
433377 if return_trace and return_tree :
434- return name , [], _shortcut_tree (name , state .component_atoms , bindings , token_spans )
378+ return name , [], _component_shortcut_tree (name , state .component_atoms , bindings , token_spans )
435379 if return_trace :
436380 return name , []
437381 if return_tree :
438- return name , _shortcut_tree (name , state .component_atoms , bindings , token_spans )
382+ return name , _component_shortcut_tree (name , state .component_atoms , bindings , token_spans )
439383 return name
440384
441385 state .exclude_atoms = set (mol .atoms .keys ()) - state .component_atoms
@@ -654,21 +598,15 @@ def name_component_again(next_mol: Molecule, next_atoms: set[int], is_substituen
654598 return name
655599
656600
657- def _shortcut_tree (name : str , component_atoms : set [int ], bindings : list [dict ], token_spans : list [dict ]) -> dict :
601+ def _component_shortcut_tree (
602+ name : str , component_atoms : set [int ], bindings : list [dict ], token_spans : list [dict ]
603+ ) -> dict :
658604 """Return a minimal component tree for shortcut component names."""
659605
660- return {
661- "kind" : "component" ,
662- "name" : name ,
663- "atoms" : sorted (component_atoms ),
664- "bonds" : [],
665- "parent" : None ,
666- "principal_group" : None ,
667- "substituents" : [],
668- "replacement_prefixes" : [],
669- "unsaturations" : [],
670- "trace_segments" : [],
671- "nested_decisions" : [],
672- "name_atom_bindings" : bindings ,
673- "name_token_spans" : token_spans ,
674- }
606+ return build_shortcut_tree_node (
607+ kind = "component" ,
608+ name = name ,
609+ atom_ids = component_atoms ,
610+ name_atom_bindings = bindings ,
611+ name_token_spans = token_spans ,
612+ )
0 commit comments