You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
add_enabled_units leaves a registry context active when alias validation raises #20790
add_enabled_units can leave a unit-registry context active when enabling a conflicting alias raises. After an enclosing application's unit context exits, its custom definition unexpectedly remains enabled.
Steps to reproduce
In a fresh process, without PyUnitWizard or any other consumer library:
fromastropyimportunitsasu# u.Unit('kcal') initially raises ValueError in the default registry.bad=u.def_unit('kcal', 1000*u.J)
withu.add_enabled_units([bad]):
try:
withu.add_enabled_units([u.imperial.kcal]):
passexceptValueError:
pass# Expected: the default registry was restored, so this raises ValueError.# Observed: it succeeds and prints 1000.0.print(u.Unit('kcal').to(u.J))
Expected and observed behavior
The failed inner activation should preserve the pre-call registry, and the successful outer context should restore the original registry on exit. Instead the custom kcal definition remains active after the outer context exits.
Source inspection suggests that the public context factory constructs/pushes _UnitContext before validating the supplied aliases. If validation raises, the caller never receives the new context manager to unwind; the enclosing application's exit then pops the inner level instead. The current development source appears to retain that construction order; I have not executed this reproducer on a development checkout.
Versions and consumer scope
The Astropy-only reproducer above was executed with Python 3.14.7 / Astropy 8.0.1. The corresponding consumer regression also executes with Python 3.11.18 / Astropy 6.1.7. The finding arose while implementing bounded calorie interoperability in uibcdf/pyunitwizard#137. PyUnitWizard now prevalidates native caloric aliases before entering the context, so it avoids the failing constructor path without mutating private registries. This report concerns the public context's exception-restoration behavior, not whether imperial units should be enabled by default.
No external scientific dataset or credentials are involved.
I am actually not sure if it is ever designed to be used nested like that. It changes the global registry in real time. And even though astropy.units.core.add_enabled_units() says you can use it with with, it is not marked explicitly as a context manager, nor has context enter/exit coded in, nor does it yield. @mhvk , maybe you can clarify?
Thanks for reporting the bug (and I agree it is a bug). You are right about where the problem is. The simplest solution is that of #20795, but it means basically working around what really is a design flaw. I'd rather update _UnitContext to be more helpful, so that, e.g., code would become something like,
Activity
pllim commentedon Nov 5, 2026
Indeed, I see this behavior in astropy
v8.1.devas well.ValueError: Object with name 'kcal' already exists in namespace. Filter the set of units to avoid name clashes before enabling them.pllim commentedon Nov 5, 2026
I am actually not sure if it is ever designed to be used nested like that. It changes the global registry in real time. And even though
astropy.units.core.add_enabled_units()says you can use it withwith, it is not marked explicitly as a context manager, nor has context enter/exit coded in, nor does ityield. @mhvk , maybe you can clarify?mhvk commentedon Nov 6, 2026
Thanks for reporting the bug (and I agree it is a bug). You are right about where the problem is. The simplest solution is that of #20795, but it means basically working around what really is a design flaw. I'd rather update
_UnitContextto be more helpful, so that, e.g., code would become something like,Note that I didn't test it, but it would seem cleaner.
pllim commentedon Nov 7, 2026
@mhvk does #20803 look about right?