From bb74a5f9b764b1e0800b81410555b571b2c49925 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Wed, 4 Dec 2024 10:11:59 +0100 Subject: [PATCH 01/37] Add support for Python 3.13 --- .circleci/config.yml | 5 +++-- .github/workflows/coverage.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/neuron-ci.yml | 2 +- azure-pipelines.yml | 7 +++++++ ci/win_download_deps.cmd | 1 + ci/win_install_deps.cmd | 3 +++ ci/win_test_installer.cmd | 3 +++ packaging/python/oldest_numpy_requirements.txt | 1 + 9 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 27c16c14c3..60ca9590fc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,6 +53,7 @@ jobs: 310) pyenv_py_ver="3.10" ;; 311) pyenv_py_ver="3.11" ;; 312) pyenv_py_ver="3.12" ;; + 313) pyenv_py_ver="3.13" ;; *) echo "Error: pyenv python version not specified or not supported." && exit 1;; esac @@ -86,7 +87,7 @@ workflows: - /circleci\/.*/ matrix: parameters: - NRN_PYTHON_VERSION: ["312"] + NRN_PYTHON_VERSION: ["313"] NRN_NIGHTLY_UPLOAD: ["false"] nightly: @@ -101,5 +102,5 @@ workflows: - manylinux2014-aarch64: matrix: parameters: - NRN_PYTHON_VERSION: ["39", "310", "311", "312"] + NRN_PYTHON_VERSION: ["39", "310", "311", "312", "313"] NRN_NIGHTLY_UPLOAD: ["true"] diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a4e23da01c..f204e36421 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -24,7 +24,7 @@ on: env: PY_MIN_VERSION: '3.9' PY_MID_VERSION: '3.10' - PY_MAX_VERSION: '3.12' + PY_MAX_VERSION: '3.13' jobs: coverage: diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2ef1052dd7..f9cc6e0051 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ on: - release/** env: - DEFAULT_PY_VERSION: '3.12' + DEFAULT_PY_VERSION: '3.13' jobs: documentation: diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index 48ec76d28e..adcf08c3b7 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -39,7 +39,7 @@ jobs: DESIRED_CMAKE_VERSION: 3.17 DYNAMIC_PYTHON_CMAKE_VERSION: 3.18 PY_MIN_VERSION: ${{ matrix.config.python_min_version || '3.9' }} - PY_MAX_VERSION: ${{ matrix.config.python_max_version || '3.12' }} + PY_MAX_VERSION: ${{ matrix.config.python_max_version || '3.13' }} MUSIC_INSTALL_DIR: /opt/MUSIC # hash of commit containing mpi4py 4 fix MUSIC_VERSION: '13f312338dcccebfe74d391b1b24f1b6d816ac6c' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 02f5f8374a..00dc718236 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -42,6 +42,9 @@ stages: python.version: '3.11' Python312: python.version: '3.12' + Python313: + python.version: '3.13' + steps: # Secure files documentation: @@ -102,6 +105,10 @@ stages: python.version: '3.12' python.org.version: '3.12.0' python.installer.name: 'macos11.pkg' + Python313: + python.version: '3.13' + python.org.version: '3.13.0' + python.installer.name: 'macos11.pkg' steps: diff --git a/ci/win_download_deps.cmd b/ci/win_download_deps.cmd index 40a9b44f49..166d44461a 100644 --- a/ci/win_download_deps.cmd +++ b/ci/win_download_deps.cmd @@ -7,6 +7,7 @@ pwsh -command Invoke-WebRequest -MaximumRetryCount 4 -OutFile python-3.9.exe htt pwsh -command Invoke-WebRequest -MaximumRetryCount 4 -OutFile python-3.10.exe https://www.python.org/ftp/python/3.10.0/python-3.10.0-amd64.exe || goto :error pwsh -command Invoke-WebRequest -MaximumRetryCount 4 -OutFile python-3.11.exe https://www.python.org/ftp/python/3.11.1/python-3.11.1-amd64.exe || goto :error pwsh -command Invoke-WebRequest -MaximumRetryCount 4 -OutFile python-3.12.exe https://www.python.org/ftp/python/3.12.1/python-3.12.1-amd64.exe || goto :error +pwsh -command Invoke-WebRequest -MaximumRetryCount 4 -OutFile python-3.13.exe https://www.python.org/ftp/python/3.13.0/python-3.13.0-amd64.exe || goto :error :: mpi pwsh -command Invoke-WebRequest -MaximumRetryCount 4 -OutFile msmpisetup.exe https://download.microsoft.com/download/a/5/2/a5207ca5-1203-491a-8fb8-906fd68ae623/msmpisetup.exe || goto :error diff --git a/ci/win_install_deps.cmd b/ci/win_install_deps.cmd index c12f32cdef..82a8c950d1 100644 --- a/ci/win_install_deps.cmd +++ b/ci/win_install_deps.cmd @@ -7,6 +7,7 @@ python-3.9.exe /passive Include_pip=1 Include_test=0 PrependPath=1 DefaultJustFo python-3.10.exe /passive Include_pip=1 Include_test=0 PrependPath=1 DefaultJustForMeTargetDir=C:\Python310 || goto :error python-3.11.exe /passive Include_pip=1 Include_test=0 PrependPath=1 DefaultJustForMeTargetDir=C:\Python311 || goto :error python-3.12.exe /passive Include_pip=1 Include_test=0 PrependPath=1 DefaultJustForMeTargetDir=C:\Python312 || goto :error +python-3.13.exe /passive Include_pip=1 Include_test=0 PrependPath=1 DefaultJustForMeTargetDir=C:\Python313 || goto :error :: fix msvcc version for all python3 pwsh -command "(Get-Content C:\Python39\Lib\distutils\cygwinccompiler.py) -replace 'elif msc_ver == ''1600'':', 'elif msc_ver == ''1927'':' | Out-File C:\Python39\Lib\distutils\cygwinccompiler.py" @@ -24,8 +25,10 @@ C:\Python39\python.exe -m pip install numpy cython || goto :error C:\Python310\python.exe -m pip install numpy cython || goto :error C:\Python311\python.exe -m pip install numpy cython || goto :error C:\Python312\python.exe -m pip install numpy cython || goto :error +C:\Python313\python.exe -m pip install numpy cython || goto :error :: setuptools 70.2 leads to an error C:\Python312\python.exe -m pip install setuptools==70.1.1 || goto :error +C:\Python313\python.exe -m pip install setuptools==70.1.1 || goto :error :: install nsis nsis-3.05-setup.exe /S || goto :error diff --git a/ci/win_test_installer.cmd b/ci/win_test_installer.cmd index bda5bbec7b..a6cf59a009 100644 --- a/ci/win_test_installer.cmd +++ b/ci/win_test_installer.cmd @@ -21,18 +21,21 @@ C:\Python39\python -c "import neuron; neuron.test(); quit()" || set "errorfound= C:\Python310\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python311\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python312\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" +C:\Python313\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" :: install oldest supported numpy C:\Python39\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error C:\Python310\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error C:\Python311\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error C:\Python312\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error +C:\Python313\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error :: test all pythons again C:\Python39\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python310\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python311\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python312\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" +C:\Python313\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" :: run also using whatever is system python python -m pip install numpy diff --git a/packaging/python/oldest_numpy_requirements.txt b/packaging/python/oldest_numpy_requirements.txt index 4a77e64c2b..eb2e1a80db 100644 --- a/packaging/python/oldest_numpy_requirements.txt +++ b/packaging/python/oldest_numpy_requirements.txt @@ -3,3 +3,4 @@ numpy==1.21.6;python_version=='3.9' and platform_machine=='arm64' numpy==1.21.6;python_version=='3.10' numpy==1.23.5;python_version=='3.11' numpy==1.26.4;python_version=='3.12' +numpy==2.1.0;python_version=='3.13' From 2a7c9cfab37aec364096692a5e5111070811705b Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Wed, 4 Dec 2024 12:03:25 +0100 Subject: [PATCH 02/37] Missed one instance --- ci/win_build_cmake.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/win_build_cmake.sh b/ci/win_build_cmake.sh index b82e430444..15cc217323 100755 --- a/ci/win_build_cmake.sh +++ b/ci/win_build_cmake.sh @@ -32,7 +32,7 @@ cd $BUILD_SOURCESDIRECTORY/build -DNRN_BINARY_DIST_BUILD=ON \ -DPYTHON_EXECUTABLE=/c/Python39/python.exe \ -DNRN_ENABLE_PYTHON_DYNAMIC=ON \ - -DNRN_PYTHON_DYNAMIC='c:/Python39/python.exe;c:/Python310/python.exe;c:/Python311/python.exe;c:/Python312/python.exe' \ + -DNRN_PYTHON_DYNAMIC='c:/Python39/python.exe;c:/Python310/python.exe;c:/Python311/python.exe;c:/Python312/python.exe;c:/Python313/python.exe' \ -DCMAKE_INSTALL_PREFIX='/c/nrn-install' \ -DMPI_CXX_LIB_NAMES:STRING=msmpi \ -DMPI_C_LIB_NAMES:STRING=msmpi \ From 831b2bc74af2decf9c7406b125c1b80c2f694f93 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Wed, 4 Dec 2024 13:58:17 +0100 Subject: [PATCH 03/37] Consistent `neuron_wheel` tags --- .circleci/config.yml | 2 +- azure-pipelines.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 60ca9590fc..edf5d0a01e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: -e NRN_RELEASE_UPLOAD \ -e SETUPTOOLS_SCM_PRETEND_VERSION \ -e NRN_BUILD_FOR_UPLOAD=1 \ - 'neuronsimulator/neuron_wheel:latest-gcc9-aarch64' \ + 'neuronsimulator/neuron_wheel:test-aarch64' \ packaging/python/build_wheels.bash linux << parameters.NRN_PYTHON_VERSION >> coreneuron - store_artifacts: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 00dc718236..dfadcccdcb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -70,7 +70,7 @@ stages: -e NRN_RELEASE_UPLOAD \ -e SETUPTOOLS_SCM_PRETEND_VERSION \ -e NRN_BUILD_FOR_UPLOAD=1 \ - 'neuronsimulator/neuron_wheel:latest-x86_64' \ + 'neuronsimulator/neuron_wheel:test-x86_64' \ packaging/python/build_wheels.bash linux $(python.version) coreneuron displayName: 'Building ManyLinux Wheel' From 387ee9544494596d9251320bdd54ac909d70f800 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Wed, 4 Dec 2024 17:59:59 +0100 Subject: [PATCH 04/37] Rerun CI From 75b07cdefe73145e188a03cb0f495733211367df Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Wed, 4 Dec 2024 18:32:22 +0100 Subject: [PATCH 05/37] Upgrade Python orb in circle CI --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index edf5d0a01e..78b0083c5b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 orbs: - python: circleci/python@2.1.1 + python: circleci/python@3.0.0 jobs: manylinux2014-aarch64: From a5ffdfcc310e94334935dd642c09a80189bb7232 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Thu, 5 Dec 2024 14:23:24 +0100 Subject: [PATCH 06/37] Try suggestion --- .circleci/config.yml | 46 +++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 78b0083c5b..758467b1b3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,24 +46,34 @@ jobs: sudo apt update sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev - # choose available python versions from pyenv - pyenv_py_ver="" - case << parameters.NRN_PYTHON_VERSION >> in - 39) pyenv_py_ver="3.9" ;; - 310) pyenv_py_ver="3.10" ;; - 311) pyenv_py_ver="3.11" ;; - 312) pyenv_py_ver="3.12" ;; - 313) pyenv_py_ver="3.13" ;; - *) echo "Error: pyenv python version not specified or not supported." && exit 1;; - esac - - env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install $pyenv_py_ver --force - pyenv global $pyenv_py_ver - export PYTHON_EXE=$(which python) - - # test wheel - packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) - + # use the desired python version from the docker image directly + echo "Using Python << parameters.NRN_PYTHON_VERSION >>" + + # set python version using the correct docker image + if [ "<< parameters.NRN_PYTHON_VERSION >>" == "313" ]; then + docker run --rm -v $PWD:/mnt cimg/python:3.13.1 bash -c " + python --version; + # test wheel + packaging/python/test_wheels.sh $(which python) $(ls -t wheelhouse/*.whl) + " + else + # for older versions, fallback to pyenv approach + pyenv_py_ver="" + case << parameters.NRN_PYTHON_VERSION >> in + 39) pyenv_py_ver="3.9" ;; + 310) pyenv_py_ver="3.10" ;; + 311) pyenv_py_ver="3.11" ;; + 312) pyenv_py_ver="3.12" ;; + *) echo "Error: pyenv python version not specified or not supported." && exit 1;; + esac + + env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install $pyenv_py_ver --force + pyenv global $pyenv_py_ver + export PYTHON_EXE=$(which python) + + # test wheel + packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) + fi - run: name: Upload nightly wheel to pypi.org command: | From 01320a7514eca566772e57b5322e34f53f5f327a Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Thu, 5 Dec 2024 14:52:02 +0100 Subject: [PATCH 07/37] Try in the right location --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 758467b1b3..a3bd6fbb71 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,6 +54,7 @@ jobs: docker run --rm -v $PWD:/mnt cimg/python:3.13.1 bash -c " python --version; # test wheel + cd /mnt packaging/python/test_wheels.sh $(which python) $(ls -t wheelhouse/*.whl) " else From 9821eaf97eb20697050e09e4a115f8723f799f73 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 14:04:03 +0100 Subject: [PATCH 08/37] Fix issue on Python 3.13.1 For some reason, https://github.com/python/cpython/pull/125846 broke the ability to iterate over `HocObject`s, so as a workaround, we can first cast it to a Python list. --- test/hoctests/tests/test_thread_partition.py | 2 +- test/pytest_coreneuron/test_basic.py | 2 +- test/pytest_coreneuron/test_zptrlist.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hoctests/tests/test_thread_partition.py b/test/hoctests/tests/test_thread_partition.py index 10b10aabdf..ba5539281d 100644 --- a/test/hoctests/tests/test_thread_partition.py +++ b/test/hoctests/tests/test_thread_partition.py @@ -38,7 +38,7 @@ def assertpart(parts="default"): if str(parts) == "default": # not round-robin but root order roots = h.SectionList() roots.allroots() - roots = [root for root in roots] + roots = [root for root in list(roots)] i = 0 for ith in range(pc.nthread()): sl = pc.get_partition(ith) diff --git a/test/pytest_coreneuron/test_basic.py b/test/pytest_coreneuron/test_basic.py index 5ec4fe01e1..11e442cbe5 100644 --- a/test/pytest_coreneuron/test_basic.py +++ b/test/pytest_coreneuron/test_basic.py @@ -209,7 +209,7 @@ def test_HocObject_no_deferred_unref(): for sec in h.allsec(): print(sec) sl.append(sec=sec) - assert len([s for s in sl]) == 0 + assert len([s for s in list(sl)]) == 0 def test_deleted_sec(): diff --git a/test/pytest_coreneuron/test_zptrlist.py b/test/pytest_coreneuron/test_zptrlist.py index 3f5b11b4cf..ee39de805a 100644 --- a/test/pytest_coreneuron/test_zptrlist.py +++ b/test/pytest_coreneuron/test_zptrlist.py @@ -49,7 +49,7 @@ def test_rvp(): # for coverage of ptrlist changes in nrniv/shape.cpp assert rvp.right() == 30.0 sl = h.SectionList() rvp.list(sl) - sz = sum([1 for _ in sl]) + sz = sum([1 for _ in list(sl)]) assert sz == 3 From 714c81b59f93ea11d316b40f1bac6180bfccde6e Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 14:17:46 +0100 Subject: [PATCH 09/37] Missed one --- share/lib/python/neuron/rxd/region.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index cdfc0e8f96..a6d403f5a8 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -29,7 +29,7 @@ def _sort_secs(secs): all_sorted = h.SectionList() for root in root_secs: all_sorted.wholetree(sec=root) - secs_names = dict([(sec.hoc_internal_name(), sec) for sec in secs]) + secs_names = dict([(sec.hoc_internal_name(), sec) for sec in list(secs)]) # for sec in secs: # if sec.orientation(): # raise RxDException('still need to deal with backwards sections') From 1e4bcedeba812743865b9b8a98aa7c89747bb9c6 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 14:28:52 +0100 Subject: [PATCH 10/37] And another --- share/lib/python/neuron/rxd/region.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index a6d403f5a8..ed41d3258b 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -35,7 +35,7 @@ def _sort_secs(secs): # raise RxDException('still need to deal with backwards sections') secs = [ secs_names[sec.hoc_internal_name()] - for sec in all_sorted + for sec in list(all_sorted) if sec.hoc_internal_name() in secs_names ] # return an empty list rather than an empty SectionList because From 6f967c1d59bd95a001d8ea5885d9a3b398294571 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 15:59:20 +0100 Subject: [PATCH 11/37] Fix rest of issues with iterables --- share/lib/python/neuron/rxd/region.py | 12 +++++++----- test/hoctests/tests/test_thread_partition.py | 2 +- test/pytest_coreneuron/test_basic.py | 2 +- test/pytest_coreneuron/test_zptrlist.py | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index ed41d3258b..74278227fa 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -29,7 +29,7 @@ def _sort_secs(secs): all_sorted = h.SectionList() for root in root_secs: all_sorted.wholetree(sec=root) - secs_names = dict([(sec.hoc_internal_name(), sec) for sec in list(secs)]) + secs_names = {sec.hoc_internal_name(): sec for sec in list(secs)} # for sec in secs: # if sec.orientation(): # raise RxDException('still need to deal with backwards sections') @@ -645,7 +645,7 @@ def mesh_eval(self): else: return {"instantiated": False} result = {"instantiated": True} - total_num_3d_segs = sum(sec.nseg for sec in self._secs3d) + total_num_3d_segs = sum(sec.nseg for sec in list(self._secs3d)) segs_with_surface = {node.segment for node in sp.nodes if node.surface_area} result["3dsegswithoutsurface"] = len(segs_with_surface) - total_num_3d_segs return result @@ -725,7 +725,9 @@ def _do_init(self): self._xs, self._ys, self._zs = zip(*self._points) maps = { seg: i - for i, seg in enumerate([seg for sec in self._secs3d for seg in sec]) + for i, seg in enumerate( + [seg for sec in list(self._secs3d) for seg in sec] + ) } segs = [] @@ -753,13 +755,13 @@ def _do_init(self): self._surface_nodes_by_seg = surface_nodes_by_seg self._nodes_by_seg = nodes_by_seg self._secs3d_names = { - sec.hoc_internal_name(): sec.nseg for sec in self._secs3d + sec.hoc_internal_name(): sec.nseg for sec in list(self._secs3d) } self._segsidx = segs self._dx = self.dx def _segs3d(self, index=None): - segs = [seg for sec in self._secs3d for seg in sec] + segs = [seg for sec in list(self._secs3d) for seg in sec] if index: return [seg for i, seg in enumerate(segs) if i in index] return segs diff --git a/test/hoctests/tests/test_thread_partition.py b/test/hoctests/tests/test_thread_partition.py index ba5539281d..7eb840b290 100644 --- a/test/hoctests/tests/test_thread_partition.py +++ b/test/hoctests/tests/test_thread_partition.py @@ -38,7 +38,7 @@ def assertpart(parts="default"): if str(parts) == "default": # not round-robin but root order roots = h.SectionList() roots.allroots() - roots = [root for root in list(roots)] + roots = list(roots) i = 0 for ith in range(pc.nthread()): sl = pc.get_partition(ith) diff --git a/test/pytest_coreneuron/test_basic.py b/test/pytest_coreneuron/test_basic.py index 11e442cbe5..338872a25d 100644 --- a/test/pytest_coreneuron/test_basic.py +++ b/test/pytest_coreneuron/test_basic.py @@ -209,7 +209,7 @@ def test_HocObject_no_deferred_unref(): for sec in h.allsec(): print(sec) sl.append(sec=sec) - assert len([s for s in list(sl)]) == 0 + assert list(sl) def test_deleted_sec(): diff --git a/test/pytest_coreneuron/test_zptrlist.py b/test/pytest_coreneuron/test_zptrlist.py index ee39de805a..6b3aa9e713 100644 --- a/test/pytest_coreneuron/test_zptrlist.py +++ b/test/pytest_coreneuron/test_zptrlist.py @@ -49,7 +49,7 @@ def test_rvp(): # for coverage of ptrlist changes in nrniv/shape.cpp assert rvp.right() == 30.0 sl = h.SectionList() rvp.list(sl) - sz = sum([1 for _ in list(sl)]) + sz = len(list(sl)) assert sz == 3 From ff010a778e8a143c09c95f65b9675e6f0740cce0 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 16:18:20 +0100 Subject: [PATCH 12/37] One more --- share/lib/python/neuron/rxd/species.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/lib/python/neuron/rxd/species.py b/share/lib/python/neuron/rxd/species.py index bd6e59f610..b6b08b65a0 100644 --- a/share/lib/python/neuron/rxd/species.py +++ b/share/lib/python/neuron/rxd/species.py @@ -1751,7 +1751,7 @@ def _do_init2(self): d = self._d self._secs = [ - Section1D(self, sec, d, r) for r in self._regions for sec in r._secs1d + Section1D(self, sec, d, r) for r in self._regions for sec in list(r._secs1d) ] if self._secs: self._offset = self._secs[0]._offset From 460e12b0b93db791fa5200ab9c52e526c8346662 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 16:30:00 +0100 Subject: [PATCH 13/37] More casting to list --- share/lib/python/neuron/rxd/region.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index 74278227fa..e24a6279b7 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -75,7 +75,7 @@ def __init__(self, regions): for rptr in self._regions: r = rptr() self._overlap = h.SectionList( - [sec for sec in r._secs1d if sec in self._overlap] + [sec for sec in list(r._secs1d) if sec in self._overlap] ) if r in _c_region_lookup: _c_region_lookup[rptr].append(self) @@ -1026,7 +1026,7 @@ def volume(self, index=None): vol += numpy.sum(self._vol) if hasattr(self, "_geometry") and any(self._secs1d): vol += numpy.sum( - [self._geometry.volumes1d(sec) for sec in self._secs1d] + [self._geometry.volumes1d(sec) for sec in list(self._secs1d)] ) return vol return self._vol[index] From 8262448f4b9bee2452b082e799aa0e5d9481cadd Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Fri, 6 Dec 2024 23:53:04 +0100 Subject: [PATCH 14/37] Another one --- share/lib/python/neuron/rxd/region.py | 2 +- test/pytest_coreneuron/test_basic.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index e24a6279b7..d4f67c4329 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -75,7 +75,7 @@ def __init__(self, regions): for rptr in self._regions: r = rptr() self._overlap = h.SectionList( - [sec for sec in list(r._secs1d) if sec in self._overlap] + [sec for sec in list(r._secs1d) if sec in list(self._overlap)] ) if r in _c_region_lookup: _c_region_lookup[rptr].append(self) diff --git a/test/pytest_coreneuron/test_basic.py b/test/pytest_coreneuron/test_basic.py index 338872a25d..ce6c31b31e 100644 --- a/test/pytest_coreneuron/test_basic.py +++ b/test/pytest_coreneuron/test_basic.py @@ -209,7 +209,7 @@ def test_HocObject_no_deferred_unref(): for sec in h.allsec(): print(sec) sl.append(sec=sec) - assert list(sl) + assert len(list(sl)) == 0 def test_deleted_sec(): From 0564d4937608550a6a1c6fa779a17a377e883013 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Sat, 7 Dec 2024 00:07:50 +0100 Subject: [PATCH 15/37] Another --- share/lib/python/neuron/rxd/region.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index d4f67c4329..906ea88bfa 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -197,7 +197,7 @@ def _ecs_initalize(self): def _initalize(self): from .species import Species, SpeciesOnRegion - self.num_segments = numpy.sum([x.nseg for x in self._overlap]) + self.num_segments = numpy.sum([x.nseg for x in list(self._overlap)]) self.location_index = -numpy.ones( (self.num_regions, self.num_species + self.num_params, self.num_segments), ctypes.c_int, From e474bbf9dd2eab95f080f78338e37814787d9fa9 Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sat, 7 Dec 2024 05:30:12 -0500 Subject: [PATCH 16/37] Python 3.13.1 failure for [s for s in sl] where sl is a SectionList. Also accept len(sl) --- src/nrnpython/nrnpy_hoc.cpp | 25 +++++++++++++++++++++++-- test/hoctests/tests/test_seclist.py | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 test/hoctests/tests/test_seclist.py diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index 1e68124c8c..26d16e3931 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -1646,6 +1646,16 @@ static int araychk(Arrayinfo* a, PyHocObject* po, int ix) { return 0; } +static Py_ssize_t seclist_count(Object* ho) { + assert(ho->ctemplate == hoc_sectionlist_template_); + hoc_List* sl = (hoc_List*) (ho->u.this_pointer); + Py_ssize_t n = 0; + for (hoc_Item* q1 = sl->next; q1 != sl; q1 = q1->next) { + n++; + } + return n; +} + static Py_ssize_t hocobj_len(PyObject* self) { PyHocObject* po = (PyHocObject*) self; if (po->type_ == PyHoc::HocObject) { @@ -1654,8 +1664,7 @@ static Py_ssize_t hocobj_len(PyObject* self) { } else if (po->ho_->ctemplate == hoc_list_template_) { return ivoc_list_count(po->ho_); } else if (po->ho_->ctemplate == hoc_sectionlist_template_) { - PyErr_SetString(PyExc_TypeError, "hoc.SectionList has no len()"); - return -1; + return seclist_count(po->ho_); } } else if (po->type_ == PyHoc::HocArray) { Arrayinfo* a = hocobj_aray(po->sym_, po->ho_); @@ -1682,6 +1691,8 @@ static int hocobj_nonzero(PyObject* self) { b = vector_capacity((Vect*) po->ho_->u.this_pointer) > 0; } else if (po->ho_->ctemplate == hoc_list_template_) { b = ivoc_list_count(po->ho_) > 0; + } else if (po->ho_->ctemplate == hoc_sectionlist_template_) { + b = seclist_count(po->ho_) > 0; } } else if (po->type_ == PyHoc::HocArray) { Arrayinfo* a = hocobj_aray(po->sym_, po->ho_); @@ -1729,6 +1740,16 @@ static PyObject* hocobj_iter(PyObject* raw_self) { pho2->iteritem_ = ((hoc_Item*) po->ho_->u.this_pointer); return po2.release().ptr(); } + } else if (po->type_ == PyHoc::HocSectionListIterator) { + // Can anyone explain why this block has become needed since + // Python3.13.1 and why a copy of the above body suffices. + // need a clone of self so nested loops do not share iteritem_ + auto po2 = nb::steal(nrnpy_ho2po(po->ho_)); + PyHocObject* pho2 = (PyHocObject*) po2.ptr(); + pho2->type_ = PyHoc::HocSectionListIterator; + pho2->u.its_ = PyHoc::Begin; + pho2->iteritem_ = ((hoc_Item*) po->ho_->u.this_pointer); + return po2.release().ptr(); } else if (po->type_ == PyHoc::HocForallSectionIterator) { po->iteritem_ = section_list; po->u.its_ = PyHoc::Begin; diff --git a/test/hoctests/tests/test_seclist.py b/test/hoctests/tests/test_seclist.py new file mode 100644 index 0000000000..0f3c86696a --- /dev/null +++ b/test/hoctests/tests/test_seclist.py @@ -0,0 +1,18 @@ +from neuron import h + +secs = [h.Section() for _ in range(10)] + + +def test(): + sl = h.SectionList() + sl.allroots() + assert len(sl) == len(list(sl)) + b = [(s1, s2) for s1 in sl for s2 in sl] + n = len(sl) + for i in range(n): + for j in range(n): + assert b[i * n + j][0] == b[i + j * n][1] + return sl + + +sl = test() From bf3cc7e85b5c199d4eeff68c991ab2787c15872d Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sat, 7 Dec 2024 05:50:01 -0500 Subject: [PATCH 17/37] Update doc for h.SectionList() --- docs/python/modelspec/programmatic/topology/seclist.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/python/modelspec/programmatic/topology/seclist.rst b/docs/python/modelspec/programmatic/topology/seclist.rst index 3ff618c188..810d145d62 100755 --- a/docs/python/modelspec/programmatic/topology/seclist.rst +++ b/docs/python/modelspec/programmatic/topology/seclist.rst @@ -31,6 +31,10 @@ SectionList for sec in python_iterable_of_sections: sl.append(sec) + ``len(sl)`` returns the number of sections in the SectionList. + + ``list(sl)`` and ``[s for s in sl]`` generate equivalent lists. + .. seealso:: :class:`SectionBrowser`, :class:`Shape`, :meth:`RangeVarPlot.list` From 781a75cc37de33cf4f32c92fd957cd15247c531a Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Sun, 8 Dec 2024 13:18:22 +0100 Subject: [PATCH 18/37] Revert list changes --- share/lib/python/neuron/rxd/region.py | 20 +++++++++----------- share/lib/python/neuron/rxd/species.py | 2 +- test/hoctests/tests/test_thread_partition.py | 2 +- test/pytest_coreneuron/test_basic.py | 2 +- test/pytest_coreneuron/test_zptrlist.py | 2 +- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index 906ea88bfa..cdfc0e8f96 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -29,13 +29,13 @@ def _sort_secs(secs): all_sorted = h.SectionList() for root in root_secs: all_sorted.wholetree(sec=root) - secs_names = {sec.hoc_internal_name(): sec for sec in list(secs)} + secs_names = dict([(sec.hoc_internal_name(), sec) for sec in secs]) # for sec in secs: # if sec.orientation(): # raise RxDException('still need to deal with backwards sections') secs = [ secs_names[sec.hoc_internal_name()] - for sec in list(all_sorted) + for sec in all_sorted if sec.hoc_internal_name() in secs_names ] # return an empty list rather than an empty SectionList because @@ -75,7 +75,7 @@ def __init__(self, regions): for rptr in self._regions: r = rptr() self._overlap = h.SectionList( - [sec for sec in list(r._secs1d) if sec in list(self._overlap)] + [sec for sec in r._secs1d if sec in self._overlap] ) if r in _c_region_lookup: _c_region_lookup[rptr].append(self) @@ -197,7 +197,7 @@ def _ecs_initalize(self): def _initalize(self): from .species import Species, SpeciesOnRegion - self.num_segments = numpy.sum([x.nseg for x in list(self._overlap)]) + self.num_segments = numpy.sum([x.nseg for x in self._overlap]) self.location_index = -numpy.ones( (self.num_regions, self.num_species + self.num_params, self.num_segments), ctypes.c_int, @@ -645,7 +645,7 @@ def mesh_eval(self): else: return {"instantiated": False} result = {"instantiated": True} - total_num_3d_segs = sum(sec.nseg for sec in list(self._secs3d)) + total_num_3d_segs = sum(sec.nseg for sec in self._secs3d) segs_with_surface = {node.segment for node in sp.nodes if node.surface_area} result["3dsegswithoutsurface"] = len(segs_with_surface) - total_num_3d_segs return result @@ -725,9 +725,7 @@ def _do_init(self): self._xs, self._ys, self._zs = zip(*self._points) maps = { seg: i - for i, seg in enumerate( - [seg for sec in list(self._secs3d) for seg in sec] - ) + for i, seg in enumerate([seg for sec in self._secs3d for seg in sec]) } segs = [] @@ -755,13 +753,13 @@ def _do_init(self): self._surface_nodes_by_seg = surface_nodes_by_seg self._nodes_by_seg = nodes_by_seg self._secs3d_names = { - sec.hoc_internal_name(): sec.nseg for sec in list(self._secs3d) + sec.hoc_internal_name(): sec.nseg for sec in self._secs3d } self._segsidx = segs self._dx = self.dx def _segs3d(self, index=None): - segs = [seg for sec in list(self._secs3d) for seg in sec] + segs = [seg for sec in self._secs3d for seg in sec] if index: return [seg for i, seg in enumerate(segs) if i in index] return segs @@ -1026,7 +1024,7 @@ def volume(self, index=None): vol += numpy.sum(self._vol) if hasattr(self, "_geometry") and any(self._secs1d): vol += numpy.sum( - [self._geometry.volumes1d(sec) for sec in list(self._secs1d)] + [self._geometry.volumes1d(sec) for sec in self._secs1d] ) return vol return self._vol[index] diff --git a/share/lib/python/neuron/rxd/species.py b/share/lib/python/neuron/rxd/species.py index b6b08b65a0..bd6e59f610 100644 --- a/share/lib/python/neuron/rxd/species.py +++ b/share/lib/python/neuron/rxd/species.py @@ -1751,7 +1751,7 @@ def _do_init2(self): d = self._d self._secs = [ - Section1D(self, sec, d, r) for r in self._regions for sec in list(r._secs1d) + Section1D(self, sec, d, r) for r in self._regions for sec in r._secs1d ] if self._secs: self._offset = self._secs[0]._offset diff --git a/test/hoctests/tests/test_thread_partition.py b/test/hoctests/tests/test_thread_partition.py index 7eb840b290..10b10aabdf 100644 --- a/test/hoctests/tests/test_thread_partition.py +++ b/test/hoctests/tests/test_thread_partition.py @@ -38,7 +38,7 @@ def assertpart(parts="default"): if str(parts) == "default": # not round-robin but root order roots = h.SectionList() roots.allroots() - roots = list(roots) + roots = [root for root in roots] i = 0 for ith in range(pc.nthread()): sl = pc.get_partition(ith) diff --git a/test/pytest_coreneuron/test_basic.py b/test/pytest_coreneuron/test_basic.py index ce6c31b31e..5ec4fe01e1 100644 --- a/test/pytest_coreneuron/test_basic.py +++ b/test/pytest_coreneuron/test_basic.py @@ -209,7 +209,7 @@ def test_HocObject_no_deferred_unref(): for sec in h.allsec(): print(sec) sl.append(sec=sec) - assert len(list(sl)) == 0 + assert len([s for s in sl]) == 0 def test_deleted_sec(): diff --git a/test/pytest_coreneuron/test_zptrlist.py b/test/pytest_coreneuron/test_zptrlist.py index 6b3aa9e713..3f5b11b4cf 100644 --- a/test/pytest_coreneuron/test_zptrlist.py +++ b/test/pytest_coreneuron/test_zptrlist.py @@ -49,7 +49,7 @@ def test_rvp(): # for coverage of ptrlist changes in nrniv/shape.cpp assert rvp.right() == 30.0 sl = h.SectionList() rvp.list(sl) - sz = len(list(sl)) + sz = sum([1 for _ in sl]) assert sz == 3 From fb30bb58e84662f22f8df9459a008c7d7dd4aa58 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Sun, 8 Dec 2024 14:34:55 +0100 Subject: [PATCH 19/37] Add workaround for `install_name_tool` issue --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index 05e8ca67e1..069bb124a4 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,7 @@ import sys from collections import defaultdict import logging +import platform logging.basicConfig(level=logging.INFO) from shutil import copytree, which @@ -461,6 +462,8 @@ def setup_package(): + ["-Wl,-rpath,{}".format(REL_RPATH + "/../../.data/lib/")], ) ) + if platform.system() == "Darwin": + rxd_params["extra_link_args"] = ["-headerpad_max_install_names"] logging.info("RX3D compile flags %s" % str(rxd_params)) From 4c9c9d728dfe64720f99ef93c890a20ce2091196 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Sun, 8 Dec 2024 16:15:15 +0100 Subject: [PATCH 20/37] Typo --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 069bb124a4..25c3fabc2a 100644 --- a/setup.py +++ b/setup.py @@ -463,7 +463,7 @@ def setup_package(): ) ) if platform.system() == "Darwin": - rxd_params["extra_link_args"] = ["-headerpad_max_install_names"] + rxd_params["extra_link_args"] += ["-headerpad_max_install_names"] logging.info("RX3D compile flags %s" % str(rxd_params)) From e700d85718d34e0c8f4bc46b2b9d9db8b903a4fb Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 12:45:41 +0100 Subject: [PATCH 21/37] Try single quotes --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a3bd6fbb71..ae00afd28f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,12 +51,12 @@ jobs: # set python version using the correct docker image if [ "<< parameters.NRN_PYTHON_VERSION >>" == "313" ]; then - docker run --rm -v $PWD:/mnt cimg/python:3.13.1 bash -c " + docker run --rm -v $PWD:/mnt cimg/python:3.13.1 bash -c ' python --version; # test wheel cd /mnt packaging/python/test_wheels.sh $(which python) $(ls -t wheelhouse/*.whl) - " + ' else # for older versions, fallback to pyenv approach pyenv_py_ver="" From 9e96b90359dabfdc4cd6906dfd5fdabd20f0f728 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 15:12:38 +0100 Subject: [PATCH 22/37] Update pyenv --- .circleci/config.yml | 49 ++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ae00afd28f..eb359fbcc9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,35 +46,26 @@ jobs: sudo apt update sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev - # use the desired python version from the docker image directly - echo "Using Python << parameters.NRN_PYTHON_VERSION >>" - - # set python version using the correct docker image - if [ "<< parameters.NRN_PYTHON_VERSION >>" == "313" ]; then - docker run --rm -v $PWD:/mnt cimg/python:3.13.1 bash -c ' - python --version; - # test wheel - cd /mnt - packaging/python/test_wheels.sh $(which python) $(ls -t wheelhouse/*.whl) - ' - else - # for older versions, fallback to pyenv approach - pyenv_py_ver="" - case << parameters.NRN_PYTHON_VERSION >> in - 39) pyenv_py_ver="3.9" ;; - 310) pyenv_py_ver="3.10" ;; - 311) pyenv_py_ver="3.11" ;; - 312) pyenv_py_ver="3.12" ;; - *) echo "Error: pyenv python version not specified or not supported." && exit 1;; - esac - - env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install $pyenv_py_ver --force - pyenv global $pyenv_py_ver - export PYTHON_EXE=$(which python) - - # test wheel - packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) - fi + # choose available python versions from pyenv + pyenv update || cd $(pyenv root) && git pull && cd - + + pyenv_py_ver="" + case << parameters.NRN_PYTHON_VERSION >> in + 39) pyenv_py_ver="3.9" ;; + 310) pyenv_py_ver="3.10" ;; + 311) pyenv_py_ver="3.11" ;; + 312) pyenv_py_ver="3.12" ;; + 313) pyenv_py_ver="3.13" ;; + *) echo "Error: pyenv python version not specified or not supported." && exit 1;; + esac + + env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install $pyenv_py_ver --force + pyenv global $pyenv_py_ver + export PYTHON_EXE=$(which python) + + # test wheel + packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) + - run: name: Upload nightly wheel to pypi.org command: | From 2c2da0c110f4e20d69b476749b3f80ebd8c4899e Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 15:42:32 +0100 Subject: [PATCH 23/37] I don't know anymore --- .circleci/config.yml | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eb359fbcc9..6406f880b4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: manylinux2014-aarch64: parameters: - NRN_PYTHON_VERSION: + NRN_PYTHON_VERSION_MINOR: type: string NRN_NIGHTLY_UPLOAD: type: string @@ -32,7 +32,7 @@ jobs: -e SETUPTOOLS_SCM_PRETEND_VERSION \ -e NRN_BUILD_FOR_UPLOAD=1 \ 'neuronsimulator/neuron_wheel:test-aarch64' \ - packaging/python/build_wheels.bash linux << parameters.NRN_PYTHON_VERSION >> coreneuron + packaging/python/build_wheels.bash linux 3<< parameters.NRN_PYTHON_VERSION_MINOR >> coreneuron - store_artifacts: path: ./wheelhouse @@ -42,26 +42,15 @@ jobs: name: Test manylinux AArch64 wheel command: | - # install mpi dependencies + sudo apt install software-properties-common + sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update + # install mpi dependencies sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev + # install Python from deadsnakes + sudo apt install python3.<< parameters.NRN_PYTHON_VERSION_MINOR >> - # choose available python versions from pyenv - pyenv update || cd $(pyenv root) && git pull && cd - - - pyenv_py_ver="" - case << parameters.NRN_PYTHON_VERSION >> in - 39) pyenv_py_ver="3.9" ;; - 310) pyenv_py_ver="3.10" ;; - 311) pyenv_py_ver="3.11" ;; - 312) pyenv_py_ver="3.12" ;; - 313) pyenv_py_ver="3.13" ;; - *) echo "Error: pyenv python version not specified or not supported." && exit 1;; - esac - - env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install $pyenv_py_ver --force - pyenv global $pyenv_py_ver - export PYTHON_EXE=$(which python) + export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) # test wheel packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) @@ -89,7 +78,7 @@ workflows: - /circleci\/.*/ matrix: parameters: - NRN_PYTHON_VERSION: ["313"] + NRN_PYTHON_VERSION_MINOR: ["13"] NRN_NIGHTLY_UPLOAD: ["false"] nightly: @@ -104,5 +93,5 @@ workflows: - manylinux2014-aarch64: matrix: parameters: - NRN_PYTHON_VERSION: ["39", "310", "311", "312", "313"] + NRN_PYTHON_VERSION_MINOR: ["9", "10", "11", "12", "13"] NRN_NIGHTLY_UPLOAD: ["true"] From a4ff9149995421b80a92dde6fc683903274d1b1f Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 15:49:17 +0100 Subject: [PATCH 24/37] Do not copy dockerfile --- packaging/python/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/packaging/python/Dockerfile b/packaging/python/Dockerfile index 36c7d0ad4f..07bb55d3fb 100644 --- a/packaging/python/Dockerfile +++ b/packaging/python/Dockerfile @@ -87,9 +87,6 @@ ENV PATH /nrnwheel/openmpi/bin:$PATH RUN yum -y install epel-release libX11-devel libXcomposite-devel vim-enhanced && yum -y clean all && rm -rf /var/cache RUN yum -y remove ncurses-devel -# Copy Dockerfile for reference -COPY Dockerfile . - # build wheels from there WORKDIR /root From 3d234370d96f73cc7c74461b1f58085c021e166b Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 16:12:42 +0100 Subject: [PATCH 25/37] Revert "Do not copy dockerfile" This reverts commit a4ff9149995421b80a92dde6fc683903274d1b1f. --- packaging/python/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packaging/python/Dockerfile b/packaging/python/Dockerfile index 07bb55d3fb..36c7d0ad4f 100644 --- a/packaging/python/Dockerfile +++ b/packaging/python/Dockerfile @@ -87,6 +87,9 @@ ENV PATH /nrnwheel/openmpi/bin:$PATH RUN yum -y install epel-release libX11-devel libXcomposite-devel vim-enhanced && yum -y clean all && rm -rf /var/cache RUN yum -y remove ncurses-devel +# Copy Dockerfile for reference +COPY Dockerfile . + # build wheels from there WORKDIR /root From bcf17f2467b6c348e00994c776cf92092a68d5cc Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 16:13:17 +0100 Subject: [PATCH 26/37] yYYYYYY --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6406f880b4..afa7453cc7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,13 +42,13 @@ jobs: name: Test manylinux AArch64 wheel command: | - sudo apt install software-properties-common - sudo add-apt-repository ppa:deadsnakes/ppa + sudo apt install -t software-properties-common + sudo add-apt-repository -y ppa:deadsnakes/ppa sudo apt update # install mpi dependencies sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev # install Python from deadsnakes - sudo apt install python3.<< parameters.NRN_PYTHON_VERSION_MINOR >> + sudo apt install -y python3.<< parameters.NRN_PYTHON_VERSION_MINOR >> export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) From 5c23c801ce38cd8a3bb6026e60fffd650da55b7d Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 17:09:24 +0100 Subject: [PATCH 27/37] Test --- .circleci/config.yml | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index afa7453cc7..928d5597fa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,30 +18,10 @@ jobs: resource_class: arm.medium steps: - - checkout - - run: - name: Build manylinux AArch64 wheel - command: | - docker run --rm \ - -w /root/nrn \ - -v $PWD:/root/nrn \ - -v /opt/nrnwheel/mpt:/nrnwheel/mpt \ - -e NEURON_NIGHTLY_TAG \ - -e NRN_NIGHTLY_UPLOAD \ - -e NRN_RELEASE_UPLOAD \ - -e SETUPTOOLS_SCM_PRETEND_VERSION \ - -e NRN_BUILD_FOR_UPLOAD=1 \ - 'neuronsimulator/neuron_wheel:test-aarch64' \ - packaging/python/build_wheels.bash linux 3<< parameters.NRN_PYTHON_VERSION_MINOR >> coreneuron - - - store_artifacts: - path: ./wheelhouse - destination: artifacts - - run: name: Test manylinux AArch64 wheel command: | - + sudo apt update sudo apt install -t software-properties-common sudo add-apt-repository -y ppa:deadsnakes/ppa sudo apt update @@ -52,19 +32,9 @@ jobs: export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) - # test wheel - packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) + + - - run: - name: Upload nightly wheel to pypi.org - command: | - if [ "<< parameters.NRN_NIGHTLY_UPLOAD >>" == "true" ]; then - python -m pip install --upgrade pip - python -m pip install twine - python -m twine upload --verbose --skip-existing -u $TWINE_USERNAME -p $TWINE_PASSWORD wheelhouse/*.whl - else - echo "Skipping pypi.org upload!" - fi workflows: From 4158389040e3561cb78f5b225770fcd53838e913 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 17:17:04 +0100 Subject: [PATCH 28/37] Try manually --- .circleci/config.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 928d5597fa..c4f68f58bd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,8 +22,7 @@ jobs: name: Test manylinux AArch64 wheel command: | sudo apt update - sudo apt install -t software-properties-common - sudo add-apt-repository -y ppa:deadsnakes/ppa + echo "deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu jammy main" | sudo tee /etc/apt/sources.list.d/deadsnakes-ppa.list && sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 && sudo apt update sudo apt update # install mpi dependencies sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev From 4200be854537e195c8e61122812e19a5df37e50b Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 17:19:05 +0100 Subject: [PATCH 29/37] Print version --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c4f68f58bd..373ee6f8f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) - + $PYTHON_EXE --version From d01a18888a724db2763560f4f6bdac7ecf8301b5 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 17:24:09 +0100 Subject: [PATCH 30/37] Add back most of it --- .circleci/config.yml | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 373ee6f8f6..eb9268965a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,6 +18,26 @@ jobs: resource_class: arm.medium steps: + - checkout + - run: + name: Build manylinux AArch64 wheel + command: | + docker run --rm \ + -w /root/nrn \ + -v $PWD:/root/nrn \ + -v /opt/nrnwheel/mpt:/nrnwheel/mpt \ + -e NEURON_NIGHTLY_TAG \ + -e NRN_NIGHTLY_UPLOAD \ + -e NRN_RELEASE_UPLOAD \ + -e SETUPTOOLS_SCM_PRETEND_VERSION \ + -e NRN_BUILD_FOR_UPLOAD=1 \ + 'neuronsimulator/neuron_wheel:latest-gcc9-aarch64' \ + packaging/python/build_wheels.bash linux 3<< parameters.NRN_PYTHON_VERSION_MINOR >> coreneuron + + - store_artifacts: + path: ./wheelhouse + destination: artifacts + - run: name: Test manylinux AArch64 wheel command: | @@ -31,9 +51,19 @@ jobs: export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) - $PYTHON_EXE --version - + # test wheel + packaging/python/test_wheels.sh $PYTHON_EXE $(ls -t wheelhouse/*.whl) + - run: + name: Upload nightly wheel to pypi.org + command: | + if [ "<< parameters.NRN_NIGHTLY_UPLOAD >>" == "true" ]; then + python -m pip install --upgrade pip + python -m pip install twine + python -m twine upload --verbose --skip-existing -u $TWINE_USERNAME -p $TWINE_PASSWORD wheelhouse/*.whl + else + echo "Skipping pypi.org upload!" + fi workflows: From b6bbe925727df8b430bc91947b185409aa335966 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 17:33:23 +0100 Subject: [PATCH 31/37] Fix image --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eb9268965a..5636878226 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: -e NRN_RELEASE_UPLOAD \ -e SETUPTOOLS_SCM_PRETEND_VERSION \ -e NRN_BUILD_FOR_UPLOAD=1 \ - 'neuronsimulator/neuron_wheel:latest-gcc9-aarch64' \ + 'neuronsimulator/neuron_wheel:test-aarch64' \ packaging/python/build_wheels.bash linux 3<< parameters.NRN_PYTHON_VERSION_MINOR >> coreneuron - store_artifacts: From 349372aba0882fee054776b0e781abab179485b3 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 18:09:18 +0100 Subject: [PATCH 32/37] Missing venv --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5636878226..80fbacca26 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,7 @@ jobs: # install mpi dependencies sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev # install Python from deadsnakes - sudo apt install -y python3.<< parameters.NRN_PYTHON_VERSION_MINOR >> + sudo apt install -y python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>-venv export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) From 2d4fb82334d7a078a537804e79133582a369f7b2 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 18:11:08 +0100 Subject: [PATCH 33/37] Bring back original --- src/nrnpython/nrnpy_hoc.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index 6508b82257..0ee57d8289 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -1743,16 +1743,6 @@ static PyObject* hocobj_iter(PyObject* raw_self) { pho2->iteritem_ = ((hoc_Item*) po->ho_->u.this_pointer); return po2.release().ptr(); } - } else if (po->type_ == PyHoc::HocSectionListIterator) { - // Can anyone explain why this block has become needed since - // Python3.13.1 and why a copy of the above body suffices. - // need a clone of self so nested loops do not share iteritem_ - auto po2 = nb::steal(nrnpy_ho2po(po->ho_)); - PyHocObject* pho2 = (PyHocObject*) po2.ptr(); - pho2->type_ = PyHoc::HocSectionListIterator; - pho2->u.its_ = PyHoc::Begin; - pho2->iteritem_ = ((hoc_Item*) po->ho_->u.this_pointer); - return po2.release().ptr(); } else if (po->type_ == PyHoc::HocForallSectionIterator) { po->iteritem_ = section_list; po->u.its_ = PyHoc::Begin; From 6e959fbbae89dbab8585d47aeeb5b416fb3f3c54 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Mon, 9 Dec 2024 18:13:52 +0100 Subject: [PATCH 34/37] Update image --- .circleci/config.yml | 2 +- azure-pipelines.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 80fbacca26..1c5c509ab3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: -e NRN_RELEASE_UPLOAD \ -e SETUPTOOLS_SCM_PRETEND_VERSION \ -e NRN_BUILD_FOR_UPLOAD=1 \ - 'neuronsimulator/neuron_wheel:test-aarch64' \ + 'neuronsimulator/neuron_wheel:latest-aarch64' \ packaging/python/build_wheels.bash linux 3<< parameters.NRN_PYTHON_VERSION_MINOR >> coreneuron - store_artifacts: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index dfadcccdcb..5970a4243f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -70,14 +70,14 @@ stages: -e NRN_RELEASE_UPLOAD \ -e SETUPTOOLS_SCM_PRETEND_VERSION \ -e NRN_BUILD_FOR_UPLOAD=1 \ - 'neuronsimulator/neuron_wheel:test-x86_64' \ + 'neuronsimulator/neuron_wheel:latest-x86_64' \ packaging/python/build_wheels.bash linux $(python.version) coreneuron displayName: 'Building ManyLinux Wheel' - script: | sudo apt update sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev - displayName: 'Install Test System Depdendencies' + displayName: 'Install Test System Dependencies' - template: ci/azure-wheel-test-upload.yml From 95074a27310a1f80a0014399d3cd1f86bd1e8ba9 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Tue, 10 Dec 2024 09:26:08 +0100 Subject: [PATCH 35/37] Update Dockerfile Remove Python 3.13t (the free-threaded build) as we do not support it yet. --- packaging/python/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packaging/python/Dockerfile b/packaging/python/Dockerfile index 36c7d0ad4f..95931335cc 100644 --- a/packaging/python/Dockerfile +++ b/packaging/python/Dockerfile @@ -93,4 +93,7 @@ COPY Dockerfile . # build wheels from there WORKDIR /root +# remove Python 3.13t since we do not support the free-threaded build yet +RUN rm -fr /opt/python/cp313-cp313t + ENV NMODL_PYLIB=/nrnwheel/python/lib/libpython3.10.so.1.0 From d8cfdc432b1abce2efc81abc24b5663d99bc3c61 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Tue, 10 Dec 2024 10:49:03 +0100 Subject: [PATCH 36/37] Install lib --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1c5c509ab3..2abda946dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,8 +46,9 @@ jobs: sudo apt update # install mpi dependencies sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev + version=3.<< parameters.NRN_PYTHON_VERSION_MINOR >> # install Python from deadsnakes - sudo apt install -y python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>-venv + sudo apt install -y python${version}-venv libpython${version}-dev export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>) From 0c8ea49e6dcaeb648e44901c0be9945e51961146 Mon Sep 17 00:00:00 2001 From: Goran Jelic-Cizmek Date: Tue, 10 Dec 2024 11:29:19 +0100 Subject: [PATCH 37/37] Explicitly install all deps --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2abda946dd..263a46c424 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,7 +48,7 @@ jobs: sudo apt install -y mpich openmpi-bin libopenmpi-dev libmpich-dev version=3.<< parameters.NRN_PYTHON_VERSION_MINOR >> # install Python from deadsnakes - sudo apt install -y python${version}-venv libpython${version}-dev + sudo apt install -y python${version}-venv libpython${version}-dev g++ make export PYTHON_EXE=$(which python3.<< parameters.NRN_PYTHON_VERSION_MINOR >>)