Skip to content

ureg.wraps does not work with var-positional arguments #2254

@ikondov

Description

@ikondov

I want to wrap the math.gcd function using ureg.wraps utility function (decorator). The wrapped function works only with one parameter. Called without parameters and with more than one parameter I get various behaviors / errors:

>>> import pint
>>> import math
>>> ureg = pint.UnitRegistry()
>>> gcd = ureg.wraps('=A', '=A')(math.gcd)
>>> gcd(1)
<Quantity(1, 'dimensionless')>
>>> gcd(ureg.Quantity(1))
<Quantity(1, 'dimensionless')>
>>> gcd(ureg.Quantity(1, 'm'))
<Quantity(1, 'meter')>
>>> gcd(ureg.Quantity(1), ureg.Quantity(2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pint/pint/registry_helpers.py", line 293, in wrapper
    result = func(*new_values, **new_kw)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'Quantity' object cannot be interpreted as an integer
>>> gcd()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pint/pint/registry_helpers.py", line 289, in wrapper
    new_values, new_kw, values_by_name = converter(
                                         ^^^^^^^^^^
  File "pint/pint/registry_helpers.py", line 128, in _converter
    values.append(kw[param_name])
                  ~~^^^^^^^^^^^^
KeyError: 'integers'
>>> gcd(1, 2)
<Quantity(1, 'dimensionless')>

When I create a function with *args myself the same error occurs called without parameters and another error occurs with more than one pint quantity parameters:

>>> import pint
>>> ureg = pint.UnitRegistry()
>>> def f(*x: int) -> int:
...     return sum(x)
...
>>> f_wrapped = ureg.wraps('=A', '=A')(f)
>>> f_wrapped()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pint/pint/registry_helpers.py", line 289, in wrapper
    new_values, new_kw, values_by_name = converter(
                                         ^^^^^^^^^^
  File "pint/pint/registry_helpers.py", line 128, in _converter
    values.append(kw[param_name])
                  ~~^^^^^^^^^^^^
KeyError: 'x'
>>> f_wrapped(1)
<Quantity(1, 'dimensionless')>
>>> f_wrapped(1, 2)
<Quantity(3, 'dimensionless')>
>>> f_wrapped(ureg.Quantity(1, 'm'))
<Quantity(1, 'meter')>
>>> f_wrapped(ureg.Quantity(1, 'm'), ureg.Quantity(2, 'm'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pint/pint/registry_helpers.py", line 293, in wrapper
    result = func(*new_values, **new_kw)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<stdin>", line 2, in f
  File "pint/pint/facets/plain/quantity.py", line 874, in __add__
    return self._add_sub(other, operator.add)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "pint/pint/facets/plain/quantity.py", line 101, in wrapped
    return f(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "pint/pint/facets/plain/quantity.py", line 750, in _add_sub
    raise DimensionalityError(self._units, "dimensionless")
pint.errors.DimensionalityError: Cannot convert from 'meter' to 'dimensionless'

I have python 3.12.3, pint 0.25rc2.dev28+g9325ea272 (master branch).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions