Skip to content

Commit af424bb

Browse files
authored
Merge pull request #2079 from minrk/cpython-cffi
allow building cffi on cpython
2 parents bddc57d + 799b026 commit af424bb

File tree

9 files changed

+56
-9
lines changed

9 files changed

+56
-9
lines changed

.github/workflows/test.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ jobs:
8282
- os: ubuntu-24.04
8383
python: "3.12"
8484

85+
- os: ubuntu-24.04
86+
python: "3.13"
87+
backend: cffi
88+
8589
- os: ubuntu-24.04
8690
python: "3.13"
8791

@@ -193,6 +197,12 @@ jobs:
193197
run: |
194198
echo "ZMQ_PREFIX=${{ matrix.zmq }}" >> "$GITHUB_ENV"
195199
200+
- name: set $PYZMQ_BACKEND
201+
if: matrix.backend
202+
run: |
203+
echo "PYZMQ_BACKEND=${{ matrix.backend }}" >> "$GITHUB_ENV"
204+
pip install cffi
205+
196206
- name: install libzmq-dev
197207
if: matrix.zmq == 'head'
198208
run: |

CMakeLists.txt

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ set(PYZMQ_LIBSODIUM_URL "" CACHE STRING "full URL to download bundled libsodium"
2929
set(PYZMQ_LIBSODIUM_CONFIGURE_ARGS "" CACHE STRING "semicolon-separated list of arguments to pass to ./configure for bundled libsodium")
3030
set(PYZMQ_LIBSODIUM_MSBUILD_ARGS "" CACHE STRING "semicolon-separated list of arguments to pass to msbuild for bundled libsodium")
3131
set(PYZMQ_LIBSODIUM_VS_VERSION "" CACHE STRING "Visual studio solution version for bundled libsodium (default: detect from MSVC_VERSION)")
32+
set(PYZMQ_BACKEND "" CACHE STRING "pyzmq backend to build ('cffi' or 'cython'). Default: cffi on PyPy, else Cython.")
3233

3334
if (NOT CMAKE_BUILD_TYPE)
3435
# default to Release
@@ -57,6 +58,7 @@ foreach(_optname
5758
PYZMQ_LIBSODIUM_CONFIGURE_ARGS
5859
PYZMQ_LIBSODIUM_MSBUILD_ARGS
5960
PYZMQ_LIBSODIUM_VS_VERSION
61+
PYZMQ_BACKEND
6062
)
6163
if (DEFINED ENV{${_optname}})
6264
if (_optname MATCHES ".*_ARGS")
@@ -367,8 +369,19 @@ set(EXT_SRC_DIR "${CMAKE_CURRENT_BINARY_DIR}/_src")
367369
set(ZMQ_BUILDUTILS "${CMAKE_CURRENT_SOURCE_DIR}/buildutils")
368370
file(MAKE_DIRECTORY "${EXT_SRC_DIR}")
369371

370-
if(Python_INTERPRETER_ID STREQUAL "PyPy")
372+
if (NOT PYZMQ_BACKEND)
373+
if(Python_INTERPRETER_ID STREQUAL "PyPy")
374+
set(PYZMQ_BACKEND "cffi")
375+
else()
376+
set(PYZMQ_BACKEND "cython")
377+
endif()
378+
endif()
379+
380+
if(PYZMQ_BACKEND STREQUAL "cffi")
371381
message(STATUS "Building CFFI backend")
382+
if(NOT Python_INTERPRETER_ID STREQUAL "PyPy")
383+
message(WARNING "Building CFFI backend on ${Python_INTERPRETER_ID}, not PyPy. This is not supported and may not work.")
384+
endif()
372385
set(ZMQ_EXT_NAME "_cffi")
373386

374387
set(ZMQ_BACKEND_DEST "zmq/backend/cffi")
@@ -381,8 +394,11 @@ if(Python_INTERPRETER_ID STREQUAL "PyPy")
381394
"${ZMQ_BUILDUTILS}/build_cffi.py"
382395
"${ZMQ_C}"
383396
)
384-
else()
397+
elseif(PYZMQ_BACKEND STREQUAL "cython")
385398
message(STATUS "Building Cython backend")
399+
if(NOT Python_INTERPRETER_ID STREQUAL "Python")
400+
message(WARNING "Building Cython backend on ${Python_INTERPRETER_ID}, not CPython. This is not supported and may not work.")
401+
endif()
386402
find_program(CYTHON "cython")
387403

388404
set(ZMQ_BACKEND_DEST "zmq/backend/cython")
@@ -400,6 +416,8 @@ else()
400416
--module-name "zmq.backend.cython._zmq"
401417
${ZMQ_PYX}
402418
)
419+
else()
420+
message(FATAL_ERROR "Unsupported PYZMQ_BACKEND=${PYZMQ_BACKEND}. Must be 'cffi' or 'cython'.")
403421
endif()
404422

405423
file(MAKE_DIRECTORY ${ZMQ_BACKEND_DEST})

docs/source/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ For a full changelog, consult the [git log](https://github.com/zeromq/pyzmq/comm
77

88
## 26
99

10+
### 26.3
11+
12+
pyzmq 26.3 drops support for Python 3.7 and adds wheels for PyPy 3.11
13+
1014
### 26.2.1
1115

1216
26.2.1 is a tiny bugfix release

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ requires = [
44
"cffi; implementation_name == 'pypy'",
55
"cython>=3.0.0; implementation_name != 'pypy'",
66
"packaging",
7-
"scikit-build-core",
7+
"scikit-build-core>=0.10",
88
]
99
build-backend = "scikit_build_core.build"
1010

@@ -55,9 +55,13 @@ wheel.license-files = ["licenses/LICENSE*"]
5555
# 3.15 is required by scikit-build-core
5656
cmake.version = ">=3.15"
5757
# only build/install the pyzmq component
58-
cmake.targets = ["pyzmq"]
58+
build.targets = ["pyzmq"]
5959
install.components = ["pyzmq"]
6060

61+
[[tool.scikit-build.overrides]]
62+
if.env.PYZMQ_BACKEND = "cffi"
63+
build.requires = ["cffi"]
64+
6165
[tool.ruff]
6266

6367
[tool.ruff.format]

tests/test_message.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import time
1717

1818
import zmq
19-
from zmq_test_utils import PYPY, BaseZMQTestCase, SkipTest, skip_pypy
19+
from zmq_test_utils import PYPY, BaseZMQTestCase, SkipTest, skip_cpython_cffi, skip_pypy
2020

2121
# some useful constants:
2222

@@ -230,6 +230,7 @@ def test_buffer_out(self):
230230
assert outb is m.buffer
231231
assert m.buffer is m.buffer
232232

233+
@skip_cpython_cffi
233234
def test_memoryview_shape(self):
234235
"""memoryview shape info"""
235236
data = "§§¶•ªº˜µ¬˚…∆˙åß∂©œ∑´†≈ç√".encode()
@@ -278,6 +279,7 @@ def test_memoryview(self):
278279
assert s2 == s
279280
assert m.bytes == s
280281

282+
@skip_cpython_cffi
281283
def test_noncopying_recv(self):
282284
"""check for clobbering message buffers"""
283285
null = b'\0' * 64
@@ -300,6 +302,7 @@ def test_noncopying_recv(self):
300302
assert m2.bytes == ff
301303
assert type(m2.bytes) is bytes
302304

305+
@skip_cpython_cffi
303306
def test_noncopying_memoryview(self):
304307
"""test non-copying memmoryview messages"""
305308
null = b'\0' * 64

tests/test_socket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ def test_large_send(self):
630630
# sample the front and back of the received message
631631
# without checking the whole content
632632
byte = ord(c)
633-
view = memoryview(rcvd)
633+
view = memoryview(rcvd.buffer)
634634
assert len(view) == N
635635
assert view[0] == byte
636636
assert view[-1] == byte

tests/zmq_test_utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
have_gevent = False
2828

2929

30-
PYPY = platform.python_implementation() == 'PyPy'
30+
CFFI = zmq.backend.Socket.__module__.startswith("zmq.backend.cffi.")
31+
PYPY = platform.python_implementation() == 'PyPy' or CFFI
3132

3233
# -----------------------------------------------------------------------------
3334
# skip decorators (directly from unittest)
@@ -38,7 +39,11 @@ def _id(x):
3839
return x
3940

4041

41-
skip_pypy = mark.skipif(PYPY, reason="Doesn't work on PyPy")
42+
skip_pypy = mark.skipif(PYPY, reason="Doesn't work on CFFI backend")
43+
skip_cpython_cffi = mark.skipif(
44+
platform.python_implementation() == 'CPython' and CFFI,
45+
reason="CFFI on CPython is unsupported",
46+
)
4247
require_zmq_4 = mark.skipif(zmq.zmq_version_info() < (4,), reason="requires zmq >= 4")
4348

4449
# -----------------------------------------------------------------------------

zmq/backend/cffi/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# Copyright (C) PyZMQ Developers
44
# Distributed under the terms of the Modified BSD License.
55

6+
# for clearer error message on missing cffi
7+
import cffi # noqa
8+
69
from zmq.backend.cffi import _poll, context, devices, error, message, socket, utils
710

811
from ._cffi import ffi

zmq/sugar/frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def __repr__(self):
7474
nbytes = len(self)
7575
msg_suffix = ""
7676
if nbytes > 16:
77-
msg_bytes = bytes(memoryview(self)[:12])
77+
msg_bytes = bytes(memoryview(self.buffer)[:12])
7878
if nbytes >= 1e9:
7979
unit = "GB"
8080
n = nbytes // 1e9

0 commit comments

Comments
 (0)