Skip to content

Commit 279f110

Browse files
authored
Merge pull request #284 from igerber/python-3-14
2 parents a26e8d5 + 30faedf commit 279f110

9 files changed

Lines changed: 27 additions & 25 deletions

File tree

.github/workflows/publish.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
- name: Build wheels
3737
run: |
3838
expected=0
39-
for pyver in 39 310 311 312 313; do
39+
for pyver in 39 310 311 312 313 314; do
4040
pybin="/opt/python/cp${pyver}-cp${pyver}/bin/python"
4141
if [ ! -f "$pybin" ]; then
4242
echo "ERROR: Expected Python interpreter not found: $pybin"
@@ -65,7 +65,7 @@ jobs:
6565
runs-on: macos-14
6666
strategy:
6767
matrix:
68-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
68+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
6969
steps:
7070
- uses: actions/checkout@v4
7171

@@ -95,7 +95,7 @@ jobs:
9595
runs-on: windows-latest
9696
strategy:
9797
matrix:
98-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
98+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
9999
steps:
100100
- uses: actions/checkout@v4
101101

.github/workflows/rust-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
fail-fast: false
8282
matrix:
8383
os: [ubuntu-latest, macos-latest, windows-latest, ubuntu-24.04-arm]
84-
python-version: ['3.11', '3.13']
84+
python-version: ['3.11', '3.13', '3.14']
8585

8686
steps:
8787
- uses: actions/checkout@v4
@@ -184,7 +184,7 @@ jobs:
184184
- name: Set up Python
185185
uses: actions/setup-python@v5
186186
with:
187-
python-version: '3.13'
187+
python-version: '3.14'
188188

189189
- name: Install dependencies
190190
# Keep in sync with pyproject.toml [project.dependencies] and [project.optional-dependencies.dev]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2769,7 +2769,7 @@ Returns DataFrame with columns: `unit`, `quality_score`, `outcome_trend_score`,
27692769

27702770
## Requirements
27712771

2772-
- Python 3.9 - 3.13
2772+
- Python 3.9 - 3.14
27732773
- numpy >= 1.20
27742774
- pandas >= 1.3
27752775
- scipy >= 1.7

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ version = "3.0.0"
88
description = "Difference-in-Differences causal inference with sklearn-like API. Callaway-Sant'Anna, Synthetic DiD, Honest DiD, event studies, parallel trends."
99
readme = "README.md"
1010
license = "MIT"
11-
requires-python = ">=3.9,<3.14"
11+
requires-python = ">=3.9,<3.15"
1212
authors = [
1313
{name = "diff-diff contributors"}
1414
]
@@ -39,6 +39,7 @@ classifiers = [
3939
"Programming Language :: Python :: 3.11",
4040
"Programming Language :: Python :: 3.12",
4141
"Programming Language :: Python :: 3.13",
42+
"Programming Language :: Python :: 3.14",
4243
"Topic :: Scientific/Engineering :: Mathematics",
4344
"Topic :: Scientific/Engineering :: Information Analysis",
4445
"Topic :: Scientific/Engineering",

rust/Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name = "diff_diff_rust"
33
version = "3.0.0"
44
edition = "2021"
5+
rust-version = "1.84"
56
description = "Rust backend for diff-diff DiD library"
67
license = "MIT"
78

@@ -20,10 +21,10 @@ accelerate = ["ndarray/blas", "dep:blas-src", "blas-src/accelerate"]
2021
openblas = ["ndarray/blas"]
2122

2223
[dependencies]
23-
# PyO3 0.22 supports Python 3.8-3.13
24-
pyo3 = "0.22"
25-
numpy = "0.22"
26-
ndarray = { version = "0.16", features = ["rayon"] }
24+
# PyO3 0.28 supports Python 3.9-3.14
25+
pyo3 = "0.28"
26+
numpy = "0.28"
27+
ndarray = { version = "0.17", features = ["rayon"] }
2728
rand = "0.8"
2829
rand_xoshiro = "0.6"
2930
rayon = "1.8"

rust/src/bootstrap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub fn generate_bootstrap_weights_batch<'py>(
4848
}
4949
};
5050

51-
Ok(weights.to_pyarray_bound(py))
51+
Ok(weights.to_pyarray(py))
5252
}
5353

5454
/// Generate Rademacher weights: ±1 with equal probability.

rust/src/linalg.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,20 +144,20 @@ pub fn solve_ols<'py>(
144144
// Rank-deficient: cannot compute valid vcov, return NaN matrix
145145
let mut nan_vcov = Array2::<f64>::zeros((k, k));
146146
nan_vcov.fill(f64::NAN);
147-
Some(nan_vcov.to_pyarray_bound(py))
147+
Some(nan_vcov.to_pyarray(py))
148148
} else {
149149
// Full rank: compute robust vcov normally
150150
let cluster_arr = cluster_ids.as_ref().map(|c| c.as_array().to_owned());
151151
let vcov_arr = compute_robust_vcov_internal(&x_arr, &residuals.view(), cluster_arr.as_ref(), n, k)?;
152-
Some(vcov_arr.to_pyarray_bound(py))
152+
Some(vcov_arr.to_pyarray(py))
153153
}
154154
} else {
155155
None
156156
};
157157

158158
Ok((
159-
coefficients.to_pyarray_bound(py),
160-
residuals.to_pyarray_bound(py),
159+
coefficients.to_pyarray(py),
160+
residuals.to_pyarray(py),
161161
vcov,
162162
))
163163
}
@@ -186,7 +186,7 @@ pub fn compute_robust_vcov<'py>(
186186
let n = x_arr.nrows();
187187
let k = x_arr.ncols();
188188
let vcov = compute_robust_vcov_internal(&x_arr, &residuals_arr, cluster_arr.as_ref(), n, k)?;
189-
Ok(vcov.to_pyarray_bound(py))
189+
Ok(vcov.to_pyarray(py))
190190
}
191191

192192
/// Internal implementation of robust variance-covariance computation.

rust/src/trop.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub fn compute_unit_distance_matrix<'py>(
4444

4545
let dist_matrix = compute_unit_distance_matrix_internal(&y_arr, &d_arr);
4646

47-
Ok(dist_matrix.to_pyarray_bound(py))
47+
Ok(dist_matrix.to_pyarray(py))
4848
}
4949

5050
/// Internal implementation of unit distance matrix computation.
@@ -1098,7 +1098,7 @@ pub fn bootstrap_trop_variance<'py>(
10981098
};
10991099

11001100
let estimates_arr = Array1::from_vec(bootstrap_estimates);
1101-
Ok((estimates_arr.to_pyarray_bound(py), se))
1101+
Ok((estimates_arr.to_pyarray(py), se))
11021102
}
11031103

11041104
// ============================================================================
@@ -1838,7 +1838,7 @@ pub fn bootstrap_trop_variance_global<'py>(
18381838
};
18391839

18401840
let estimates_arr = Array1::from_vec(bootstrap_estimates);
1841-
Ok((estimates_arr.to_pyarray_bound(py), se))
1841+
Ok((estimates_arr.to_pyarray(py), se))
18421842
}
18431843

18441844
#[cfg(test)]

rust/src/weights.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn compute_synthetic_weights<'py>(
5454
let weights =
5555
compute_synthetic_weights_internal(&y_control_arr, &y_treated_arr, lambda_reg, max_iter, tol)?;
5656

57-
Ok(weights.to_pyarray_bound(py))
57+
Ok(weights.to_pyarray(py))
5858
}
5959

6060
/// Internal implementation of synthetic weight computation.
@@ -137,7 +137,7 @@ pub fn project_simplex<'py>(
137137
) -> PyResult<Bound<'py, PyArray1<f64>>> {
138138
let v_arr = v.as_array();
139139
let result = project_simplex_internal(&v_arr);
140-
Ok(result.to_pyarray_bound(py))
140+
Ok(result.to_pyarray(py))
141141
}
142142

143143
/// Internal implementation of simplex projection.
@@ -607,7 +607,7 @@ pub fn sc_weight_fw<'py>(
607607
min_decrease,
608608
max_iter,
609609
);
610-
Ok(result.to_pyarray_bound(py))
610+
Ok(result.to_pyarray(py))
611611
}
612612

613613
/// Compute SDID time weights via Frank-Wolfe optimization.
@@ -637,7 +637,7 @@ pub fn compute_time_weights<'py>(
637637
let y_post = y_post_control.as_array();
638638

639639
let result = compute_time_weights_internal(&y_pre, &y_post, zeta_lambda, intercept, min_decrease, max_iter_pre_sparsify, max_iter);
640-
Ok(result.to_pyarray_bound(py))
640+
Ok(result.to_pyarray(py))
641641
}
642642

643643
pub(crate) fn compute_time_weights_internal(
@@ -720,7 +720,7 @@ pub fn compute_sdid_unit_weights<'py>(
720720
&y_pre, &y_tr_mean, zeta_omega, intercept, min_decrease,
721721
max_iter_pre_sparsify, max_iter,
722722
);
723-
Ok(result.to_pyarray_bound(py))
723+
Ok(result.to_pyarray(py))
724724
}
725725

726726
pub(crate) fn compute_sdid_unit_weights_internal(

0 commit comments

Comments
 (0)