Skip to content

Commit cceefac

Browse files
authored
Merge pull request #599 from Point72/tkp/313
Support Python 3.13
2 parents d35c2c3 + e40659e commit cceefac

8 files changed

Lines changed: 75 additions & 21 deletions

File tree

.github/actions/setup-dependencies/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ inputs:
1111
- 'cp310'
1212
- 'cp311'
1313
- 'cp312'
14+
- 'cp313'
1415
default: 'cp39'
1516

1617
runs:

.github/actions/setup-python/action.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ inputs:
1010
- '3.10'
1111
- '3.11'
1212
- '3.12'
13+
- '3.13'
1314
default: '3.9'
1415

1516
runs:
@@ -33,4 +34,4 @@ runs:
3334

3435
- name: Install cibuildwheel and twine
3536
shell: bash
36-
run: pip install cibuildwheel==2.16.5 twine
37+
run: pip install cibuildwheel==2.23.0 twine

.github/workflows/build.yml

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ jobs:
119119
env:
120120
FULL_RUN: ${{ github.event.inputs.ci-full }}
121121
if: ${{ github.event_name == 'workflow_dispatch' }}
122-
122+
123123
- name: Display and Setup Build Args (Schedule)
124124
id: setupschedule
125125
run: |
@@ -202,11 +202,13 @@ jobs:
202202
- "3.10"
203203
- "3.11"
204204
- "3.12"
205+
- "3.13"
205206
cibuildwheel:
206207
- "cp39"
207208
- "cp310"
208209
- "cp311"
209210
- "cp312"
211+
- "cp313"
210212
is-full-run:
211213
- ${{ needs.initialize.outputs.FULL_RUN == 'true' }}
212214
exclude:
@@ -221,24 +223,40 @@ jobs:
221223
cibuildwheel: "cp311"
222224
- python-version: "3.9"
223225
cibuildwheel: "cp312"
226+
- python-version: "3.9"
227+
cibuildwheel: "cp313"
224228
- python-version: "3.10"
225229
cibuildwheel: "cp39"
226230
- python-version: "3.10"
227231
cibuildwheel: "cp311"
228232
- python-version: "3.10"
229233
cibuildwheel: "cp312"
234+
- python-version: "3.10"
235+
cibuildwheel: "cp313"
230236
- python-version: "3.11"
231237
cibuildwheel: "cp39"
232238
- python-version: "3.11"
233239
cibuildwheel: "cp310"
234240
- python-version: "3.11"
235241
cibuildwheel: "cp312"
242+
- python-version: "3.11"
243+
cibuildwheel: "cp313"
236244
- python-version: "3.12"
237245
cibuildwheel: "cp39"
238246
- python-version: "3.12"
239247
cibuildwheel: "cp310"
240248
- python-version: "3.12"
241249
cibuildwheel: "cp311"
250+
- python-version: "3.12"
251+
cibuildwheel: "cp313"
252+
- python-version: "3.13"
253+
cibuildwheel: "cp39"
254+
- python-version: "3.13"
255+
cibuildwheel: "cp310"
256+
- python-version: "3.13"
257+
cibuildwheel: "cp311"
258+
- python-version: "3.13"
259+
cibuildwheel: "cp312"
242260

243261

244262
##############################################
@@ -261,6 +279,10 @@ jobs:
261279
os: windows-2022
262280
python-version: "3.11"
263281

282+
- is-full-run: false
283+
os: windows-2022
284+
python-version: "3.13"
285+
264286
# avoid unnecessary use of mac resources
265287
- is-full-run: false
266288
os: macos-14
@@ -270,6 +292,14 @@ jobs:
270292
os: macos-14
271293
python-version: "3.10"
272294

295+
- is-full-run: false
296+
os: macos-14
297+
python-version: "3.11"
298+
299+
- is-full-run: false
300+
os: macos-14
301+
python-version: "3.13"
302+
273303
runs-on: ${{ matrix.os }}
274304

275305
steps:
@@ -300,7 +330,6 @@ jobs:
300330
env:
301331
CIBW_BUILD: "${{ matrix.cibuildwheel }}-manylinux*"
302332
CIBW_ENVIRONMENT_LINUX: ACLOCAL_PATH="/usr/share/aclocal" CSP_MANYLINUX="ON" CCACHE_DIR="/host/home/runner/work/csp/csp/.ccache" VCPKG_DEFAULT_BINARY_CACHE="/host${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" VCPKG_DOWNLOADS="/host${{ env.VCPKG_DOWNLOADS }}"
303-
CIBW_BUILD_VERBOSITY: 3
304333
if: ${{ runner.os == 'Linux' }}
305334

306335
########
@@ -311,7 +340,6 @@ jobs:
311340
CIBW_BUILD: "${{ matrix.cibuildwheel }}-macos*"
312341
CIBW_ENVIRONMENT_MACOS: CCACHE_DIR="/Users/runner/work/csp/csp/.ccache" VCPKG_DEFAULT_BINARY_CACHE="${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" VCPKG_DOWNLOADS="${{ env.VCPKG_DOWNLOADS }}"
313342
CIBW_ARCHS_MACOS: arm64
314-
CIBW_BUILD_VERBOSITY: 3
315343
if: ${{ matrix.os == 'macos-14' }}
316344

317345
##########
@@ -426,6 +454,7 @@ jobs:
426454
- "3.10"
427455
- 3.11
428456
- 3.12
457+
- 3.13
429458
is-full-run:
430459
- ${{ needs.initialize.outputs.FULL_RUN == 'true' }}
431460
exclude:
@@ -449,6 +478,10 @@ jobs:
449478
os: windows-2022
450479
python-version: "3.11"
451480

481+
- is-full-run: false
482+
os: windows-2022
483+
python-version: "3.13"
484+
452485
# avoid unnecessary use of mac resources
453486
- is-full-run: false
454487
os: macos-14
@@ -458,6 +491,14 @@ jobs:
458491
os: macos-14
459492
python-version: "3.10"
460493

494+
- is-full-run: false
495+
os: macos-14
496+
python-version: "3.11"
497+
498+
- is-full-run: false
499+
os: macos-14
500+
python-version: "3.13"
501+
461502
runs-on: ${{ matrix.os }}
462503

463504
steps:
@@ -581,9 +622,9 @@ jobs:
581622

582623
- name: Install python dependencies
583624
run: make requirements
584-
625+
585626
- name: Install requirements
586-
run: sudo make dependencies-debian
627+
run: sudo make dependencies-debian
587628

588629
- uses: actions/download-artifact@v5
589630
with:

conda/dev-environment-unix.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ dependencies:
4040
- pytest-asyncio
4141
- pytest-cov
4242
- pytest-sugar
43-
- python<3.13
43+
- python<3.14
4444
- python-build
4545
- python-graphviz
4646
- python-rapidjson

conda/dev-environment-win.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ dependencies:
4040
- pytest-asyncio
4141
- pytest-cov
4242
- pytest-sugar
43-
- python<3.13
43+
- python<3.14
4444
- python-build
4545
- python-graphviz
4646
- python-rapidjson

cpp/csp/python/Common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <Python.h>
55

66
#define IS_PRE_PYTHON_3_11 (PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 11) )
7+
#define IS_PRE_PYTHON_3_12 (PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 12) )
8+
#define IS_PRE_PYTHON_3_13 (PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 13) )
79

810
#define INIT_PYDATETIME if( !PyDateTimeAPI ) { PyDateTime_IMPORT; }
911

cpp/csp/python/PyNode.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616
#include <frameobject.h>
1717

1818
#if !IS_PRE_PYTHON_3_11
19+
#if !IS_PRE_PYTHON_3_13
20+
# define Py_BUILD_CORE 1
21+
#endif
1922
#include <internal/pycore_code.h>
2023
#include <internal/pycore_frame.h>
24+
#if !IS_PRE_PYTHON_3_13
25+
# undef Py_BUILD_CORE
26+
#endif
2127
#endif
2228

2329
namespace csp::python
@@ -48,7 +54,7 @@ PyNode::~PyNode()
4854
void PyNode::init( PyObjectPtr inputs, PyObjectPtr outputs )
4955
{
5056
PyGenObject * pygen = ( PyGenObject * ) m_gen.ptr();
51-
57+
5258
//call gen first yield to setup locals
5359
call_gen();
5460

@@ -85,7 +91,11 @@ void PyNode::init( PyObjectPtr inputs, PyObjectPtr outputs )
8591
//PY311+ changes
8692
#else
8793
_PyInterpreterFrame * frame = ( _PyInterpreterFrame * ) pygen -> gi_iframe;
94+
#if IS_PRE_PYTHON_3_12
8895
PyCodeObject * code = frame -> f_code;
96+
#else
97+
PyPtr<PyCodeObject> code = PyPtr<PyCodeObject>::own( PyGen_GetCode( ( PyGenObject * ) pygen ) );
98+
#endif
8999
int localPlusIndex = 0;
90100
for( int stackloc = code -> co_argcount; stackloc < code -> co_nlocalsplus; ++stackloc, ++localPlusIndex )
91101
{
@@ -102,7 +112,7 @@ void PyNode::init( PyObjectPtr inputs, PyObjectPtr outputs )
102112
var = &( ( ( PyCellObject * ) *var ) -> ob_ref );
103113
else if( kind == CO_FAST_CELL )
104114
continue;
105-
#endif
115+
#endif
106116
//null var indicates a stack slot for a local state variable ( state hasnt initialized yet )
107117
//we can skip those
108118
if( !*var )
@@ -119,7 +129,7 @@ void PyNode::init( PyObjectPtr inputs, PyObjectPtr outputs )
119129
CSP_ASSERT( !isInputBasket( index ) );
120130

121131
m_localVars[ index ] = var;
122-
//These vars will be "deleted" from the python stack after start
132+
//These vars will be "deleted" from the python stack after start
123133
continue;
124134
}
125135

@@ -215,7 +225,7 @@ void PyNode::stop()
215225
if( this -> rootEngine() -> interrupted() && PyErr_CheckSignals() == -1 )
216226
{
217227
// When an interrupt occurs a KeyboardInterrupt exception is raised in Python, which we need to clear
218-
// before calling "close" on the generator. Else, the close method will fail due to the unhandled
228+
// before calling "close" on the generator. Else, the close method will fail due to the unhandled
219229
// exception, and we lose the state of the generator before the "finally" block that calls stop() is executed.
220230
PyErr_Clear();
221231
}
@@ -230,15 +240,15 @@ PyNode * PyNode::create( PyEngine * pyengine, PyObject * inputs, PyObject * outp
230240
//parse inputs/outputs, create outputs time series, etc
231241
Py_ssize_t numInputs = PyTuple_GET_SIZE( inputs );
232242
Py_ssize_t numOutputs = PyTuple_GET_SIZE( outputs );
233-
243+
234244
if( size_t( numInputs ) >= InputId::maxId() )
235245
CSP_THROW( ValueError, "number of inputs exceeds limit of " << InputId::maxBasketElements() );
236246

237247
if( size_t( numOutputs ) > OutputId::maxId() )
238248
CSP_THROW( ValueError, "number of outputs exceeds limit of " << OutputId::maxBasketElements() );
239249

240-
return pyengine -> engine() -> createOwnedObject<PyNode>( PyObjectPtr::incref( gen ),
241-
PyObjectPtr::incref( inputs ),
250+
return pyengine -> engine() -> createOwnedObject<PyNode>( PyObjectPtr::incref( gen ),
251+
PyObjectPtr::incref( inputs ),
242252
PyObjectPtr::incref( outputs ),
243253
NodeDef( numInputs, numOutputs ) );
244254
}
@@ -317,10 +327,10 @@ static PyObject * PyNode_create( PyObject * module, PyObject * args )
317327
PyObject * outputs;
318328
PyObject * gen;
319329

320-
if( !PyArg_ParseTuple( args, "O!O!O!O!",
321-
&PyEngine::PyType, &engine,
322-
&PyTuple_Type, &inputs,
323-
&PyTuple_Type, &outputs,
330+
if( !PyArg_ParseTuple( args, "O!O!O!O!",
331+
&PyEngine::PyType, &engine,
332+
&PyTuple_Type, &inputs,
333+
&PyTuple_Type, &outputs,
324334
&PyGen_Type, &gen ) )
325335
CSP_THROW( PythonPassthrough, "" );
326336

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ replace = 'project(csp VERSION "{new_version}")'
146146
ignore = []
147147

148148
[tool.cibuildwheel]
149-
build = "cp39-* cp310-* cp311-* cp312-*"
149+
build = "cp39-* cp310-* cp311-* cp312-* cp313-*"
150150
test-command = "echo 'TODO'"
151151
test-requires = [
152152
"pytest",
@@ -177,7 +177,6 @@ archs = "arm64"
177177
[tool.cibuildwheel.windows]
178178
before-all = "make dependencies-win"
179179
before-build = "make requirements"
180-
181180
archs = "AMD64"
182181
skip = "*win32 *arm_64"
183182

0 commit comments

Comments
 (0)