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

feat: allow overriding of protocol methods in subclasses #128

Merged
merged 7 commits into from
Jul 29, 2021
Merged

feat: allow overriding of protocol methods in subclasses #128

merged 7 commits into from
Jul 29, 2021

Conversation

Sinclert
Copy link
Contributor

This PR addresses issue #127 by extending the _handler_of function to consider the module of all the inherited classes of a certain object. This is neccesary to allow the definition of client-side custom classes that can inherit from the library ones, and override their protocol methods (__iadd__, __isub__ ...).

Additional clarifications

  • I inverted the logic of the if isinstance(obj, Vector) to reduce indentation.
  • I imported Python's contextlib.suppress helper to reduce indentation.

cc @jpivarski

@jpivarski jpivarski linked an issue Jul 29, 2021 that may be closed by this pull request
@jpivarski
Copy link
Member

I personally think that indented control structures are more clear than imperative-jumping logic like break and continue, but I'm fine with it being written like this. I checked on contextlib.suppress and it was introduced in Python 3.4, but Vector is a Python 3-only library, so that's fine.

Now, thinking about the substance of this: what this change does is it makes instances of any subclasses of VectorObject, VectorNumpy, or VectorAwkward be "lower priority" than any of these known types. That means that when a CustomVector is used in an expression with any other kind of vector, that other vector is used to compute it, regardless of whether CustomVector is derived from VectorObject, VectorNumpy, or VectorAwkward. That's probably not what you want. The reason we have these priority rules is so that single_vector_object + array_of_vectors gets computed by the array_of_vectors's methods, which broadcasts the single_vector_object to every item in the array. If it's an array-of-vectors class that gets inherited, you'd want that derived class to win over VectorObject, so that the VectorObject gets broadcasted.

What you originally described in issue #127 would be better: walk the .mro of the class object, checking to see if its __module__ is in _handler_priority, and stop when you find it, returning that as its priority. That way, a CustomSingleVector inheriting from VectorObject would have lower priority than CustomArrayOfVectors inheriting from VectorNumpy or VectorAwkward, and you can be sure to get the right broadcasting behavior from the array classes.

Nevermind: that's what you're doing already. I was misled by the "return -1 if not handler is found"—that can't happen because _get_handler_index is called on instances of VectorProtocol; they must have a VectorObject, VectorNumpy, or VectorAwkward (or other, future backends) in their inheritance tree by construction, so you could assert index != -1 before returning. Objects that aren't Vectors are continued before _get_handler_index can be called on them.

So if you think this PR is ready to merge, I am. (I'd only change the docstring of _get_handler_index to not mention the -1 case and maybe add an assertion for it.)

@jpivarski
Copy link
Member

jpivarski commented Jul 29, 2021

Thanks! Oh, if you consider this PR to be done, let me know and I'll merge it after the tests pass.

@Sinclert
Copy link
Contributor Author

You are completely right: if the _get_handler_index function is only called within the _handler_of function for-loop, then all objects are going to be a Vector or some sort.

I addressed your comment on 9c60f5f, and I think it is ready to merge.

src/vector/_methods.py Outdated Show resolved Hide resolved
@Sinclert
Copy link
Contributor Author

Just checking: would these changes produce a new minor version release? or you guys have other time-frame in mind?

I am asking because the current MadMiner approach to the subclassing is broken, and I would like to know if we should create a temporal solution, or just wait for... -check notes- vector 0.8.4 to be released.

@jpivarski
Copy link
Member

I think we can push a new patch release as soon as this is merged.

jpivarski and others added 2 commits July 29, 2021 09:59
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
@jpivarski jpivarski merged commit f02e2f0 into scikit-hep:main Jul 29, 2021
@Sinclert Sinclert deleted the feat/allow-subclasses-override branch July 29, 2021 15:42
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 this pull request may close these issues.

Allow overriding of protocol methods in subclasses
3 participants