Skip to content

Complete magnet holder navigation (#373) - #426

Merged
gupichon merged 1 commit into
199-elementholder-api-refurbishmentfrom
373-feature-complete-magnet-holder-navigation
Sep 17, 2026
Merged

gupichon merged 1 commit into
199-elementholder-api-refurbishmentfrom
373-feature-complete-magnet-holder-navigation

Conversation

@gupichon

Copy link
Copy Markdown
Member

Description

Extends MagnetsHolder with a get_cfm() shortcut to fetch all combined-function magnets, and adds dynamic attribute access for configured array names (e.g. magnets.QuadForTune instead of magnets.get("QuadForTune")) across all GenericArrayHolder-based holders (MagnetsHolder, CombinedFunctionMagnetsHolder, SerializedMagnetsHolder, BPMsHolder). dir() is also extended so interactive completion (IPython/Jupyter) proposes configured array names.

Related Issue

Features/issues described there are:

  • new feature: magnets.get_cfm() was added, delegating to the existing combined_function_magnets.get() — no new array-construction logic.
  • new feature: dynamic attribute access was implemented as GenericArrayHolder.__getattr__, generalized to the base class (broader scope than requested in the issue) rather than only MagnetsHolder, since the same navigation is useful on CombinedFunctionMagnetsHolder/SerializedMagnetsHolder/BPMsHolder and the mechanism is identical. __getattr__ only triggers on lookup failure, so it never shadows get/add/private attributes, and raises AttributeError for unknown or non-identifier names.

Changes to existing functionality

  • None. GenericArrayHolder/GenericElementHolder had no prior __getattr__/__dir__; existing attribute/method resolution is unaffected since __getattr__ only runs after normal lookup fails.

Testing

The following tests (compatible with pytest) were added:

  • tests/common/test_array_holder_navigation.py:
    • dynamic attribute returns the same array as get(), for MagnetsHolder, CombinedFunctionMagnetsHolder, BPMsHolder, and SerializedMagnetsHolder
    • unknown array name raises AttributeError
    • dynamic access does not shadow existing methods (get, add)
    • a non-identifier array name is rejected and excluded from dir()
    • dir() includes configured array names for completion
    • get_cfm() returns a CombinedFunctionMagnetArray matching combined_function_magnets.get()
    • test_issue_373_example: reproduces the issue's example code verbatim against real test-lattice data (tests/config/EBSTune-patterns.yaml)
  • tests/test_load_conf_with_code.py: one extra assertion exercising dynamic attribute access end-to-end (sr.live.bpms.BPM)

Verify that your checklist complies with the project

  • New and existing unit tests pass locally (315 passed, 1 pre-existing unrelated failure: tests/tuning_tools/test_tuning_orm.py, a Windows-only NamedTemporaryFile double-open issue, unaffected by this change)
  • Tests were added to prove that all features/changes are effective
  • The code is commented where appropriate (NumPy-style docstrings on all new/changed public API, including class-level docstrings so the dynamic attribute access is discoverable via help())
  • Any existing features are not broken

@gupichon
gupichon merged commit 280f10a into 199-elementholder-api-refurbishment Sep 17, 2026
3 checks passed
@gupichon gupichon mentioned this pull request Sep 17, 2026
11 tasks
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.

4 participants