Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError when using method "to" if a custom preprocessor is in place and a string is passed as target unit #1004

Open
sanzoghenzo opened this issue Jan 28, 2020 · 4 comments · May be fixed by #1402

Comments

@sanzoghenzo
Copy link

I'm experiencing a problem with the new custom preprocessors feature;
trying to convert a quantity to "%" using a string instead of the quantity raises an AttributeError in the ParserHelper.from_string method, since it's not aware of the preprocessors.

UREG = UnitRegistry(
    preprocessors=[
        functools.partial(re.sub, r"(.*)%$", r"\1 percent"),
        functools.partial(re.sub, r"(.*)\u2030$", r"\1 permille"),
    ]
)
UREG.define("percent = 0.01 count = %")
UREG.define("permille = 0.001 count = \u2030")
assert UREG("count").to(UREG("%")).magnitude == 100  # this works ok
assert UREG("count").to(UREG("\u2030")).magnitude == 1000 # this also works ok
assert UREG("count").to(UREG("‰")).magnitude == 1000 # this also works ok
assert UREG("count").to("%").magnitude == 100 

The last line throws this exception:

.\venv\lib\site-packages\pint\quantity.py:561: in to
    other = to_units_container(other, self._REGISTRY)
.\venv\lib\site-packages\pint\util.py:832: in to_units_container
    return registry._parse_units(unit_like)
.\venv\lib\site-packages\pint\registry.py:1167: in _parse_units
    return super()._parse_units(input_string, as_delta)
.\venv\lib\site-packages\pint\registry.py:1045: in _parse_units
    units = ParserHelper.from_string(input_string)
.\venv\lib\site-packages\pint\util.py:574: in from_string
   ret = build_eval_tree(gen).evaluate(cls.eval_token)
AttributeError: 'NoneType' object has no attribute 'evaluate'
@jthielen
Copy link
Contributor

This is (unfortunately) the expected behavior of the preprocessors feature. Given that the preprocessors exist on the registry level, they only function when using the registry-level parsers (parse_expression/registry-as-a-callable and parse_units), and not with lower-level functions using ParserHelper.from_string as you note. (See #429 (comment) and #429 (comment) for the rationale.)

However, this can definitely be better documented! (xref #972)

@sanzoghenzo
Copy link
Author

Thanks @jthielen for the explanation, I supposed that it was related to the design of the feature (I tried to read the entire discussion but I got lost somewhere ;) ).

Documenting this is fine, but IMHO this is something that should be better handled, i.e. by issuing a warning if a string is passed and the preprocessor attribute is not empty.

@hgrecco
Copy link
Owner

hgrecco commented Jan 29, 2020

But you can do the following:

>>> UREG("count").to(UREG("%"))
<Quantity(100.0, 'percent')>

@hgrecco
Copy link
Owner

hgrecco commented Feb 10, 2020

Any PR to document this?

@eabruzzese eabruzzese linked a pull request Oct 28, 2021 that will close this issue
5 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 a pull request may close this issue.

3 participants