Skip to content

Commit e9d2ae2

Browse files
Backport PR #51640 on branch 2.0.x (COMPAT: Update code for latest Cython 3 beta) (#51728)
Backport PR #51640: COMPAT: Update code for latest Cython 3 beta Co-authored-by: Thomas Li <[email protected]>
1 parent fb35381 commit e9d2ae2

File tree

9 files changed

+44
-19
lines changed

9 files changed

+44
-19
lines changed

.github/workflows/ubuntu.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ on:
1414
paths-ignore:
1515
- "doc/**"
1616

17-
env:
18-
PANDAS_CI: 1
19-
2017
permissions:
2118
contents: read
2219

@@ -32,6 +29,7 @@ jobs:
3229
env_file: [actions-38.yaml, actions-39.yaml, actions-310.yaml, actions-311.yaml]
3330
pattern: ["not single_cpu", "single_cpu"]
3431
pyarrow_version: ["8", "9", "10"]
32+
pandas_ci: [1]
3533
include:
3634
- name: "Downstream Compat"
3735
env_file: actions-38-downstream_compat.yaml
@@ -76,6 +74,9 @@ jobs:
7674
env_file: actions-310-numpydev.yaml
7775
pattern: "not slow and not network and not single_cpu"
7876
test_args: "-W error::DeprecationWarning -W error::FutureWarning"
77+
# TODO(cython3): Re-enable once next-beta(after beta 1) comes out
78+
# There are some warnings failing the build with -werror
79+
pandas_ci: 0
7980
exclude:
8081
- env_file: actions-38.yaml
8182
pyarrow_version: "8"
@@ -99,6 +100,7 @@ jobs:
99100
LC_ALL: ${{ matrix.lc_all || '' }}
100101
PANDAS_DATA_MANAGER: ${{ matrix.pandas_data_manager || 'block' }}
101102
PANDAS_COPY_ON_WRITE: ${{ matrix.pandas_copy_on_write || '0' }}
103+
PANDAS_CI: ${{ matrix.pandas_ci }}
102104
TEST_ARGS: ${{ matrix.test_args || '' }}
103105
PYTEST_WORKERS: ${{ contains(matrix.pattern, 'not single_cpu') && 'auto' || '1' }}
104106
PYTEST_TARGET: ${{ matrix.pytest_target || 'pandas' }}

pandas/_libs/algos.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ cpdef ndarray[int64_t, ndim=1] unique_deltas(const int64_t[:] arr):
166166

167167
@cython.wraparound(False)
168168
@cython.boundscheck(False)
169-
def is_lexsorted(list_of_arrays: list) -> bint:
169+
def is_lexsorted(list_of_arrays: list) -> bool:
170170
cdef:
171171
Py_ssize_t i
172172
Py_ssize_t n, nlevels

pandas/_libs/join.pyx

+16-6
Original file line numberDiff line numberDiff line change
@@ -834,10 +834,10 @@ def asof_join_forward_on_X_by_Y(numeric_t[:] left_values,
834834
return left_indexer, right_indexer
835835

836836

837-
def asof_join_nearest_on_X_by_Y(numeric_t[:] left_values,
838-
numeric_t[:] right_values,
839-
by_t[:] left_by_values,
840-
by_t[:] right_by_values,
837+
def asof_join_nearest_on_X_by_Y(ndarray[numeric_t] left_values,
838+
ndarray[numeric_t] right_values,
839+
ndarray[by_t] left_by_values,
840+
ndarray[by_t] right_by_values,
841841
bint allow_exact_matches=True,
842842
tolerance=None,
843843
bint use_hashtable=True):
@@ -850,7 +850,17 @@ def asof_join_nearest_on_X_by_Y(numeric_t[:] left_values,
850850
numeric_t bdiff, fdiff
851851

852852
# search both forward and backward
853-
bli, bri = asof_join_backward_on_X_by_Y(
853+
# TODO(cython3):
854+
# Bug in beta1 preventing Cython from choosing
855+
# right specialization when one fused memview is None
856+
# Doesn't matter what type we choose
857+
# (nothing happens anyways since it is None)
858+
# GH 51640
859+
if left_by_values is not None and left_by_values.dtype != object:
860+
by_dtype = f"{left_by_values.dtype}_t"
861+
else:
862+
by_dtype = object
863+
bli, bri = asof_join_backward_on_X_by_Y[f"{left_values.dtype}_t", by_dtype](
854864
left_values,
855865
right_values,
856866
left_by_values,
@@ -859,7 +869,7 @@ def asof_join_nearest_on_X_by_Y(numeric_t[:] left_values,
859869
tolerance,
860870
use_hashtable
861871
)
862-
fli, fri = asof_join_forward_on_X_by_Y(
872+
fli, fri = asof_join_forward_on_X_by_Y[f"{left_values.dtype}_t", by_dtype](
863873
left_values,
864874
right_values,
865875
left_by_values,

pandas/_libs/lib.pyx

+4-4
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ def memory_usage_of_objects(arr: object[:]) -> int64_t:
150150

151151
Does not include the actual bytes of the pointers
152152
"""
153-
i: Py_ssize_t
154-
n: Py_ssize_t
155-
size: int64_t
153+
cdef:
154+
Py_ssize_t i
155+
Py_ssize_t n
156+
int64_t size = 0
156157

157-
size = 0
158158
n = len(arr)
159159
for i in range(n):
160160
size += arr[i].__sizeof__()

pandas/_libs/sparse_op_helper.pxi.in

+6-2
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ def get_dispatch(dtypes):
128128

129129
{{for opname, dtype, rdtype in get_dispatch(dtypes)}}
130130

131-
131+
{{if opname == "pow"}}
132+
@cython.cpow(True) # Cython 3 matches Python pow, which isn't what we want here
133+
{{endif}}
132134
@cython.wraparound(False)
133135
@cython.boundscheck(False)
134136
cdef tuple block_op_{{opname}}_{{dtype}}({{dtype}}_t[:] x_,
@@ -229,7 +231,9 @@ cdef tuple block_op_{{opname}}_{{dtype}}({{dtype}}_t[:] x_,
229231

230232
return out, out_index, {{(opname, 'xfill', 'yfill', dtype) | get_op}}
231233

232-
234+
{{if opname == "pow"}}
235+
@cython.cpow(True) # Cython 3 matches Python pow, which isn't what we want here
236+
{{endif}}
233237
@cython.wraparound(False)
234238
@cython.boundscheck(False)
235239
cdef tuple int_op_{{opname}}_{{dtype}}({{dtype}}_t[:] x_,

pandas/_libs/tslibs/offsets.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4563,7 +4563,7 @@ def roll_qtrday(other: datetime, n: int, month: int,
45634563
cdef int _roll_qtrday(npy_datetimestruct* dts,
45644564
int n,
45654565
int months_since,
4566-
str day_opt) nogil except? -1:
4566+
str day_opt) except? -1 nogil:
45674567
"""
45684568
See roll_qtrday.__doc__
45694569
"""

pandas/_libs/tslibs/timedeltas.pyx

+1
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ cdef int64_t _item_to_timedelta64(
489489
raise
490490

491491

492+
@cython.cpow(True)
492493
cdef int64_t parse_timedelta_string(str ts) except? -1:
493494
"""
494495
Parse a regular format timedelta string. Return an int64_t (in ns)

pandas/_libs/window/aggregations.pyx

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ from numpy cimport (
2121

2222
cnp.import_array()
2323

24+
import cython
25+
2426
from pandas._libs.algos import is_monotonic
2527

2628

@@ -1733,7 +1735,7 @@ def roll_weighted_var(const float64_t[:] values, const float64_t[:] weights,
17331735

17341736
# ----------------------------------------------------------------------
17351737
# Exponentially weighted moving
1736-
1738+
@cython.cpow(True)
17371739
def ewm(const float64_t[:] vals, const int64_t[:] start, const int64_t[:] end,
17381740
int minp, float64_t com, bint adjust, bint ignore_na,
17391741
const float64_t[:] deltas=None, bint normalize=True) -> np.ndarray:

pandas/core/reshape/merge.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -2160,7 +2160,13 @@ def injection(obj):
21602160
else:
21612161
# choose appropriate function by type
21622162
func = _asof_by_function(self.direction)
2163-
return func(
2163+
# TODO(cython3):
2164+
# Bug in beta1 preventing Cython from choosing
2165+
# right specialization when one fused memview is None
2166+
# Doesn't matter what type we choose
2167+
# (nothing happens anyways since it is None)
2168+
# GH 51640
2169+
return func[f"{left_values.dtype}_t", object](
21642170
left_values,
21652171
right_values,
21662172
None,

0 commit comments

Comments
 (0)