From f43ae00eebe8e9d050444d84182e0e56cf998189 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 26 Aug 2023 00:05:02 -0400 Subject: [PATCH 01/10] use Python limited API --- .github/workflows/wheel.yml | 44 +---------------------------------- pyproject.toml | 13 ++++++++++- reacnetgenerator/dps.pyx | 4 ++++ reacnetgenerator/utils_np.pyx | 3 +++ setup.py | 13 +++++++++++ 5 files changed, 33 insertions(+), 44 deletions(-) diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index da3c294f0..81c769cb2 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -20,18 +20,6 @@ jobs: - os: ubuntu-latest python: 37 platform_id: manylinux_x86_64 - - os: ubuntu-latest - python: 38 - platform_id: manylinux_x86_64 - - os: ubuntu-latest - python: 39 - platform_id: manylinux_x86_64 - - os: ubuntu-latest - python: 310 - platform_id: manylinux_x86_64 - - os: ubuntu-latest - python: 311 - platform_id: manylinux_x86_64 # macos-x86-64 - os: macos-latest python: 37 @@ -39,44 +27,14 @@ jobs: - os: macos-latest python: 38 platform_id: macosx_universal2 - - os: macos-latest - python: 39 - platform_id: macosx_universal2 - - os: macos-latest - python: 310 - platform_id: macosx_universal2 - - os: macos-latest - python: 311 - platform_id: macosx_universal2 # win-64 - os: windows-2019 python: 37 platform_id: win_amd64 - - os: windows-2019 - python: 38 - platform_id: win_amd64 - - os: windows-2019 - python: 39 - platform_id: win_amd64 - - os: windows-2019 - python: 310 - platform_id: win_amd64 - - os: windows-2019 - python: 311 - platform_id: win_amd64 steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - name: Install Python - with: - python-version: '3.10' - - - name: Install cibuildwheel - run: | - python -m pip install cibuildwheel==2.11.1 - name: Build wheels - run: | - python -m cibuildwheel --output-dir wheelhouse + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_ARCHS: all CIBW_BUILD: cp${{ matrix.python }}-${{ matrix.platform_id }} diff --git a/pyproject.toml b/pyproject.toml index b6a674ab1..c0738a2ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ requires = [ "oldest-supported-numpy", "nodejs-bin~=16.15.1a4", "pyyaml", - "cython>=0.16", + "cython>=3.0.1", ] build-backend = "setuptools.build_meta" @@ -116,6 +116,17 @@ test-skip = "*-win_amd64" [tool.cibuildwheel.linux] environment-pass = ["CIBW_BUILD"] +# Use abi3audit to catch issues with Limited API wheels +repair-wheel-command = [ + "auditwheel repair -w {dest_dir} {wheel}", + "pipx run abi3audit --strict --report {wheel}", +] + +[tool.cibuildwheel.macos] +repair-wheel-command = [ + "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}", + "pipx run abi3audit --strict --report {wheel}", +] [tool.pyright] include = [ diff --git a/reacnetgenerator/dps.pyx b/reacnetgenerator/dps.pyx index c6bbdfa29..be496487e 100644 --- a/reacnetgenerator/dps.pyx +++ b/reacnetgenerator/dps.pyx @@ -6,6 +6,8 @@ """Connect molecule with Depth-First Search.""" from libc.stdlib cimport free, malloc +import cython + cdef extern from "c_stack.h": # This function is copied from https://zhuanlan.zhihu.com/p/38212302 @@ -14,6 +16,7 @@ cdef extern from "c_stack.h": int pop() +@cython.binding(False) def dps(bonds, levels): """Connect molecule with Depth-First Search. @@ -67,6 +70,7 @@ def dps(bonds, levels): return molecule, bondlist +@cython.binding(False) def dps_reaction(reactdict): """Find A+B->C+D reactions. diff --git a/reacnetgenerator/utils_np.pyx b/reacnetgenerator/utils_np.pyx index 6ce279eb4..d0d317d03 100644 --- a/reacnetgenerator/utils_np.pyx +++ b/reacnetgenerator/utils_np.pyx @@ -4,6 +4,7 @@ # cython: linetrace=True # cython: infer_types=True +import cython import numpy as np cimport cython @@ -17,6 +18,7 @@ ctypedef np.int8_t DTYPE8_t @cython.boundscheck(False) @cython.wraparound(False) +@cython.binding(False) cpdef idx_to_signal(DTYPE_t[:] idx, int step): """Converts an index array to a signal array. @@ -53,6 +55,7 @@ cpdef idx_to_signal(DTYPE_t[:] idx, int step): @cython.boundscheck(False) @cython.wraparound(False) +@cython.binding(False) cpdef check_zero_signal(DTYPE8_t[:] signal): """Check if the given signal contains only zeros. diff --git a/setup.py b/setup.py index f2087fdba..e15f2dac6 100644 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ import setuptools.command.build_ext import yaml from setuptools import Extension, setup +from wheel.bdist_wheel import bdist_wheel try: from nodejs.node import call as node_call @@ -65,6 +66,17 @@ def run(self): setuptools.command.build_ext.build_ext.run(self) +class bdist_wheel_abi3(bdist_wheel): + def get_tag(self): + python, abi, plat = super().get_tag() + + if python.startswith("cp"): + # on CPython, our wheels are abi3 and compatible back to 3.7 + return "cp37", "abi3", plat + + return python, abi, plat + + if __name__ == "__main__": define_macros = [] if os.environ.get("DEBUG", 0): @@ -89,5 +101,6 @@ def run(self): ext_modules=ext_modules, cmdclass={ "build_ext": BuildExtCommand, + "bdist_wheel": bdist_wheel_abi3 }, ) From 824cc1cbe367bf85b2ab98e03b386eba1cead13d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 26 Aug 2023 04:05:19 +0000 Subject: [PATCH 02/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- setup.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/setup.py b/setup.py index e15f2dac6..d5c565525 100644 --- a/setup.py +++ b/setup.py @@ -99,8 +99,5 @@ def get_tag(self): setup( ext_modules=ext_modules, - cmdclass={ - "build_ext": BuildExtCommand, - "bdist_wheel": bdist_wheel_abi3 - }, + cmdclass={"build_ext": BuildExtCommand, "bdist_wheel": bdist_wheel_abi3}, ) From cf836866f9235d04cac240b9077ff25391d510cb Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 26 Aug 2023 00:31:48 -0400 Subject: [PATCH 03/10] set macros Signed-off-by: Jinzhe Zeng --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d5c565525..c2f44bcda 100644 --- a/setup.py +++ b/setup.py @@ -78,7 +78,7 @@ def get_tag(self): if __name__ == "__main__": - define_macros = [] + define_macros = [("CYTHON_LIMITED_API", "1"), ("Py_LIMITED_API", "0x03070000")] if os.environ.get("DEBUG", 0): define_macros.extend((("CYTHON_TRACE", "1"), ("CYTHON_TRACE_NOGIL", "1"))) From affedf26b9c026e30f8d35644ecc5ce3a2afd9a5 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 26 Aug 2023 14:20:11 -0400 Subject: [PATCH 04/10] fix for a in b --- reacnetgenerator/dps.pyx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/reacnetgenerator/dps.pyx b/reacnetgenerator/dps.pyx index be496487e..efd14099e 100644 --- a/reacnetgenerator/dps.pyx +++ b/reacnetgenerator/dps.pyx @@ -38,7 +38,7 @@ def dps(bonds, levels): bondlist = [] cdef int _N = len(bonds) cdef int *visited = malloc(_N * sizeof(int)) - cdef int i, s, b_c, l + cdef int i, s, b_c, l, ib, nb cdef C_Stack st for i in range(_N): visited[i]=0 @@ -55,7 +55,10 @@ def dps(bonds, levels): elif visited[s]==1: continue mol.append(s) - for b, l in zip(bonds[s], levels[s]): + nb = len(bonds[s]) + for ib in range(nb): + b = bonds[s][nb] + l = levels[s][nb] b_c = b if visited[b_c]==0: # bond.append((s, b, l) if i < b else (b, s, l)) @@ -91,8 +94,11 @@ def dps_reaction(reactdict): cdef set visited_right = set() visited = [visited_left, visited_right] cdef C_Stack st + cdef nm, im, nr, ir - for init_mol in reactdict[0]: + nm = len(reactdict[0]) + for im in range(nm): + init_mol = reactdict[0][im] if init_mol not in visited[0]: reaction = [[], []] st.push(init_mol) @@ -104,7 +110,9 @@ def dps_reaction(reactdict): elif mol in visited[side]: continue reaction[side].append(mol) - for r in reactdict[side][mol]: + nr = len(reactdict[side][mol]) + for ir in range(nr): + r = reactdict[side][mol][ir] if r < 0: if r not in reaction[1-side]: reaction[1-side].append(r) From 1d3354f646dabfa1c047f8e0a4e08b64177a6ba1 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 26 Aug 2023 14:30:41 -0400 Subject: [PATCH 05/10] int --- reacnetgenerator/dps.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reacnetgenerator/dps.pyx b/reacnetgenerator/dps.pyx index efd14099e..3ef58ebf7 100644 --- a/reacnetgenerator/dps.pyx +++ b/reacnetgenerator/dps.pyx @@ -94,7 +94,7 @@ def dps_reaction(reactdict): cdef set visited_right = set() visited = [visited_left, visited_right] cdef C_Stack st - cdef nm, im, nr, ir + cdef int nm, im, nr, ir nm = len(reactdict[0]) for im in range(nm): From 758b05c053e302d0b4b10078af7b1b61e0bed797 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 26 Aug 2023 14:57:59 -0400 Subject: [PATCH 06/10] fix --- reacnetgenerator/utils_np.pyx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/reacnetgenerator/utils_np.pyx b/reacnetgenerator/utils_np.pyx index d0d317d03..fcb13a872 100644 --- a/reacnetgenerator/utils_np.pyx +++ b/reacnetgenerator/utils_np.pyx @@ -16,8 +16,6 @@ DTYPE8 = np.int8 ctypedef np.int8_t DTYPE8_t -@cython.boundscheck(False) -@cython.wraparound(False) @cython.binding(False) cpdef idx_to_signal(DTYPE_t[:] idx, int step): """Converts an index array to a signal array. @@ -53,8 +51,6 @@ cpdef idx_to_signal(DTYPE_t[:] idx, int step): return signal -@cython.boundscheck(False) -@cython.wraparound(False) @cython.binding(False) cpdef check_zero_signal(DTYPE8_t[:] signal): """Check if the given signal contains only zeros. From d778a744aad8841d3b658f31953409f396ab6504 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 11 Mar 2024 21:44:10 -0400 Subject: [PATCH 07/10] bump numpy --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 07155cee1..26b2bf1a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "setuptools>=63", "wheel", "setuptools_scm[toml]", - "oldest-supported-numpy", + "numpy>=2.0.0b0", "nodejs-wheel~=20.9", "pyyaml", "cython>=3.0.1", From 492875dcdb2580a585787112a5c8c5913843c1c3 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 11 Mar 2024 22:23:14 -0400 Subject: [PATCH 08/10] compile against int64 Signed-off-by: Jinzhe Zeng --- reacnetgenerator/utils_np.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reacnetgenerator/utils_np.pyx b/reacnetgenerator/utils_np.pyx index fcb13a872..7779bf872 100644 --- a/reacnetgenerator/utils_np.pyx +++ b/reacnetgenerator/utils_np.pyx @@ -10,8 +10,8 @@ import numpy as np cimport cython cimport numpy as np -DTYPE = int -ctypedef np.int_t DTYPE_t +DTYPE = np.int64 +ctypedef np.int64_t DTYPE_t DTYPE8 = np.int8 ctypedef np.int8_t DTYPE8_t From 94ec9d8452ab8968097f4e7677f86a0bbdc4f28d Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Tue, 12 Mar 2024 15:03:39 -0400 Subject: [PATCH 09/10] bump to py311 --- .github/workflows/wheel.yml | 8 ++++---- setup.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index 16f481310..c109b3a7c 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -19,15 +19,15 @@ jobs: include: # linux-64 - os: ubuntu-latest - python: 39 + python: 311 platform_id: manylinux_x86_64 # macos-x86-64 - os: macos-latest - python: 39 + python: 311 platform_id: macosx_universal2 # win-64 - os: windows-2019 - python: 39 + python: 311 platform_id: win_amd64 steps: - uses: actions/checkout@v4 @@ -50,7 +50,7 @@ jobs: - uses: actions/setup-python@v5 name: Install Python with: - python-version: '3.10' + python-version: '3.11' - run: python -m pip install build - name: Build sdist run: python -m build --sdist diff --git a/setup.py b/setup.py index e9a8cdf63..75889f7ba 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ def get_tag(self): if __name__ == "__main__": - define_macros = [("CYTHON_LIMITED_API", "1"), ("Py_LIMITED_API", "0x03070000")] + define_macros = [("CYTHON_LIMITED_API", "1"), ("Py_LIMITED_API", "0x03110000")] if os.environ.get("DEBUG", 0): define_macros.extend((("CYTHON_TRACE", "1"), ("CYTHON_TRACE_NOGIL", "1"))) From a95364974d45949647170f798ede5b7a3aa88c07 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Tue, 12 Mar 2024 15:13:21 -0400 Subject: [PATCH 10/10] fix Py_LIMITED_API Signed-off-by: Jinzhe Zeng --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 75889f7ba..17cfa2f93 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ def get_tag(self): if __name__ == "__main__": - define_macros = [("CYTHON_LIMITED_API", "1"), ("Py_LIMITED_API", "0x03110000")] + define_macros = [("CYTHON_LIMITED_API", "1"), ("Py_LIMITED_API", "0x030b0000")] if os.environ.get("DEBUG", 0): define_macros.extend((("CYTHON_TRACE", "1"), ("CYTHON_TRACE_NOGIL", "1")))