Skip to content

Unifying branches - #38

Merged
r-fedorov merged 6 commits into
testsfrom
unifying-branches
Jul 21, 2026
Merged

Unifying branches#38
r-fedorov merged 6 commits into
testsfrom
unifying-branches

Conversation

@r-fedorov

@r-fedorov r-fedorov commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary by Sourcery

Unify recursive subgraph naming and tree construction, and refine how stereochemical substituent boundaries are represented and formatted.

New Features:

  • Introduce shared RecursiveSubgraphNamer protocol for branch and component subgraph naming with optional trace and tree outputs.
  • Add RenderedSubstituentName type to carry metadata about optional outer parentheses around substituent names.

Enhancements:

  • Factor out build_naming_tree_node and build_shortcut_tree_node helpers to standardize naming tree schema and avoid mutable default issues.
  • Refactor shortcut component and substituent tree construction to use the shared tree builders.
  • Adjust parent name assembly to mark when substituent boundaries are optional, enabling downstream formatting decisions.
  • Update substituent and prefix formatting to optionally drop outer parentheses when the substituent boundary is semantically clear.

Tests:

  • Add tests verifying that naming tree builders share a common schema without mutable defaults.
  • Add tests covering stereochemical substituent naming and the conditions under which outer parentheses are omitted or retained.

@sourcery-ai

sourcery-ai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Reviewer's Guide

Centralizes recursive subgraph naming contracts and naming tree node construction, standardizes shortcut tree schemas, and refines how optionally parenthesized stereochemical substituent names are carried through and rendered in component and substituent formatting.

File-Level Changes

Change Details Files
Introduce shared helpers for constructing component/substituent naming tree nodes and reuse them for assembled and shortcut trees to ensure a common, immutable schema.
  • Added build_naming_tree_node to create the invariant portion of naming tree nodes with safe defaults and optional metadata injection.
  • Added build_shortcut_tree_node to construct schema-complete shortcut nodes with bindings/token span metadata and delegate core shape to build_naming_tree_node.
  • Refactored assembly_substituent_tree to return a node built via build_naming_tree_node and move stereo, hydrogen, hydro-operation, and charge data into metadata.
  • Updated component and substituent shortcut tree builders to use build_shortcut_tree_node instead of hand-rolled dicts, and added tests to confirm shared schema and lack of mutable defaults.
src/openclatura/trace_helpers.py
src/openclatura/component_namer.py
src/openclatura/namer.py
src/openclatura/tests/test_analysis.py
Unify branch/subgraph naming interfaces behind a shared RecursiveSubgraphNamer protocol and replace ad hoc BranchNamer/SubgraphNamer types across the codebase.
  • Introduced naming_protocols.RecursiveSubgraphNamer defining the overloaded callable contract for recursive subgraph naming with trace/tree options.
  • Removed local BranchNamer/SubgraphNamer Protocols and Callable aliases from multiple modules and replaced their usages with RecursiveSubgraphNamer.
  • Updated function signatures and type hints in component_namer, component_modifiers, heteroatom_subgraphs, functional_prefixes, substituent_tokens, and special_cases to depend on RecursiveSubgraphNamer.
src/openclatura/naming_protocols.py
src/openclatura/component_namer.py
src/openclatura/component_modifiers.py
src/openclatura/heteroatom_subgraphs.py
src/openclatura/functional_prefixes.py
src/openclatura/substituent_tokens.py
src/openclatura/special_cases.py
Track and use metadata about optionally parenthesized stereochemical substituent boundaries so rendering can omit unnecessary outer parentheses while preserving disambiguating cases.
  • Introduced RenderedSubstituentName string subclass carrying an outer_parentheses_optional flag and used it in SubstituentItem and relevant imports.
  • Wrapped assembled subgraph names in RenderedSubstituentName via a _mark_optional_substituent_boundary helper when finalized with stereochemical features, for both simple and rewrite-pipeline flows.
  • Adjusted substituent prefix formatting to unwrap a single, unlocanted, singleton substituent whose name is a RenderedSubstituentName with optional outer parentheses, then reapply parentheses only when complexity, multiplicity, or grouping requires them.
  • Added tests for stereochemical substituent formatting behavior (single unlocanted substituent, locanted substituent, and nested cases) and for edge cases like methane and hydrogen cyanide naming.
  • Ensured tree-building and naming changes are covered by new tests verifying shortcut/component tree schemas and metadata behavior.
src/openclatura/assembly_parts.py
src/openclatura/namer.py
src/openclatura/assembly_prefixes.py
src/openclatura/namer.py
src/openclatura/tests/test_analysis.py

Possibly linked issues

  • #Subgraph and Branch unifier: PR directly implements shared RecursiveSubgraphNamer and build_*_tree_node helpers, unifying naming contracts and shortcut trees.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 071f8809-253d-4f40-9d2a-cdf46f5ebb84

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch unifying-branches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In build_shortcut_tree_node, the decisions argument is passed through to build_naming_tree_node as nested_decisions; renaming the parameter to nested_decisions (and updating call sites) would make its purpose clearer and keep terminology consistent across the helpers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `build_shortcut_tree_node`, the `decisions` argument is passed through to `build_naming_tree_node` as `nested_decisions`; renaming the parameter to `nested_decisions` (and updating call sites) would make its purpose clearer and keep terminology consistent across the helpers.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@r-fedorov

Copy link
Copy Markdown
Collaborator Author

@sourcery-ai review

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The new RecursiveSubgraphNamer protocol makes upstream_atom a positional-or-keyword argument instead of keyword-only, which may be stricter than some existing implementations (that declare upstream_atom as keyword-only) and can cause static type-checking friction; consider keeping upstream_atom keyword-only in the protocol (adding a * before it) to better match existing callables.
  • RenderedSubstituentName is a str subclass with an attached outer_parentheses_optional attribute, but slicing and many string operations will drop the subclass (and thus the flag); it may be worth adding a short comment near its definition or usage to clarify that this loss is intentional and only boundary-aware names are expected to carry the marker.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new RecursiveSubgraphNamer protocol makes upstream_atom a positional-or-keyword argument instead of keyword-only, which may be stricter than some existing implementations (that declare upstream_atom as keyword-only) and can cause static type-checking friction; consider keeping upstream_atom keyword-only in the protocol (adding a * before it) to better match existing callables.
- RenderedSubstituentName is a str subclass with an attached outer_parentheses_optional attribute, but slicing and many string operations will drop the subclass (and thus the flag); it may be worth adding a short comment near its definition or usage to clarify that this loss is intentional and only boundary-aware names are expected to carry the marker.

## Individual Comments

### Comment 1
<location path="src/openclatura/naming_protocols.py" line_range="14-17" />
<code_context>
-    @overload
-    def __call__(
-        self,
-        mol: Molecule,
-        start_idx: int,
-        exclude_atoms: set[int],
-        *,
-        upstream_atom: int | None = None,
-        return_trace: Literal[False] = False,
-        return_tree: Literal[False] = False,
</code_context>
<issue_to_address>
**issue:** Align `RecursiveSubgraphNamer` parameter kinds (keyword-only vs positional) with existing implementations.

The protocol currently allows `upstream_atom` as positional‑or‑keyword (`upstream_atom: int | None = None, *`), while existing namer implementations take it as keyword‑only (`*, upstream_atom: int | None = None`). This mismatch means implementations that enforce keyword‑only don’t strictly conform to the protocol and can trigger type‑checker errors. Please update the protocol overloads to make `upstream_atom` keyword‑only (after `*`), matching the existing `BranchNamer`/`SubgraphNamer` signatures and call sites.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +14 to +17
mol: Molecule,
start_idx: int,
exclude_atoms: set[int],
upstream_atom: int | None = None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Align RecursiveSubgraphNamer parameter kinds (keyword-only vs positional) with existing implementations.

The protocol currently allows upstream_atom as positional‑or‑keyword (upstream_atom: int | None = None, *), while existing namer implementations take it as keyword‑only (*, upstream_atom: int | None = None). This mismatch means implementations that enforce keyword‑only don’t strictly conform to the protocol and can trigger type‑checker errors. Please update the protocol overloads to make upstream_atom keyword‑only (after *), matching the existing BranchNamer/SubgraphNamer signatures and call sites.

@r-fedorov
r-fedorov merged commit ade7a0c into tests Jul 21, 2026
22 checks passed
@r-fedorov
r-fedorov deleted the unifying-branches branch July 22, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant