-
Notifications
You must be signed in to change notification settings - Fork 67
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
First pass at Python2.7 compatibility #203
Conversation
@chrisrossi @andrewsg This is almost ready, but I'm running into a problem with the kokoro build. Locally, I get 100% test coverage on 2.7, but kokoro fails because it reports only 99%. It does not say which code is not covered. Could someone try this out locally to see if you get the same result? |
@chrisrossi @andrewsg never mind, found out how to fix the coverage issue. This is ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, with notes.
google/cloud/ndb/_options.py
Outdated
] | ||
# If there are any positional arguments, get their names. | ||
# inspect.signature is not available in Python 2.7, so we use the | ||
# arguments obtained with inspect.getarspec, which come from the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in inspect.getargspec.
google/cloud/ndb/_options.py
Outdated
@@ -59,6 +58,8 @@ def options(cls, wrapped): | |||
in_options = True | |||
|
|||
elif in_options and name != "_options": | |||
print(slots) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some debugging code that got left in?
@@ -381,21 +383,25 @@ def __eq__(self, other): | |||
def __lt__(self, other): | |||
"""Less than ordering.""" | |||
if not isinstance(other, Key): | |||
return NotImplemented | |||
raise TypeError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought NotImplemented was also the protocol for Python 2 comparison functions. Am I mistaken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the protocol, but it just didn't work. The NotImplemented was being evaluated as an expression and returned a True/False value instead of raising.
google/cloud/ndb/key.py
Outdated
@@ -460,7 +466,7 @@ def __getnewargs__(self): | |||
state to pickle. The dictionary has three keys ``pairs``, ``app`` | |||
and ``namespace``. | |||
""" | |||
return ( | |||
return ( # pragma: NO COVER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we unable to test this for some reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_getnewargs is never called in Python 2 code. Might change the NO COVER to NO PY2 COVER.
google/cloud/ndb/key.py
Outdated
@@ -1410,7 +1428,7 @@ def _clean_flat_path(flat): | |||
raise exceptions.BadArgumentError( | |||
"Incomplete Key entry must be last" | |||
) | |||
elif not isinstance(id_, (str, int)): | |||
elif not isinstance(id_, (str,) + six.integer_types): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
six.string_types?
google/cloud/ndb/model.py
Outdated
@@ -3836,7 +3783,9 @@ def _comparison(self, op, value): | |||
value = self._do_validate(value) | |||
filters = [] | |||
match_keys = [] | |||
for prop in self._model_class._properties.values(): | |||
# Somehow, Python 2 and 3 return values in diiferent order, sort them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: different
Also, is there a production reason to sort them, or is it only to provide consistent ordering in unit tests? If the latter, I'd tend to sort in the test rather than in the code proper.
google/cloud/ndb/tasklets.py
Outdated
traceback = self._exception.__traceback__ | ||
except AttributeError: # pragma: NO PY3 COVER # pragma: NO BRANCH | ||
# Python 2 does not have the helpful traceback attribute, and | ||
# sice the exception is not being handled, it appears that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: since
# Python 2 does not have the helpful traceback attribute, and | ||
# sice the exception is not being handled, it appears that | ||
# sys.exec_info can't give us the traceback either. | ||
traceback = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think old NDB had some way to do this. Peek that code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far a I can see, it just returns a traceback when it was specifically set by set_exception:
tests/system/test_query.py
Outdated
|
||
query = SomeKind.query().order(SomeKind.foo) | ||
assert query.map(get_other_foo) == foos | ||
# TODO: the return with values inside the tasklet crashes tests on Python 2.7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just convert these to use "raise Return(x)" instead of "return x". Or if we want to test both, we can run different tests for python 2 and python 3. "@pytest.mark.skipif" is handy for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out it errors out before even running the tests if the return is there, but I'll use the raise Return method.
This is the first pass at getting a 2.7 branch to run. It is not intended for detailed review, but more to give an idea of what needed changing, and to allow evaluation of the main compatibility issues. Note that some of these changes broke some 3.x tests as well, which will be addressed by future work on this.