pint
pint copied to clipboard
The aliases for 'millimeter' are not found
Hello,
I encountered a bug in the aliases of one certain unit.
When I added the following codes in the my_def.txt file.
@alias millimeter = DUT_MILLIMETERS
@alias centimeter = DUT_CENTIMETERS
@alias meter = DUT_METERS
After load_definitions, if I tried to get the aliases of millimetre,
ureg._units['millimeter'].aliases
It gave me an empty tuple, but the aliases for the rest of the units I can get. As you can see in the screenshot. Hope you can help to solve this, thanks!

Can reproduce
I cannot reproduce defining programatically.
Python 3.9.7 (default, Sep 16 2021, 08:50:36) Pint 0.18
>>> import pint
>>> ureg = pint.UnitRegistry()
>>> ureg.define("@alias millimeter = DUT_MILLIMETERS")
>>> ureg.define("@alias centimeter = DUT_CENTIMETERS")
>>> ureg.define("@alias meter = DUT_METERS")
>>> ureg._units["millimeter"].aliases
('DUT_MILLIMETERS',)
>>> ureg._units["centimeter"].aliases
('DUT_CENTIMETERS',)
>>> ureg._units["meter"].aliases
('metre', 'DUT_METERS')
Can you check?
@hgrecco Hello Hernan, I had a further look, you can see how the bug is produced with the following code.
Python 3.8.5
pint 0.18
import pint
ureg = pint.UnitRegistry()
ureg.define("@alias millimeter = DUT_MILLIMETERS")
ureg.define("@alias centimeter = DUT_CENTIMETERS")
ureg.define("@alias meter = DUT_METERS")
getattr(ureg, 'mm')
ureg._units['millimeter'].aliases
Hi all,
I'm having similar issues as above, and could reproduce the issue from the last message of @ItsPatrickHe.
However, starting from version 19.0, the behaviour is different.

Now when defining aliases, the aliases are not retrievable through the aliases attribute (see tests 1,2,3).
However, the original units can be retrieved by using the alias as in tests 4,5,6.
Is this intentional?
From Defining units programmatically in the docs, it seems that the same syntax is still used to add aliases, so you would expect them to end up in the aliases attribute also.
I'm using Python version 3.10.3 and Pint 19.2.
aliases not found seems to come from this commit 26461894df8958f91c52bea6ee9bf5efa5306492 @hgrecco It seems aliases are not added anymore, it comes from definition being frozen & it seems to be a good idea. I don't think it is really used anymore, since alias is being properly added to the self._units dict.
@jules-ch thanks for the reply. Actually, the aliases are quite useful for us when we try to convert these metric units to other names in different software. In this case, we get the names from the aliases of the units and select the right one. It seems more logical to do it this way than loop through the whole units dict. Is there another way to get the aliases of these units? Otherwise, we may have to do these mappings ourselves, but this kinda lose the benefits of setting up all the aliases in the first place.
As @jules-ch mentioned, this intentional. We now consider definitions as immutable, which makes everything easier to reason around. Aliases are added as references to those immutable definitions. This should not break any code operating on units or quantities (this is correct, right?).
It does break the type of introspection you are looking for (and I apologize for that). In a way, the introspection is on definitions. I would like to understand more your use case and maybe propose a good solution. I do think it is reasonable to want all aliases for a given unit. Aliases are many to one connection. We have now get_name that transverses all aliases until the canonical name is found (going from any of the many to the one). You want now to list in the other direction.
The API is critical we could add get_aliases to the registry. But still people might do what @RobClaessensRHDHV has shown and be confused. On the other hand, maybe people are doing that (accessing a _ prefixed attribute) because there is now API). What are your thoughts on this?
@hgrecco, Thanks for mentioning.
I think that a get_aliases method would be very helpful. Being able to retrieve the aliases through the original unit is important for our use case. In this case we want to convert data from our own scheme in Python to a format that is readable for another application, Revit. This requires us to map from a Pint unit, to a string representation of this unit that is recognized by Revit. Before Revit 2022, Revit had their own UnitTypes and DisplayUnitTypes to depict units. Since Revit 2022, it uses Forge type units. With Pint, we can add both as aliases (e.g. meter.aliases = [DUT_Meters, autodesk.unit.unit:meters-1.0.0]), and then loop over all aliases with get_aliases(). This would make it easy to select the right alias, based on the application (version) we're targeting.
Hope that's clear. In general, I think it makes sense to have a mapping from the original unit to its aliases also, to better accommodate workflows as above.
Sound reasonable to me, what do you think @jules-ch ? Before rolling that release I just want to check that there is no other "public" way to access aliases to avoid confusion.
I don't think there is a public way to retrieve aliases no.
@hgrecco Sounds good! Would be happy to test when it's released :)