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

how to make sure Quantity cannot wrap a user defined object #2063

Open
seb5g opened this issue Oct 19, 2024 · 5 comments
Open

how to make sure Quantity cannot wrap a user defined object #2063

seb5g opened this issue Oct 19, 2024 · 5 comments

Comments

@seb5g
Copy link

seb5g commented Oct 19, 2024

Hi there,
I'm developing a data acquisition framework (PyMoDAQ) and data handling. The main objects (let's say DataBase holds data as a list of numpy arrays and an attribute being units. So I'm using quite a bit of pint functionalities under the hood, simply adding compatibility for list of ndarrays. By implementing array_ufunc and array_function and using their implementation in pint, I could quickly get it working for many functions. However when I execute:

Quantity(1, 's') * DataBase(...)

I'm getting a quantity with a magnitude being my DataBase object.

When I'm doing the other way around:

 DataBase(...) * Quantity(1, 's')

I properly (what I want at least) get the product of the underlying quantities (with units handling).

Here comes the question:

How can I be sure that this is always my DataBase that will have the priority?

I tried the __array_priority__ attribute (I saw you set it to 17 for your numpy wrapping quantities) but it doesn't work.

I also almost understand the idea of upcast_type but i'm actually not sure if this is or not related to my issue...

Thxs

@andrewgsavage
Copy link
Collaborator

yea have a try at adding it to upcast types

see #1888

@seb5g
Copy link
Author

seb5g commented Oct 19, 2024

That's working! however my DataBase object is actually a base class inherited by many subclass. If I add the DataBase in upcast then only object of this type will work but not the inheriting ones. I could add all those in the upcast_type_names but do you know of a way to do it for all subclass at once?

@andrewgsavage
Copy link
Collaborator

something like

class DataBase():
   def __new__(cls):
      if not pint.compat.is_upcast_type(cls):
         # add class to upcast types here

@seb5g
Copy link
Author

seb5g commented Oct 20, 2024

nice, I wrote:

    def __new__(cls, *args, **kwargs):
        if not pint.compat.is_upcast_type(cls):
            upcast_type_map.update({f'{cls.__module__}.{cls.__name__}': None})
            # this will make sure, these objects are not wrapped by pint
        return super().__new__(cls)

and all subclass are upcasted! Maybe it could be nice and clearer to add this in the doc rather than digging into past issues?

@andrewgsavage
Copy link
Collaborator

yea please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants