-
-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
CI: Test on Cython 3.0 on numpydev #46029
Changes from 28 commits
cdd46ba
27a674b
d22e588
646dced
8328092
4a87227
d5a9c7e
51ce2b2
5aa9f13
de88da9
ae3e6fa
89891f7
dc7517a
416bca5
9599b74
127e97b
84d742d
6a2cb90
fd22fdb
fa2c1e2
0e3b56a
a154bb2
7259c4c
f123a47
313b8eb
00c492d
71cee4e
7f10301
92325d7
eaea742
db69f58
f467452
7bc1609
9557ae9
efd227a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -404,6 +404,8 @@ cdef class Interval(IntervalMixin): | |
): | ||
return Interval(self.left + y, self.right + y, closed=self.closed) | ||
elif ( | ||
# __radd__ pattern | ||
# TODO(cython3): remove this | ||
isinstance(y, Interval) | ||
and ( | ||
isinstance(self, numbers.Number) | ||
|
@@ -414,6 +416,15 @@ cdef class Interval(IntervalMixin): | |
return Interval(y.left + self, y.right + self, closed=y.closed) | ||
return NotImplemented | ||
|
||
def __radd__(self, other): | ||
if ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a huge fan of doing these checks(probably has an adverse effect on performance). Unfortunately, Cython gets stuck in a infinite recursion look from one binop to the reverse binop, when the reverse binop calls the regular binop and the regular binop raises NotImplemented. Not sure if this is intended by Cython or a bug, but this works around it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, if you implement infinite recursion, then you get infinite recursion. No surprise here. Consider extracting a separate function for the actual implementation instead, and make both special methods call that, in their own way. Then you can catch the "can't handle that" cases in one place, and otherwise run through the addition code and be done, rather than risking infinite recursion in the first place. |
||
isinstance(other, numbers.Number) | ||
or PyDelta_Check(other) | ||
or is_timedelta64_object(other) | ||
): | ||
return Interval(self.left + other, self.right + other, closed=self.closed) | ||
return NotImplemented | ||
|
||
def __sub__(self, y): | ||
if ( | ||
isinstance(y, numbers.Number) | ||
|
@@ -427,9 +438,16 @@ cdef class Interval(IntervalMixin): | |
if isinstance(y, numbers.Number): | ||
return Interval(self.left * y, self.right * y, closed=self.closed) | ||
elif isinstance(y, Interval) and isinstance(self, numbers.Number): | ||
# __radd__ semantics | ||
# TODO(cython3): remove this | ||
return Interval(y.left * self, y.right * self, closed=y.closed) | ||
return NotImplemented | ||
|
||
def __rmul__(self, other): | ||
if isinstance(other, numbers.Number): | ||
return Interval(self.left * other, self.right * other, closed=self.closed) | ||
return NotImplemented | ||
|
||
def __truediv__(self, y): | ||
if isinstance(y, numbers.Number): | ||
return Interval(self.left / y, self.right / y, closed=self.closed) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1710,6 +1710,7 @@ cdef class _Period(PeriodMixin): | |
def __add__(self, other): | ||
if not is_period_object(self): | ||
# cython semantics; this is analogous to a call to __radd__ | ||
# TODO(cython3): remove this | ||
if self is NaT: | ||
return NaT | ||
return other.__add__(self) | ||
|
@@ -1734,6 +1735,11 @@ cdef class _Period(PeriodMixin): | |
|
||
return NotImplemented | ||
|
||
def __radd__(self, other): | ||
if other is NaT: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this looks harmless, but is it necessary? would falling through to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think falling through works. (I vaguely remember some tests failing because of this) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you double-check and add a comment for when future-me thinks this looks weird and doesn't remember this thread There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm. Looks like this might work? Checking with CI. |
||
return NaT | ||
return self.__add__(other) | ||
|
||
def __sub__(self, other): | ||
if not is_period_object(self): | ||
# cython semantics; this is like a call to __rsub__ | ||
|
@@ -1760,6 +1766,11 @@ cdef class _Period(PeriodMixin): | |
|
||
return NotImplemented | ||
|
||
def __rsub__(self, other): | ||
if other is NaT: | ||
return NaT | ||
return NotImplemented | ||
|
||
def asfreq(self, freq, how='E') -> "Period": | ||
""" | ||
Convert Period to desired frequency, at the start or end of the interval. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -282,8 +282,10 @@ cdef class _Timestamp(ABCTimestamp): | |
return other.tzinfo is None | ||
|
||
def __add__(self, other): | ||
cdef: | ||
int64_t nanos = 0 | ||
lithomas1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# TODO: There is a Cython 3 bug where self.values + nanos | ||
# would silently overflow if this is defined | ||
#cdef: | ||
# int64_t nanos = 0 | ||
lithomas1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if is_any_td_scalar(other): | ||
nanos = delta_to_nanoseconds(other) | ||
|
@@ -308,9 +310,16 @@ cdef class _Timestamp(ABCTimestamp): | |
|
||
elif not isinstance(self, _Timestamp): | ||
# cython semantics, args have been switched and this is __radd__ | ||
# TODO(cython3): remove this it moved to __radd__ | ||
return other.__add__(self) | ||
return NotImplemented | ||
|
||
def __radd__(self, other): | ||
# Have to duplicate checks to avoid infinite recursion due to NotImplemented | ||
if is_any_td_scalar(other) or is_integer_object(other) or is_array(other): | ||
return self.__add__(other) | ||
return NotImplemented | ||
|
||
def __sub__(self, other): | ||
|
||
if is_any_td_scalar(other) or is_integer_object(other): | ||
|
@@ -337,6 +346,7 @@ cdef class _Timestamp(ABCTimestamp): | |
and (PyDateTime_Check(other) or is_datetime64_object(other))): | ||
# both_timestamps is to determine whether Timedelta(self - other) | ||
# should raise the OOB error, or fall back returning a timedelta. | ||
# TODO(cython3): clean out the bits that moved to __rsub__ | ||
both_timestamps = (isinstance(other, _Timestamp) and | ||
isinstance(self, _Timestamp)) | ||
if isinstance(self, _Timestamp): | ||
|
@@ -367,10 +377,22 @@ cdef class _Timestamp(ABCTimestamp): | |
elif is_datetime64_object(self): | ||
# GH#28286 cython semantics for __rsub__, `other` is actually | ||
# the Timestamp | ||
# TODO(cython3): remove this, this moved to __rsub__ | ||
return type(other)(self) - other | ||
|
||
return NotImplemented | ||
|
||
def __rsub__(self, other): | ||
if PyDateTime_Check(other): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any problem with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually copy-pasted from the sub code block above(including the contents). This actually shows up in other tests in addition to the stata ones(which is why I needed to copy-paste it).
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. Took me a few tries to find a relevant example:
returns a pytimedelta. There's a small hiccup (doesn't matter for this PR, but i want to write it down before I forget it) if the Timestamp has nanos:
We lose the nanoseconds. In principle we could call to_pydatetime() and get a warning if appropropriate. |
||
try: | ||
return type(self)(other) - self | ||
except (OverflowError, OutOfBoundsDatetime) as err: | ||
# We get here in stata tests, fall back to stdlib datetime | ||
# method and return stdlib timedelta object | ||
pass | ||
elif is_datetime64_object(other): | ||
return type(self)(other) - self | ||
return NotImplemented | ||
# ----------------------------------------------------------------- | ||
|
||
cdef int64_t _maybe_convert_value_to_local(self): | ||
|
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.
prob should make an issue for this