Skip to content

Commit 5028aaf

Browse files
authored
numpy 2.0 support (#785)
* Switch to numpy 2.0, correct Segmentation fault * updated build action * upgrade upload-artifact * update matlab testing * full Matlab tests on linux
1 parent ad67355 commit 5028aaf

File tree

9 files changed

+65
-52
lines changed

9 files changed

+65
-52
lines changed

.github/workflows/build-python-wheels.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ${{ matrix.os }}
1414
strategy:
1515
matrix:
16-
os: [ubuntu-22.04, macos-12, windows-2022]
16+
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
1717

1818
steps:
1919
- uses: actions/checkout@v4
@@ -22,18 +22,13 @@ jobs:
2222
# see: https://github.com/pypa/setuptools_scm/issues/480
2323
fetch-depth: 0
2424

25-
- name: Install Python
26-
uses: actions/setup-python@v5
27-
with:
28-
python-version: '3.9'
29-
3025
- name: Build wheels
31-
uses: pypa/cibuildwheel@v2.16.2
26+
uses: pypa/cibuildwheel@v2.19.1
3227

3328
- name: Upload wheels
34-
uses: actions/upload-artifact@v3
29+
uses: actions/upload-artifact@v4
3530
with:
36-
name: wheels
31+
name: wheels-${{ matrix.os }}
3732
path: ./wheelhouse/*.whl
3833
if-no-files-found: error
3934

@@ -59,7 +54,7 @@ jobs:
5954
run: python -m build --sdist
6055

6156
- name: Upload sdist
62-
uses: actions/upload-artifact@v3
57+
uses: actions/upload-artifact@v4
6358
with:
6459
name: tar.gz
6560
path: ./dist/*.tar.gz

.github/workflows/matlab-tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ jobs:
2626

2727
- uses: actions/checkout@v4
2828

29-
- name: Set up python 3.9
29+
- name: Set up python
3030
uses: actions/setup-python@v5
3131
with:
32-
python-version: '3.9'
32+
python-version: '3.10'
3333
cache: pip
3434

3535
- name: Set up MATLAB
36-
uses: matlab-actions/setup-matlab@v1
36+
uses: matlab-actions/setup-matlab@v2
3737
with:
38-
release: R2022a
38+
release: R2023a
3939

4040
- name: Atmexall
41-
uses: matlab-actions/run-command@v1
41+
uses: matlab-actions/run-command@v2
4242
with:
4343
command: run('atmat/atpath');githubsetup();
4444

atmat/attests/githubrun.m

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
% normally no reason to run it in a user workflow.
33

44
tsuite=fullfile(atroot,'attests');
5-
if ispc || ismac
6-
v=assertSuccess(run(testsuite(tsuite)));
7-
else
8-
v=assertSuccess(run(testsuite(tsuite,'Tag','GitHub')));
5+
if ~(ispc || ismac)
6+
% Solution for
7+
% "Intel MKL ERROR: Parameter 11 was incorrect on entry to DSBEVD."
8+
% found there:
9+
% https://fr.mathworks.com/matlabcentral/answers/1983899-intel-mkl-error-when-callying-scipy-from-matlab
10+
py.sys.setdlopenflags(int32(bitor(int64(py.os.RTLD_LAZY), int64(py.os.RTLD_DEEPBIND))));
911
end
12+
v=assertSuccess(run(testsuite(tsuite)));
1013
disp(table(v));

atmat/attests/githubsetup.m

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,9 @@ function githubsetup()
99
atmexall -fail
1010
if ispc
1111
execfile=fullfile(getenv('pythonLocation'),'pythonw.exe');
12-
execmode='InProcess';
13-
elseif ismac
14-
execfile=fullfile(getenv('pythonLocation'),'bin','python');
15-
execmode='InProcess';
1612
else
1713
execfile=fullfile(getenv('pythonLocation'),'bin','python');
18-
execmode='OutOfProcess';
1914
end
20-
pyenv("Version", execfile,'ExecutionMode', execmode);
15+
pyenv("Version", execfile,'ExecutionMode', 'InProcess');
2116
disp(pyenv);
2217
end

pyat/at.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
#include <float.h>
1919
#include <atrandom.c>
2020

21+
#define atPrintf(...) PySys_WriteStdout(__VA_ARGS__)
22+
2123
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
2224
#include <numpy/ndarrayobject.h>
23-
24-
#define NUMPY_IMPORT_ARRAY_RETVAL NULL
25-
#define NUMPY_IMPORT_ARRAY_TYPE void *
25+
#if NPY_ABI_VERSION < 0x02000000
26+
#define NPY_RAVEL_AXIS 32
27+
#endif
2628

2729
typedef PyObject atElem;
2830

@@ -306,11 +308,11 @@ void set_energy_particle(PyObject *lattice, PyObject *energy,
306308
void set_current_fillpattern(PyArrayObject *bspos, PyArrayObject *bcurrents,
307309
struct parameters *param){
308310
if(bcurrents != NULL){
309-
PyObject *bcurrentsum = PyArray_Sum(bcurrents, NPY_MAXDIMS,
311+
PyObject *bcurrentsum = PyArray_Sum(bcurrents, NPY_RAVEL_AXIS,
310312
PyArray_DESCR(bcurrents)->type_num,
311-
NULL);
313+
NULL);
312314
param->beam_current = PyFloat_AsDouble(bcurrentsum);
313-
Py_DECREF(bcurrentsum);
315+
Py_DECREF(bcurrentsum);
314316
param->nbunch = PyArray_SIZE(bspos);
315317
param->bunch_spos = PyArray_DATA(bspos);
316318
param->bunch_currents = PyArray_DATA(bcurrents);
@@ -319,7 +321,7 @@ void set_current_fillpattern(PyArrayObject *bspos, PyArrayObject *bcurrents,
319321
param->nbunch=1;
320322
param->bunch_spos = (double[1]){0.0};
321323
param->bunch_currents = (double[1]){0.0};
322-
}
324+
}
323325
}
324326

325327
/*
@@ -415,7 +417,7 @@ static PyObject *at_atpass(PyObject *self, PyObject *args, PyObject *kwargs) {
415417
else
416418
param.nturn = counter;
417419

418-
set_energy_particle(lattice, energy, particle, &param);
420+
set_energy_particle(lattice, energy, particle, &param);
419421
set_current_fillpattern(bspos, bcurrents, &param);
420422

421423
num_particles = (PyArray_SIZE(rin)/6);

pyat/at/load/matfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import scipy.io
1818

1919
# imports necessary in 'globals()' for 'eval'
20-
from numpy import array, uint8, NaN # noqa: F401
20+
from numpy import array, uint8, nan as NaN # noqa: F401
2121

2222
from .allfiles import register_format
2323
from .utils import split_ignoring_parentheses, RingParam, keep_elements

pyat/at/load/reprfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import numpy as np
1414

1515
# imports necessary in 'globals()' for 'eval'
16-
from numpy import array, uint8, NaN # noqa: F401
16+
from numpy import array, uint8, nan as NaN # noqa: F401
1717

1818
from at.lattice import Lattice, Element
1919

pyat/at/load/utils.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
"keep_attributes",
1414
"split_ignoring_parentheses",
1515
"RingParam",
16+
"protect",
17+
"restore",
1618
]
1719

1820
import collections
@@ -32,6 +34,7 @@
3234
from at.lattice import idtable_element
3335

3436
_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
37+
_placeholder = "placeholder"
3538

3639

3740
def _no_encoder(v):
@@ -379,25 +382,41 @@ def element_to_dict(elem: Element, encoder: Callable[[Any], Any] = _no_encoder)
379382
return dct
380383

381384

382-
def split_ignoring_parentheses(string: str, delimiter: str = ",") -> list[str]:
383-
"""Split a string while keeping parenthesized expressions intact
385+
def split_ignoring_parentheses(
386+
string: str,
387+
delimiter: str = ",",
388+
fence: tuple[str, str] = ('\\(', '\\)'),
389+
maxsplit: int = -1,
390+
) -> list[str]:
391+
"""Split a string while keeping protected expressions intact
384392
385393
Example: "l=0,hom(4,0.0,0)" -> ["l=0", "hom(4,0.0,0)"]
386394
"""
387-
placeholder = "placeholder"
395+
substituted, matches = protect(string, fence=fence)
396+
parts = substituted.split(delimiter, maxsplit=maxsplit)
397+
return restore(matches, *parts)
398+
399+
400+
def protect(string: str, fence: tuple[str, str] = ('"', '"')):
401+
inf, outf = fence
402+
pattern = f"{inf}.*?{outf}"
388403
substituted = string[:]
389-
matches = collections.deque(re.finditer("\\(.*?\\)", string))
404+
matches = collections.deque(re.finditer(pattern, string))
390405
for match in matches:
391-
substituted = substituted.replace(match.group(), placeholder, 1)
392-
parts = substituted.split(delimiter)
393-
replaced_parts = []
394-
for part in parts:
395-
if placeholder in part:
406+
substituted = substituted.replace(match.group(), _placeholder, 1)
407+
return substituted, matches
408+
409+
410+
def restore(matches, *parts):
411+
412+
def rep(part):
413+
while _placeholder in part:
396414
next_match = matches.popleft()
397-
part = part.replace(placeholder, next_match.group(), 1)
398-
replaced_parts.append(part)
399-
assert not matches
415+
part = part.replace(_placeholder, next_match.group(), 1)
416+
return part
400417

418+
replaced_parts = [rep(part) for part in parts]
419+
assert not matches
401420
return replaced_parts
402421

403422

pyproject.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
requires = [
33
"setuptools >= 64",
44
"setuptools_scm >= 7",
5-
"oldest-supported-numpy",
5+
"oldest-supported-numpy; python_version <= '3.8'",
6+
"numpy >= 2.0; python_version >= '3.9'",
67
"wheel",
78
]
89
# build-backend = "setuptools.build_meta"
@@ -36,7 +37,8 @@ classifiers = [
3637
requires-python = ">=3.7"
3738
dependencies = [
3839
"importlib-resources;python_version<'3.9'",
39-
"numpy >=1.16.6, <2.0",
40+
"numpy >=1.16.6, <2.0; python_version <= '3.8'",
41+
"numpy >= 1.23.5; python_version >= '3.9'",
4042
"scipy>=1.4.0"
4143
]
4244

@@ -73,9 +75,6 @@ build-verbosity = "1"
7375
# "build" frontend fails on windows
7476
# build-frontend = "build"
7577

76-
[tool.cibuildwheel.macos]
77-
archs = ["x86_64", "arm64"]
78-
7978
#[tool.cibuildwheel.linux]
8079
## Pass the detected PyAT version to the linux docker containers
8180
#environment-pass = ["SETUPTOOLS_SCM_PRETEND_VERSION"]

0 commit comments

Comments
 (0)