Skip to content

fix: defer to pint application registry#198

Merged
gipert merged 5 commits into
mainfrom
fix-pint-app-registry
May 14, 2026
Merged

fix: defer to pint application registry#198
gipert merged 5 commits into
mainfrom
fix-pint-app-registry

Conversation

@gipert
Copy link
Copy Markdown
Member

@gipert gipert commented May 14, 2026

Summary

  • dspeed/units.py was creating its own pint.UnitRegistry and globally overriding the application registry on import via set_application_registry(). This silently hijacked any consumer code that also used pint.
  • When a consumer created pint.Quantity(...) against the default (or their own) registry before importing dspeed, mixing those quantities with dspeed's produced Cannot operate with Quantity of different registries errors.
  • Switched to pint.get_application_registry() so dspeed shares whatever registry the consumer is using, with no global side effects on import.

The auto_reduce_dimensions=True flag previously set on the private registry is dropped — it's purely cosmetic (e.g. simplifies m·s/s → m after arithmetic) and nothing in dspeed depends on it.

Test plan

  • Cross-registry sanity check: consumer's pint.Quantity(1, "us") and dspeed's ureg.Quantity(1, "us") share the same registry; arithmetic between them works.
  • pint.get_application_registry() is no longer mutated by importing dspeed.
  • CI test suite (tests/processors/test_iir_filter.py, tests/test_build_dsp.py exercise unit_registry).

🤖 Generated with Claude Code

dspeed was creating its own pint UnitRegistry and globally overriding
the application registry on import via set_application_registry().
This silently hijacked consumer code that also used pint, and produced
cross-registry errors when consumers created Quantities against pint's
default (or their own) registry before dspeed was imported.

Use pint.get_application_registry() instead so dspeed shares whatever
registry the consumer is using, with no global side effects on import.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
With dspeed now sharing the application pint registry (instead of
hijacking it), lgdo's preferred short format (~P) propagates: unit
attributes are written as 'ns' instead of 'nanosecond', and pint emits
a DeprecationWarning when user format specs lack a unit formatter.

- Update test_proc_chain_where to expect 'ns' in lh5 attrs.
- Filter the pint DeprecationWarning so user-provided legend format
  strings without unit formatters keep working.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

fix(vis): strip units from legend values before format

WaveformBrowser passed pint Quantity objects directly into user-supplied
format strings like 'energy = {trapEmax:0.1f}'. With a registry default
format that includes a unit formatter (~P, set by lgdo), pint emits a
DeprecationWarning predicting that '0.1f' will silently start appending
units in a future release — the opposite of what dspeed users want here.

Convert Quantity legend values to their magnitudes before format(),
preserving the numeric formatting the user requested. Drop the
filterwarnings workaround that hid this warning.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@gipert gipert requested a review from Copilot May 14, 2026 14:42
@gipert gipert added the bug Something isn't working label May 14, 2026
@gipert gipert force-pushed the fix-pint-app-registry branch from 7d5d91c to d71092c Compare May 14, 2026 14:42
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR changes dspeed to use Pint’s application registry instead of creating and installing its own registry, avoiding global registry hijacking for downstream consumers.

Changes:

  • Replaces dspeed’s private UnitRegistry setup with pint.get_application_registry().
  • Updates processing-chain unit expectations from canonical names to abbreviated unit strings.
  • Adjusts waveform-browser legend formatting to unwrap Pint quantities before string formatting.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/dspeed/units.py Uses Pint’s application registry as dspeed’s shared unit registry.
src/dspeed/vis/waveform_browser.py Converts legend Quantity values to magnitudes before formatting.
tests/test_processing_chain.py Updates expected output unit strings from nanosecond to ns.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/dspeed/vis/waveform_browser.py Outdated
Comment thread src/dspeed/units.py
The previous fix stripped magnitudes from every Quantity in leg_dat, but
the default-spec branch in WaveformBrowser.__init__ substitutes
'0.3gP~' for entries without an explicit format. Stripping there made
the format call ValueError out because '0.3gP~' is invalid for plain
floats.

Parse each legend format string and only strip Quantities whose spec
has no pint formatter character (~, P, H, L, C, D). Default '0.3gP~'
and explicit pint specs keep the Quantity; user-provided plain specs
like '0.1f' get the magnitude so pint's DeprecationWarning does not
fire.

Also add tests/test_units.py to lock in the application-registry
sharing contract (importing dspeed must not replace pint's app
registry, and consumer-created quantities must interoperate with
dspeed.units.unit_registry quantities).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@tdixon97
Copy link
Copy Markdown
Contributor

tdixon97 commented May 14, 2026

Thanks Luigi, this is an important fix, which was causing quite some issues (but I couldnt understand why)

build_processing_chain stored values via 'processors[key] = node'. When
processors is a dbetto AttrsDict (which CLI configs are, after
Props.read_from), __setitem__ wraps any plain dict in a fresh
AttrsDict via __init__'s copy loop, decoupling the stored entry from
the local reference. Later in-place mutations like node["prereqs"] = ...
then never reached the entry in processors[key], so
resolve_dependencies failed with KeyError: 'prereqs'.

Cast processors to a plain dict once at the top of the function so all
subsequent assignments behave normally, regardless of the input type.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@gipert gipert force-pushed the fix-pint-app-registry branch from 075962a to 9a136c3 Compare May 14, 2026 15:20
dspeed assumes short-form unit names (e.g. 'ns' rather than 'nanosecond')
in output attrs and elsewhere. Today this works because lgdo.units sets
formatter.default_format = "~P" on the application registry when lh5
imports it. Make the dependency explicit so dspeed does not silently
break if that transitive import side effect goes away or if a consumer
uses dspeed.units without triggering lh5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@gipert gipert merged commit 522d4a1 into main May 14, 2026
14 checks passed
@iguinn iguinn mentioned this pull request May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants