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

implements more dunder protocols #506

Merged
merged 2 commits into from
Apr 11, 2020

Conversation

cmacdonald
Copy link
Contributor

Inspired by #494 (comment), this PR has more support for Java Collections Framework, Iterators, Iterable and Comparable

I worked from https://rszalski.github.io/magicmethods/. Various test cases included.

Ones I didn't implement:

  • __hash__(self) - we couldnt guarentee the Python contract of hashCode() vs equals() wouldnt have been implemented on the Java side, as Comparable doesnt require it.
  • __nonzero__(self) - java.lang.Boolean (etc) are automapped anyway
  • __str__(self) - this could be mapped this to toString(), but it was still handy in Python to know the jnius representation, i.e. that its a wrapper object.

I haven't verified on Python versions other than 3.6 and Java versions other than 13, so would appreciate the github workflow being run on this PR.

Copy link
Member

@tshirtman tshirtman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really not much to say there, it's really nice.

About __str__ i think that usage should be achieved by repr(obj) (implemented by __repr__) instead of str(obj), but it's true that it's very common to use the latter rather than the former in programs to display debug info, and it sometime accidentally makes it easier to spot issues, so i understand this decision for practical reasons.

jnius/reflect.py Outdated
@@ -339,17 +339,58 @@ def _getitem(self, index):
else:
raise

#dunder method for java.util.Map
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make these docstrings instead :)

class TestCollections(unittest.TestCase):

def __init__(self, *args, **kwargs):
super(TestCollections, self).__init__(*args, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious why this pass-through override is needed? leftover from tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. i developed the protocol_map in the test constructor before copying into reflect.py. do you want removed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would be appreciated, not a big deal, but good dead code is deleted code :P.

@cmacdonald
Copy link
Contributor Author

feedback address, thanks!

@tshirtman tshirtman merged commit dd8fbdc into kivy:master Apr 11, 2020
@cmacdonald
Copy link
Contributor Author

problems on Python 2 - see https://github.com/kivy/pyjnius/runs/579173024?check_suite_focus=true#step:9:138. Do you have a Python 2 dev environment @tshirtman ?

@tshirtman
Copy link
Member

woopsie, yes i do, i should have tested, thanks for the heads up!

@tshirtman
Copy link
Member

tshirtman commented Apr 11, 2020

i can reproduce localy, let's try to make sense of it :]
the call to keySet() and to iterator() on it both, work, the issue seems to be when iterating on the result.

@cmacdonald
Copy link
Contributor Author

https://github.com/kivy/pyjnius/runs/579173024?check_suite_focus=true#step:9:138
Python 2 needs next() rather than __next__()? (see https://stackoverflow.com/questions/41524531/python-2-vs-python-3-class-with-iter) The Java next() implementation wont raise StopIteration.

Not sure how to fix this, as I'm not sure we can call "super().next()"?

https://github.com/kivy/pyjnius/runs/579173024?check_suite_focus=true#step:9:181 this line of code should be removed.

@tshirtman
Copy link
Member

yeah, it calls next() all the time, so the _iterator_next is not used, and so doesn't check for hasNext(). i think the last link is not what you wanted to paste.

@cmacdonald
Copy link
Contributor Author

cmacdonald commented Apr 11, 2020

Last link was not a fix for this, just an observation that a print(dir()) had made it into a test

We would need a special if() in autoclass for Python 2, which would need to rename the classDict entry for the Java next(). As we have discovered with the fields, renaming them on the Python side is tricky.

How long do you plan to support Python 2 for?

Or we "degrade" the protocol_map support for Python 2.

@tshirtman
Copy link
Member

tshirtman commented Apr 11, 2020

How long do you plan to support Python 2 for?

This is a strong reminder that we probably want to drop it next release :D (it would be a bit abrubt to drop without forewarning, right?) i'm myself would be perfectly fine dropping it asap, normaly everybody using pyjnius for android should have migrated to python3 anyway, as this one did drop support a couple releases ago.

We would need a special if() in autoclass for Python 2, which would need to rename the classDict entry for the Java next(). As we have discovered with the fields, renaming them on the Python side is tricky.

Yeah, my ideas of how to fix this on the python side are quite gross, like

def _iterator_iter(self):
    print("starting iterator")
    if PY2:
        # in py2 the next() is called on the iterator, not __next__
        # so we need to monkey patch this one to check hasNext
        j_next = self.next
        log.debug("monkey patching next()")
        def safe_next():
            if not self.hasNext():
                raise StopIteration()
            return j_next()
        self.next = safe_next

    return self

(though it's not working yet in my tests, not sure why, but if it did, would that be fine?)

@cmacdonald
Copy link
Contributor Author

I can live with that implementation until Python 2 expires.

@tshirtman
Copy link
Member

so this works, and feels a bit less hacky #507

@cmacdonald cmacdonald deleted the more_dunder_protocols branch April 19, 2020 17:27
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.

2 participants