Skip to content

Commit f1fe651

Browse files
authored
Merge pull request #590 from light-curve/pyo3-0.27
Bump PyO3 and numpy to 0.27
2 parents 235f7d1 + 8dbe9e9 commit f1fe651

File tree

7 files changed

+62
-59
lines changed

7 files changed

+62
-59
lines changed

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
### Changed
1515

16-
- Bump `pyO3` and `rust-numpy` to 0.26.0: introduce Python build 3.14/3.14t support https://github.com/light-curve/light-curve-python/pull/553
17-
- **Breaking** macOS x86\_64 binary wheel now requires macOS 15 instead of 13 https://github.com/light-curve/light-curve-python/issues/587
16+
- Bump `pyO3` and `rust-numpy` from 0.25.0 to 0.27.0: introduce Python build 3.14/3.14t
17+
support https://github.com/light-curve/light-curve-python/pull/553 https://github.com/light-curve/light-curve-python/pull/590
18+
- **Breaking** macOS x86\_64 binary wheel now requires macOS 15 instead of
19+
13 https://github.com/light-curve/light-curve-python/issues/587
1820

1921
### Deprecated
2022

light-curve/Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

light-curve/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ mimalloc = { version = "0.1.48", features = [
4747
"local_dynamic_tls",
4848
], optional = true }
4949
ndarray = { version = "0.16.1", features = ["rayon"] }
50-
numpy = "0.26.0"
50+
numpy = "0.27.0"
5151
num_cpus = "1.17.0"
5252
num-traits = "0.2"
5353
once_cell = "1"
54-
pyo3 = { version = "0.26.0", features = [
54+
pyo3 = { version = "0.27.1", features = [
5555
"extension-module",
5656
"multiple-pymethods",
5757
] }

light-curve/src/dmdt.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ where
112112
let wrapped_t_ = t_
113113
.into_iter()
114114
.enumerate()
115-
.map(|(i, t)| match t.downcast::<PyArray1<T>>() {
115+
.map(|(i, t)| match t.cast::<PyArray1<T>>() {
116116
Ok(a) => Ok(a.readonly()),
117117
Err(_) => Err(Exception::TypeError(format!(
118118
"t_[{}] has mismatched dtype with the t_[0] which is {}",
@@ -189,8 +189,8 @@ where
189189
.into_iter()
190190
.enumerate()
191191
.map(|(i, (t, m))| {
192-
let t = t.downcast::<PyArray1<T>>().map(|a| a.readonly());
193-
let m = m.downcast::<PyArray1<T>>().map(|a| a.readonly());
192+
let t = t.cast::<PyArray1<T>>().map(|a| a.readonly());
193+
let m = m.cast::<PyArray1<T>>().map(|a| a.readonly());
194194
match (t, m) {
195195
(Ok(t), Ok(m)) => Ok((t, m)),
196196
_ => Err(Exception::TypeError(format!(
@@ -256,8 +256,8 @@ where
256256
.into_iter()
257257
.enumerate()
258258
.map(|(i, (t, m))| {
259-
let t = t.downcast::<PyArray1<T>>().map(|a| a.readonly());
260-
let m = m.downcast::<PyArray1<T>>().map(|a| a.readonly());
259+
let t = t.cast::<PyArray1<T>>().map(|a| a.readonly());
260+
let m = m.cast::<PyArray1<T>>().map(|a| a.readonly());
261261
match (t, m) {
262262
(Ok(t), Ok(m)) => {
263263
let t: ContArray<_> = t.as_array().into();
@@ -332,9 +332,9 @@ where
332332
.into_iter()
333333
.enumerate()
334334
.map(|(i, (t, m, sigma))| {
335-
let t = t.downcast::<PyArray1<T>>().map(|a| a.readonly());
336-
let m = m.downcast::<PyArray1<T>>().map(|a| a.readonly());
337-
let sigma = sigma.downcast::<PyArray1<T>>().map(|a| a.readonly());
335+
let t = t.cast::<PyArray1<T>>().map(|a| a.readonly());
336+
let m = m.cast::<PyArray1<T>>().map(|a| a.readonly());
337+
let sigma = sigma.cast::<PyArray1<T>>().map(|a| a.readonly());
338338

339339
match (t, m, sigma) {
340340
(Ok(t), Ok(m), Ok(sigma)) => Ok((t, m, Self::sigma_to_err2(sigma))),
@@ -406,9 +406,9 @@ where
406406
.into_iter()
407407
.enumerate()
408408
.map(|(i, (t, m, sigma))| {
409-
let t = t.downcast::<PyArray1<T>>().map(|a| a.readonly());
410-
let m = m.downcast::<PyArray1<T>>().map(|a| a.readonly());
411-
let sigma = sigma.downcast::<PyArray1<T>>().map(|a| a.readonly());
409+
let t = t.cast::<PyArray1<T>>().map(|a| a.readonly());
410+
let m = m.cast::<PyArray1<T>>().map(|a| a.readonly());
411+
let sigma = sigma.cast::<PyArray1<T>>().map(|a| a.readonly());
412412

413413
match (t, m, sigma) {
414414
(Ok(t), Ok(m), Ok(sigma)) => {

light-curve/src/features.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,10 @@ impl PyFeatureEvaluator {
339339
.into_iter()
340340
.enumerate()
341341
.map(|(i, (t, m, sigma))| {
342-
let t = t.downcast::<PyArray1<T>>().map(|a| a.readonly());
343-
let m = m.downcast::<PyArray1<T>>().map(|a| a.readonly());
342+
let t = t.cast::<PyArray1<T>>().map(|a| a.readonly());
343+
let m = m.cast::<PyArray1<T>>().map(|a| a.readonly());
344344
let sigma = match &sigma {
345-
Some(sigma) => sigma.downcast::<PyArray1<T>>().map(|a| Some(a.readonly())),
345+
Some(sigma) => sigma.cast::<PyArray1<T>>().map(|a| Some(a.readonly())),
346346
None => Ok(None),
347347
};
348348

@@ -1014,7 +1014,7 @@ macro_rules! fit_evaluator {
10141014

10151015
let make_transformation = match transform {
10161016
None => false,
1017-
Some(py_transform) => match py_transform.downcast::<PyBool>() {
1017+
Some(py_transform) => match py_transform.cast::<PyBool>() {
10181018
Ok(py_bool) => py_bool.is_true(),
10191019
Err(_) => return Err(PyValueError::new_err(
10201020
"transform must be a bool or None, other types are not implemented yet",
@@ -1262,7 +1262,7 @@ impl Bins {
12621262
let mut eval_f32 = lcf::Bins::default();
12631263
let mut eval_f64 = lcf::Bins::default();
12641264
for x in features.try_iter()? {
1265-
let py_feature = x?.downcast::<PyFeatureEvaluator>()?.borrow();
1265+
let py_feature = x?.cast::<PyFeatureEvaluator>()?.borrow();
12661266
eval_f32.add_feature(py_feature.feature_evaluator_f32.clone());
12671267
eval_f64.add_feature(py_feature.feature_evaluator_f64.clone());
12681268
}
@@ -1684,7 +1684,7 @@ impl Periodogram {
16841684
const STEP_SIZE_TOLLERANCE: f64 = 10.0 * f32::EPSILON as f64;
16851685

16861686
// It is more likely for users to give f64 array
1687-
let freqs_f64 = PyArrayLike1::<f64, AllowTypeChange>::extract_bound(&freqs)?;
1687+
let freqs_f64 = PyArrayLike1::<f64, AllowTypeChange>::extract(freqs.as_borrowed())?;
16881688
let freqs_f64 = freqs_f64.readonly();
16891689
let freqs_f64 = freqs_f64.as_array();
16901690
let size = freqs_f64.len();
@@ -1726,7 +1726,8 @@ impl Periodogram {
17261726

17271727
let freq_grid_f32 = match &freq_grid_f64 {
17281728
FreqGrid::Arbitrary(_) => {
1729-
let freqs_f32 = PyArrayLike1::<f32, AllowTypeChange>::extract_bound(&freqs)?;
1729+
let freqs_f32 =
1730+
PyArrayLike1::<f32, AllowTypeChange>::extract(freqs.as_borrowed())?;
17301731
let freqs_f32 = freqs_f32.readonly();
17311732
let freqs_f32 = freqs_f32.as_array();
17321733
FreqGrid::from_array(freqs_f32)
@@ -1748,7 +1749,7 @@ impl Periodogram {
17481749

17491750
if let Some(features) = features {
17501751
for x in features.try_iter()? {
1751-
let py_feature = x?.downcast::<PyFeatureEvaluator>()?.borrow();
1752+
let py_feature = x?.cast::<PyFeatureEvaluator>()?.borrow();
17521753
eval_f32.add_feature(py_feature.feature_evaluator_f32.clone());
17531754
eval_f64.add_feature(py_feature.feature_evaluator_f64.clone());
17541755
}

light-curve/src/np_array.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl DType for f64 {
2727
}
2828

2929
pub(crate) fn unknown_type_exception(name: &str, obj: &Bound<PyAny>) -> Exception {
30-
let message = if let Ok(arr) = obj.downcast::<PyUntypedArray>() {
30+
let message = if let Ok(arr) = obj.cast::<PyUntypedArray>() {
3131
let ndim = arr.ndim();
3232
if ndim != 1 {
3333
format!("'{name}' is a {ndim}-d array, only 1-d arrays are supported.")
@@ -59,13 +59,13 @@ fn cast_fail_reason<const N: usize>(
5959
let first_name = names.first().expect("Empty names slice");
6060
let fist_obj = objects.first().expect("Empty objects slice");
6161

62-
// If the very first argument downcast
62+
// If the very first argument cast
6363
if idx == 0 {
6464
return unknown_type_exception(first_name, fist_obj);
6565
}
6666

67-
let maybe_first_f32_array = try_downcast_to_f32_array(objects[0]);
68-
let maybe_first_f64_array = try_downcast_to_f64_array(objects[0], cast);
67+
let maybe_first_f32_array = try_cast_to_f32_array(objects[0]);
68+
let maybe_first_f64_array = try_cast_to_f64_array(objects[0], cast);
6969
let (first_arr, first_dtype_name) = if let Some(f32_array) = maybe_first_f32_array.as_ref() {
7070
(f32_array.as_untyped(), f32::dtype_name())
7171
} else if let Some(f64_array) = maybe_first_f64_array.as_ref() {
@@ -79,7 +79,7 @@ fn cast_fail_reason<const N: usize>(
7979
.get(idx)
8080
.expect("idx is out of bounds of objects slice");
8181

82-
let error_message = if let Ok(fail_arr) = fail_obj.downcast::<PyUntypedArray>() {
82+
let error_message = if let Ok(fail_arr) = fail_obj.cast::<PyUntypedArray>() {
8383
if fail_arr.ndim() != 1 {
8484
format!(
8585
"'{}' is a {}-d array, only 1-d arrays are supported.",
@@ -125,12 +125,12 @@ impl<const N: usize> GenericPyReadonlyArrays<'_, N> {
125125
}
126126
}
127127

128-
fn try_downcast_objects_to_f32_arrays<'py, const N: usize>(
128+
fn try_cast_objects_to_f32_arrays<'py, const N: usize>(
129129
objects: &[&Bound<'py, PyAny>; N],
130130
) -> [Option<PyReadonlyArray1<'py, f32>>; N] {
131131
let mut arrays = [const { None }; N];
132132
for (&obj, arr) in objects.iter().zip(arrays.iter_mut()) {
133-
*arr = try_downcast_to_f32_array(obj);
133+
*arr = try_cast_to_f32_array(obj);
134134
// If we cannot cast an array, we stop trying for future arguments
135135
if arr.is_none() {
136136
break;
@@ -139,18 +139,18 @@ fn try_downcast_objects_to_f32_arrays<'py, const N: usize>(
139139
arrays
140140
}
141141

142-
fn try_downcast_to_f32_array<'py>(obj: &Bound<'py, PyAny>) -> Option<PyReadonlyArray1<'py, f32>> {
143-
let py_array = obj.downcast::<PyArray1<f32>>().ok()?;
142+
fn try_cast_to_f32_array<'py>(obj: &Bound<'py, PyAny>) -> Option<PyReadonlyArray1<'py, f32>> {
143+
let py_array = obj.cast::<PyArray1<f32>>().ok()?;
144144
Some(py_array.readonly())
145145
}
146146

147-
fn try_downcast_to_f64_array<'py>(
147+
fn try_cast_to_f64_array<'py>(
148148
obj: &Bound<'py, PyAny>,
149149
cast: bool,
150150
) -> Option<PyReadonlyArray1<'py, f64>> {
151-
match (obj.downcast::<PyArray1<f64>>(), cast) {
151+
match (obj.cast::<PyArray1<f64>>(), cast) {
152152
(Ok(py_array), _) => Some(py_array.readonly()),
153-
(Err(_), true) => match PyArrayLike1::<f64, AllowTypeChange>::extract_bound(obj) {
153+
(Err(_), true) => match PyArrayLike1::<f64, AllowTypeChange>::extract(obj.as_borrowed()) {
154154
Ok(py_array) => Some(py_array.readonly()),
155155
Err(_) => None,
156156
},
@@ -168,11 +168,11 @@ const fn index<const N: usize>() -> [usize; N] {
168168
arr
169169
}
170170

171-
fn downcast_objects_cast<'py, const N: usize>(
171+
fn cast_objects_with_dtype_change<'py, const N: usize>(
172172
names: &'static [&'static str; N],
173173
objects: &[&Bound<'py, PyAny>; N],
174174
) -> Res<GenericPyReadonlyArrays<'py, N>> {
175-
let f32_arrays = try_downcast_objects_to_f32_arrays(objects);
175+
let f32_arrays = try_cast_objects_to_f32_arrays(objects);
176176

177177
if f32_arrays.iter().all(|arr| arr.is_some()) {
178178
Ok(GenericPyReadonlyArrays::F32(
@@ -183,7 +183,7 @@ fn downcast_objects_cast<'py, const N: usize>(
183183
let f64_arr = if let Some(f32_arr) = &f32_arrays[i] {
184184
f32_arr.cast_array::<f64>(false)?.readonly()
185185
} else {
186-
try_downcast_to_f64_array(objects[i], true)
186+
try_cast_to_f64_array(objects[i], true)
187187
.ok_or_else(|| cast_fail_reason(i, names, objects, true))?
188188
};
189189
Ok(f64_arr)
@@ -193,11 +193,11 @@ fn downcast_objects_cast<'py, const N: usize>(
193193
}
194194
}
195195

196-
fn downcast_objects_no_cast<'py, const N: usize>(
196+
fn cast_objects_no_dtype_change<'py, const N: usize>(
197197
names: &'static [&'static str; N],
198198
objects: &[&Bound<'py, PyAny>; N],
199199
) -> Res<GenericPyReadonlyArrays<'py, N>> {
200-
let f32_arrays = try_downcast_objects_to_f32_arrays(objects);
200+
let f32_arrays = try_cast_objects_to_f32_arrays(objects);
201201

202202
if f32_arrays.iter().all(|arr| arr.is_some()) {
203203
Ok(GenericPyReadonlyArrays::F32(
@@ -208,7 +208,7 @@ fn downcast_objects_no_cast<'py, const N: usize>(
208208
let f64_arrays = objects
209209
.map_option(|obj| {
210210
valid_f64_count += 1;
211-
try_downcast_to_f64_array(obj, false)
211+
try_cast_to_f64_array(obj, false)
212212
})
213213
.ok_or_else(|| {
214214
let valid_f32_count = f32_arrays.iter().filter(|arr| arr.is_some()).count();
@@ -224,7 +224,7 @@ fn downcast_objects_no_cast<'py, const N: usize>(
224224
}
225225
}
226226

227-
pub(crate) fn downcast_and_validate<'py, const N: usize>(
227+
pub(crate) fn cast_and_validate<'py, const N: usize>(
228228
names: &'static [&'static str; N],
229229
objects: &[&Bound<'py, PyAny>; N],
230230
check_size: &[bool; N],
@@ -233,9 +233,9 @@ pub(crate) fn downcast_and_validate<'py, const N: usize>(
233233
assert_eq!(names.len(), objects.len());
234234

235235
let arrays = if cast {
236-
downcast_objects_cast(names, objects)?
236+
cast_objects_with_dtype_change(names, objects)?
237237
} else {
238-
downcast_objects_no_cast(names, objects)?
238+
cast_objects_no_dtype_change(names, objects)?
239239
};
240240
let mut first_array_len = None;
241241
// We checked that 1) names size matches objects size, 2) objects is not empty
@@ -299,7 +299,7 @@ macro_rules! dtype_dispatch {
299299
let objects = &[&$first_arg, $(&$arg, )*];
300300
let check_size = &[ false, $(_distinguish_eq_symbol!($eq), )* ];
301301

302-
let generic_arrays = crate::np_array::downcast_and_validate(names, objects, check_size, $cast)?;
302+
let generic_arrays = crate::np_array::cast_and_validate(names, objects, check_size, $cast)?;
303303
match generic_arrays {
304304
crate::np_array::GenericPyReadonlyArrays::F32(arrays) => {
305305
let func = $f32;

light-curve/src/transform.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ pub(crate) fn parse_transform(
110110
match option {
111111
None => Ok(None),
112112
Some(py_any) => {
113-
if let Ok(py_bool) = py_any.downcast::<PyBool>() {
113+
if let Ok(py_bool) = py_any.cast::<PyBool>() {
114114
if py_bool.is_true() {
115115
Ok(Some(default))
116116
} else {
117117
Ok(None)
118118
}
119-
} else if let Ok(py_str) = py_any.downcast::<PyString>() {
119+
} else if let Ok(py_str) = py_any.cast::<PyString>() {
120120
// py_str.to_str() is Python 3.10+ only
121121
let cow_string = py_str.to_cow()?;
122122
let s = cow_string.as_ref();

0 commit comments

Comments
 (0)