| diff --git a/buildutils/config.py b/buildutils/config.py |
| --- a/buildutils/config.py |
| +++ b/buildutils/config.py |
| @@ -87,6 +87,11 @@ def get_cfg_args(): |
| cfg = cfg2dict(cfg) |
| |
| g = cfg.setdefault('global', {}) |
| + if "NACL_BUILD_TREE" in os.environ: |
| + NACL_TREE = os.environ["NACL_BUILD_TREE"] |
| + cfg["global"]["zmq_prefix"] = NACL_TREE |
| + cfg["global"]["have_sys_un_h"] = "False" |
| + |
| # boolean keys: |
| for key in ['libzmq_extension', |
| 'bundle_libzmq_dylib', |
| diff --git a/setup.cfg b/setup.cfg |
| new file mode 100644 |
| --- /dev/null |
| +++ b/setup.cfg |
| @@ -0,0 +1,3 @@ |
| +[bdist_egg] |
| +plat-name = pnacl |
| + |
| diff --git a/setup.py b/setup.py |
| --- a/setup.py |
| +++ b/setup.py |
| @@ -270,6 +270,10 @@ class Configure(build_ext): |
| # include internal directories |
| settings.setdefault('include_dirs', []) |
| settings['include_dirs'] += [pjoin('zmq', sub) for sub in ('utils','core','devices')] |
| + if "NACL_BUILD_TREE" in os.environ: |
| + settings['include_dirs'].append(pjoin( |
| + os.environ["NACL_BUILD_TREE"], |
| + "include", "glibc-compat")) |
| |
| for ext in self.distribution.ext_modules: |
| if ext.name == 'zmq.libzmq': |
| @@ -826,29 +830,29 @@ def dotc(subdir, name): |
| |
| libzmq = pxd('core', 'libzmq') |
| buffers = pxd('utils', 'buffers') |
| -message = pxd('core', 'message') |
| -context = pxd('core', 'context') |
| -socket = pxd('core', 'socket') |
| +message = pxd('core', '_zmessage') |
| +context = pxd('core', '_zcontext') |
| +socket = pxd('core', '_zsocket') |
| checkrc = pxd('core', 'checkrc') |
| -monqueue = pxd('devices', 'monitoredqueue') |
| +monqueue = pxd('devices', '_zmonitoredqueue') |
| |
| submodules = dict( |
| - core = {'constants': [libzmq], |
| - 'error':[libzmq, checkrc], |
| - '_poll':[libzmq, socket, context, checkrc], |
| - 'stopwatch':[libzmq, pxd('core','stopwatch'), checkrc], |
| - 'context':[context, libzmq, checkrc], |
| - 'message':[libzmq, buffers, message, checkrc], |
| - 'socket':[context, message, socket, libzmq, buffers, checkrc], |
| - '_device':[libzmq, socket, context, checkrc], |
| - '_version':[libzmq], |
| + core = {'_zconstants': [libzmq], |
| + '_zerror':[libzmq, checkrc], |
| + '__zpoll':[libzmq, socket, context, checkrc], |
| + '_zstopwatch':[libzmq, pxd('core','_zstopwatch'), checkrc], |
| + '_zcontext':[context, libzmq, checkrc], |
| + '_zmessage':[libzmq, buffers, message, checkrc], |
| + '_zsocket':[context, message, socket, libzmq, buffers, checkrc], |
| + '__zdevice':[libzmq, socket, context, checkrc], |
| + '__zversion':[libzmq], |
| }, |
| devices = { |
| - 'monitoredqueue':[buffers, libzmq, monqueue, socket, context, checkrc], |
| + '_zmonitoredqueue':[buffers, libzmq, monqueue, socket, context, checkrc], |
| }, |
| utils = { |
| - 'initthreads':[libzmq], |
| - 'rebuffer':[buffers], |
| + '_zinitthreads':[libzmq], |
| + '_zrebuffer':[buffers], |
| }, |
| ) |
| |
| diff --git a/zmq/__init__.py b/zmq/__init__.py |
| --- a/zmq/__init__.py |
| +++ b/zmq/__init__.py |
| @@ -39,7 +39,7 @@ if bundled: |
| |
| if 'PyPy' not in sys.version: |
| try: |
| - from zmq.utils import initthreads # initialize threads |
| + from zmq.utils import _zinitthreads as initthreads # initialize threads |
| except ImportError as e: |
| raise ImportError("%s\nAre you trying to `import zmq` from the pyzmq source dir?" % e) |
| else: |
| diff --git a/zmq/core/__init__.py b/zmq/core/__init__.py |
| --- a/zmq/core/__init__.py |
| +++ b/zmq/core/__init__.py |
| @@ -23,21 +23,21 @@ |
| # Imports |
| #----------------------------------------------------------------------------- |
| |
| -from zmq.core import (constants, error, message, context, |
| - socket, stopwatch, _poll, _version, _device ) |
| +from zmq.core import (_zconstants, _zerror, _zmessage, _zcontext, |
| + _zsocket, _zstopwatch, __zpoll, __zversion, __zdevice ) |
| |
| __all__ = [] |
| -for submod in (constants, error, message, context, |
| - socket, stopwatch, _poll, _version, _device): |
| +for submod in (_zconstants, _zerror, _zmessage, _zcontext, |
| + _zsocket, _zstopwatch, __zpoll, __zversion, __zdevice): |
| __all__.extend(submod.__all__) |
| |
| -from zmq.core.constants import * |
| -from zmq.core.error import * |
| -from zmq.core.message import * |
| -from zmq.core.context import * |
| -from zmq.core.socket import * |
| -from zmq.core._poll import * |
| -from zmq.core.stopwatch import * |
| -from zmq.core._device import * |
| -from zmq.core._version import * |
| +from zmq.core._zconstants import * |
| +from zmq.core._zerror import * |
| +from zmq.core._zmessage import * |
| +from zmq.core._zcontext import * |
| +from zmq.core._zsocket import * |
| +from zmq.core.__zpoll import * |
| +from zmq.core._zstopwatch import * |
| +from zmq.core.__zdevice import * |
| +from zmq.core.__zversion import * |
| |
| diff --git a/zmq/core/__zdevice.pyx b/zmq/core/__zdevice.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/__zdevice.pyx |
| @@ -0,0 +1,86 @@ |
| +"""Python binding for 0MQ device function.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libzmq cimport zmq_device, zmq_proxy, ZMQ_VERSION_MAJOR |
| +from zmq.core._zsocket cimport Socket as cSocket |
| +from zmq.core.checkrc cimport _check_rc |
| + |
| +#----------------------------------------------------------------------------- |
| +# Basic device API |
| +#----------------------------------------------------------------------------- |
| + |
| +def device(int device_type, cSocket frontend, cSocket backend=None): |
| + """device(device_type, frontend, backend) |
| + |
| + Start a zeromq device. |
| + |
| + WARNING: zmq.device is deprecated as of libzmq-3.2, |
| + in favor of zmq.proxy. |
| + |
| + Parameters |
| + ---------- |
| + device_type : (QUEUE, FORWARDER, STREAMER) |
| + The type of device to start. |
| + frontend : Socket |
| + The Socket instance for the incoming traffic. |
| + backend : Socket |
| + The Socket instance for the outbound traffic. |
| + """ |
| + if ZMQ_VERSION_MAJOR >= 3: |
| + return proxy(frontend, backend) |
| + |
| + cdef int rc = 0 |
| + with nogil: |
| + rc = zmq_device(device_type, frontend.handle, backend.handle) |
| + _check_rc(rc) |
| + return rc |
| + |
| +def proxy(cSocket frontend, cSocket backend, cSocket capture=None): |
| + """proxy(frontend, backend, capture) |
| + |
| + Start a zeromq proxy (replacement for device). |
| + |
| + Parameters |
| + ---------- |
| + frontend : Socket |
| + The Socket instance for the incoming traffic. |
| + backend : Socket |
| + The Socket instance for the outbound traffic. |
| + capture : Socket |
| + The Socket instance for capturing traffic. |
| + """ |
| + cdef int rc = 0 |
| + cdef void* capture_handle |
| + if isinstance(capture, cSocket): |
| + capture_handle = capture.handle |
| + else: |
| + capture_handle = NULL |
| + with nogil: |
| + rc = zmq_proxy(frontend.handle, backend.handle, capture_handle) |
| + _check_rc(rc) |
| + return rc |
| + |
| +__all__ = ['device', 'proxy'] |
| + |
| diff --git a/zmq/core/__zpoll.pyx b/zmq/core/__zpoll.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/__zpoll.pyx |
| @@ -0,0 +1,136 @@ |
| +"""0MQ polling related functions and classes.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libc.stdlib cimport free, malloc |
| + |
| +from libzmq cimport zmq_pollitem_t, ZMQ_VERSION_MAJOR |
| +from libzmq cimport zmq_poll as zmq_poll_c |
| +from _zsocket cimport Socket |
| + |
| +import sys |
| + |
| +from zmq.core.checkrc cimport _check_rc |
| + |
| +#----------------------------------------------------------------------------- |
| +# Polling related methods |
| +#----------------------------------------------------------------------------- |
| + |
| +# version-independent typecheck for int/long |
| +if sys.version_info[0] >= 3: |
| + int_t = int |
| +else: |
| + int_t = (int,long) |
| + |
| +def zmq_poll(sockets, long timeout=-1): |
| + """zmq_poll(sockets, timeout=-1) |
| + |
| + Poll a set of 0MQ sockets, native file descs. or sockets. |
| + |
| + Parameters |
| + ---------- |
| + sockets : list of tuples of (socket, flags) |
| + Each element of this list is a two-tuple containing a socket |
| + and a flags. The socket may be a 0MQ socket or any object with |
| + a ``fileno()`` method. The flags can be zmq.POLLIN (for detecting |
| + for incoming messages), zmq.POLLOUT (for detecting that send is OK) |
| + or zmq.POLLIN|zmq.POLLOUT for detecting both. |
| + timeout : int |
| + The number of milliseconds to poll for. Negative means no timeout. |
| + """ |
| + cdef int rc, i |
| + cdef zmq_pollitem_t *pollitems = NULL |
| + cdef int nsockets = <int>len(sockets) |
| + cdef Socket current_socket |
| + |
| + if nsockets == 0: |
| + return [] |
| + |
| + pollitems = <zmq_pollitem_t *>malloc(nsockets*sizeof(zmq_pollitem_t)) |
| + if pollitems == NULL: |
| + raise MemoryError("Could not allocate poll items") |
| + |
| + if ZMQ_VERSION_MAJOR < 3: |
| + # timeout is us in 2.x, ms in 3.x |
| + # expected input is ms (matches 3.x) |
| + timeout = 1000*timeout |
| + |
| + for i in range(nsockets): |
| + s = sockets[i][0] |
| + events = sockets[i][1] |
| + if isinstance(s, Socket): |
| + current_socket = s |
| + pollitems[i].socket = current_socket.handle |
| + pollitems[i].events = events |
| + pollitems[i].revents = 0 |
| + elif isinstance(s, int_t): |
| + pollitems[i].socket = NULL |
| + pollitems[i].fd = s |
| + pollitems[i].events = events |
| + pollitems[i].revents = 0 |
| + elif hasattr(s, 'fileno'): |
| + try: |
| + fileno = int(s.fileno()) |
| + except: |
| + free(pollitems) |
| + raise ValueError('fileno() must return an valid integer fd') |
| + else: |
| + pollitems[i].socket = NULL |
| + pollitems[i].fd = fileno |
| + pollitems[i].events = events |
| + pollitems[i].revents = 0 |
| + else: |
| + free(pollitems) |
| + raise TypeError( |
| + "Socket must be a 0MQ socket, an integer fd or have " |
| + "a fileno() method: %r" % s |
| + ) |
| + |
| + |
| + with nogil: |
| + rc = zmq_poll_c(pollitems, nsockets, timeout) |
| + |
| + if rc < 0: |
| + free(pollitems) |
| + _check_rc(rc) |
| + |
| + results = [] |
| + for i in range(nsockets): |
| + s = sockets[i][0] |
| + # Return the fd for sockets, for compat. with select.poll. |
| + if hasattr(s, 'fileno'): |
| + s = s.fileno() |
| + revents = pollitems[i].revents |
| + # Only return sockets with non-zero status for compat. with select.poll. |
| + if revents > 0: |
| + results.append((s, revents)) |
| + |
| + free(pollitems) |
| + return results |
| + |
| +#----------------------------------------------------------------------------- |
| +# Symbols to export |
| +#----------------------------------------------------------------------------- |
| + |
| +__all__ = [ 'zmq_poll' ] |
| diff --git a/zmq/core/__zversion.pyx b/zmq/core/__zversion.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/__zversion.pyx |
| @@ -0,0 +1,43 @@ |
| +"""PyZMQ and 0MQ version functions.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libzmq cimport _zmq_version |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| +def zmq_version_info(): |
| + """zmq_version_info() |
| + |
| + Return the version of ZeroMQ itself as a 3-tuple of ints. |
| + """ |
| + cdef int major, minor, patch |
| + _zmq_version(&major, &minor, &patch) |
| + return (major, minor, patch) |
| + |
| + |
| +__all__ = ['zmq_version_info'] |
| + |
| diff --git a/zmq/core/_device.pyx b/zmq/core/_device.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/_device.pyx |
| +++ /dev/null |
| @@ -1,86 +0,0 @@ |
| -"""Python binding for 0MQ device function.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libzmq cimport zmq_device, zmq_proxy, ZMQ_VERSION_MAJOR |
| -from zmq.core.socket cimport Socket as cSocket |
| -from zmq.core.checkrc cimport _check_rc |
| - |
| -#----------------------------------------------------------------------------- |
| -# Basic device API |
| -#----------------------------------------------------------------------------- |
| - |
| -def device(int device_type, cSocket frontend, cSocket backend=None): |
| - """device(device_type, frontend, backend) |
| - |
| - Start a zeromq device. |
| - |
| - WARNING: zmq.device is deprecated as of libzmq-3.2, |
| - in favor of zmq.proxy. |
| - |
| - Parameters |
| - ---------- |
| - device_type : (QUEUE, FORWARDER, STREAMER) |
| - The type of device to start. |
| - frontend : Socket |
| - The Socket instance for the incoming traffic. |
| - backend : Socket |
| - The Socket instance for the outbound traffic. |
| - """ |
| - if ZMQ_VERSION_MAJOR >= 3: |
| - return proxy(frontend, backend) |
| - |
| - cdef int rc = 0 |
| - with nogil: |
| - rc = zmq_device(device_type, frontend.handle, backend.handle) |
| - _check_rc(rc) |
| - return rc |
| - |
| -def proxy(cSocket frontend, cSocket backend, cSocket capture=None): |
| - """proxy(frontend, backend, capture) |
| - |
| - Start a zeromq proxy (replacement for device). |
| - |
| - Parameters |
| - ---------- |
| - frontend : Socket |
| - The Socket instance for the incoming traffic. |
| - backend : Socket |
| - The Socket instance for the outbound traffic. |
| - capture : Socket |
| - The Socket instance for capturing traffic. |
| - """ |
| - cdef int rc = 0 |
| - cdef void* capture_handle |
| - if isinstance(capture, cSocket): |
| - capture_handle = capture.handle |
| - else: |
| - capture_handle = NULL |
| - with nogil: |
| - rc = zmq_proxy(frontend.handle, backend.handle, capture_handle) |
| - _check_rc(rc) |
| - return rc |
| - |
| -__all__ = ['device', 'proxy'] |
| - |
| diff --git a/zmq/core/_poll.pyx b/zmq/core/_poll.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/_poll.pyx |
| +++ /dev/null |
| @@ -1,136 +0,0 @@ |
| -"""0MQ polling related functions and classes.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libc.stdlib cimport free, malloc |
| - |
| -from libzmq cimport zmq_pollitem_t, ZMQ_VERSION_MAJOR |
| -from libzmq cimport zmq_poll as zmq_poll_c |
| -from socket cimport Socket |
| - |
| -import sys |
| - |
| -from zmq.core.checkrc cimport _check_rc |
| - |
| -#----------------------------------------------------------------------------- |
| -# Polling related methods |
| -#----------------------------------------------------------------------------- |
| - |
| -# version-independent typecheck for int/long |
| -if sys.version_info[0] >= 3: |
| - int_t = int |
| -else: |
| - int_t = (int,long) |
| - |
| -def zmq_poll(sockets, long timeout=-1): |
| - """zmq_poll(sockets, timeout=-1) |
| - |
| - Poll a set of 0MQ sockets, native file descs. or sockets. |
| - |
| - Parameters |
| - ---------- |
| - sockets : list of tuples of (socket, flags) |
| - Each element of this list is a two-tuple containing a socket |
| - and a flags. The socket may be a 0MQ socket or any object with |
| - a ``fileno()`` method. The flags can be zmq.POLLIN (for detecting |
| - for incoming messages), zmq.POLLOUT (for detecting that send is OK) |
| - or zmq.POLLIN|zmq.POLLOUT for detecting both. |
| - timeout : int |
| - The number of milliseconds to poll for. Negative means no timeout. |
| - """ |
| - cdef int rc, i |
| - cdef zmq_pollitem_t *pollitems = NULL |
| - cdef int nsockets = <int>len(sockets) |
| - cdef Socket current_socket |
| - |
| - if nsockets == 0: |
| - return [] |
| - |
| - pollitems = <zmq_pollitem_t *>malloc(nsockets*sizeof(zmq_pollitem_t)) |
| - if pollitems == NULL: |
| - raise MemoryError("Could not allocate poll items") |
| - |
| - if ZMQ_VERSION_MAJOR < 3: |
| - # timeout is us in 2.x, ms in 3.x |
| - # expected input is ms (matches 3.x) |
| - timeout = 1000*timeout |
| - |
| - for i in range(nsockets): |
| - s = sockets[i][0] |
| - events = sockets[i][1] |
| - if isinstance(s, Socket): |
| - current_socket = s |
| - pollitems[i].socket = current_socket.handle |
| - pollitems[i].events = events |
| - pollitems[i].revents = 0 |
| - elif isinstance(s, int_t): |
| - pollitems[i].socket = NULL |
| - pollitems[i].fd = s |
| - pollitems[i].events = events |
| - pollitems[i].revents = 0 |
| - elif hasattr(s, 'fileno'): |
| - try: |
| - fileno = int(s.fileno()) |
| - except: |
| - free(pollitems) |
| - raise ValueError('fileno() must return an valid integer fd') |
| - else: |
| - pollitems[i].socket = NULL |
| - pollitems[i].fd = fileno |
| - pollitems[i].events = events |
| - pollitems[i].revents = 0 |
| - else: |
| - free(pollitems) |
| - raise TypeError( |
| - "Socket must be a 0MQ socket, an integer fd or have " |
| - "a fileno() method: %r" % s |
| - ) |
| - |
| - |
| - with nogil: |
| - rc = zmq_poll_c(pollitems, nsockets, timeout) |
| - |
| - if rc < 0: |
| - free(pollitems) |
| - _check_rc(rc) |
| - |
| - results = [] |
| - for i in range(nsockets): |
| - s = sockets[i][0] |
| - # Return the fd for sockets, for compat. with select.poll. |
| - if hasattr(s, 'fileno'): |
| - s = s.fileno() |
| - revents = pollitems[i].revents |
| - # Only return sockets with non-zero status for compat. with select.poll. |
| - if revents > 0: |
| - results.append((s, revents)) |
| - |
| - free(pollitems) |
| - return results |
| - |
| -#----------------------------------------------------------------------------- |
| -# Symbols to export |
| -#----------------------------------------------------------------------------- |
| - |
| -__all__ = [ 'zmq_poll' ] |
| diff --git a/zmq/core/_version.pyx b/zmq/core/_version.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/_version.pyx |
| +++ /dev/null |
| @@ -1,43 +0,0 @@ |
| -"""PyZMQ and 0MQ version functions.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libzmq cimport _zmq_version |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| -def zmq_version_info(): |
| - """zmq_version_info() |
| - |
| - Return the version of ZeroMQ itself as a 3-tuple of ints. |
| - """ |
| - cdef int major, minor, patch |
| - _zmq_version(&major, &minor, &patch) |
| - return (major, minor, patch) |
| - |
| - |
| -__all__ = ['zmq_version_info'] |
| - |
| diff --git a/zmq/core/_zconstants.pyx b/zmq/core/_zconstants.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zconstants.pyx |
| @@ -0,0 +1,190 @@ |
| +"""0MQ Constants.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libzmq cimport * |
| + |
| +#----------------------------------------------------------------------------- |
| +# Python module level constants |
| +#----------------------------------------------------------------------------- |
| + |
| +_optionals = [] |
| + |
| +if ZMQ_VERSION < 30000: |
| + # backport DONTWAIT as alias to NOBLOCK |
| + NOBLOCK = ZMQ_NOBLOCK |
| + DONTWAIT = ZMQ_NOBLOCK |
| +else: |
| + # keep NOBLOCK as alias for new DONTWAIT |
| + NOBLOCK = ZMQ_DONTWAIT |
| + DONTWAIT = ZMQ_DONTWAIT |
| + |
| +VERSION = ZMQ_VERSION |
| + |
| +# socket types |
| +PAIR = ZMQ_PAIR |
| +PUB = ZMQ_PUB |
| +SUB = ZMQ_SUB |
| +REQ = ZMQ_REQ |
| +REP = ZMQ_REP |
| +DEALER = ZMQ_DEALER |
| +ROUTER = ZMQ_ROUTER |
| +PULL = ZMQ_PULL |
| +PUSH = ZMQ_PUSH |
| +XPUB = ZMQ_XPUB |
| +XSUB = ZMQ_XSUB |
| + |
| +# keep deprecated aliases |
| +XREQ = DEALER |
| +XREP = ROUTER |
| +UPSTREAM = PULL |
| +DOWNSTREAM = PUSH |
| + |
| + |
| +# socket options |
| +AFFINITY = ZMQ_AFFINITY |
| +IDENTITY = ZMQ_IDENTITY |
| +SUBSCRIBE = ZMQ_SUBSCRIBE |
| +UNSUBSCRIBE = ZMQ_UNSUBSCRIBE |
| +RATE = ZMQ_RATE |
| +RECOVERY_IVL = ZMQ_RECOVERY_IVL |
| +RECONNECT_IVL_MAX = ZMQ_RECONNECT_IVL_MAX |
| +SNDBUF = ZMQ_SNDBUF |
| +RCVBUF = ZMQ_RCVBUF |
| +RCVMORE = ZMQ_RCVMORE |
| +SNDMORE = ZMQ_SNDMORE |
| +POLLIN = ZMQ_POLLIN |
| +POLLOUT = ZMQ_POLLOUT |
| +POLLERR = ZMQ_POLLERR |
| + |
| +STREAMER = ZMQ_STREAMER |
| +FORWARDER = ZMQ_FORWARDER |
| +QUEUE = ZMQ_QUEUE |
| + |
| +# sockopts new in 2.2.0 |
| +SNDTIMEO = ZMQ_SNDTIMEO |
| +RCVTIMEO = ZMQ_RCVTIMEO |
| + |
| +# sockopts removed in 3.0.0 |
| +HWM = ZMQ_HWM |
| +SWAP = ZMQ_SWAP |
| +MCAST_LOOP = ZMQ_MCAST_LOOP |
| +RECOVERY_IVL_MSEC = ZMQ_RECOVERY_IVL_MSEC |
| + |
| +# new in 3.x |
| +IO_THREADS = ZMQ_IO_THREADS |
| +MAX_SOCKETS = ZMQ_MAX_SOCKETS |
| + |
| +MORE = ZMQ_MORE |
| + |
| +MAXMSGSIZE = ZMQ_MAXMSGSIZE |
| +SNDHWM = ZMQ_SNDHWM |
| +RCVHWM = ZMQ_RCVHWM |
| +MULTICAST_HOPS = ZMQ_MULTICAST_HOPS |
| +IPV4ONLY = ZMQ_IPV4ONLY |
| +LAST_ENDPOINT = ZMQ_LAST_ENDPOINT |
| + |
| +ROUTER_MANDATORY = ZMQ_ROUTER_MANDATORY |
| +# aliases |
| +ROUTER_BEHAVIOR = ROUTER_MANDATORY |
| +FAIL_UNROUTABLE = ROUTER_MANDATORY |
| + |
| +TCP_KEEPALIVE = ZMQ_TCP_KEEPALIVE |
| +TCP_KEEPALIVE_CNT = ZMQ_TCP_KEEPALIVE_CNT |
| +TCP_KEEPALIVE_IDLE = ZMQ_TCP_KEEPALIVE_IDLE |
| +TCP_KEEPALIVE_INTVL = ZMQ_TCP_KEEPALIVE_INTVL |
| +TCP_ACCEPT_FILTER = ZMQ_TCP_ACCEPT_FILTER |
| +DELAY_ATTACH_ON_CONNECT = ZMQ_DELAY_ATTACH_ON_CONNECT |
| +XPUB_VERBOSE = ZMQ_XPUB_VERBOSE |
| +ROUTER_RAW = ZMQ_ROUTER_RAW |
| + |
| +EVENT_CONNECTED = ZMQ_EVENT_CONNECTED |
| +EVENT_CONNECT_DELAYED = ZMQ_EVENT_CONNECT_DELAYED |
| +EVENT_CONNECT_RETRIED = ZMQ_EVENT_CONNECT_RETRIED |
| +EVENT_LISTENING = ZMQ_EVENT_LISTENING |
| +EVENT_BIND_FAILED = ZMQ_EVENT_BIND_FAILED |
| +EVENT_ACCEPTED = ZMQ_EVENT_ACCEPTED |
| +EVENT_ACCEPT_FAILED = ZMQ_EVENT_ACCEPT_FAILED |
| +EVENT_CLOSED = ZMQ_EVENT_CLOSED |
| +EVENT_CLOSE_FAILED = ZMQ_EVENT_CLOSE_FAILED |
| +EVENT_DISCONNECTED = ZMQ_EVENT_DISCONNECTED |
| + |
| +FD = ZMQ_FD |
| +EVENTS = ZMQ_EVENTS |
| +TYPE = ZMQ_TYPE |
| +LINGER = ZMQ_LINGER |
| +RECONNECT_IVL = ZMQ_RECONNECT_IVL |
| +BACKLOG = ZMQ_BACKLOG |
| + |
| +# As new constants are added in future versions, add a new block here |
| +# like the two above, checking agains the relevant value for ZMQ_VERSION. |
| +# The constants will need to be added to libzmq.pxd and utils/zmq_compat.h |
| +# as well. |
| + |
| +#----------------------------------------------------------------------------- |
| +# Error handling |
| +#----------------------------------------------------------------------------- |
| + |
| +# Often used standard errnos |
| +from errno import ( |
| + EAGAIN, |
| + EINVAL, |
| + EFAULT, |
| + ENOMEM, |
| + ENODEV |
| +) |
| + |
| +# For Windows compatability |
| +ENOTSUP = ZMQ_ENOTSUP |
| +EPROTONOSUPPORT = ZMQ_EPROTONOSUPPORT |
| +ENOBUFS = ZMQ_ENOBUFS |
| +ENETDOWN = ZMQ_ENETDOWN |
| +EADDRINUSE = ZMQ_EADDRINUSE |
| +EADDRNOTAVAIL = ZMQ_EADDRNOTAVAIL |
| +ECONNREFUSED = ZMQ_ECONNREFUSED |
| +EINPROGRESS = ZMQ_EINPROGRESS |
| +ENOTSOCK = ZMQ_ENOTSOCK |
| + |
| +# new errnos in zmq3 |
| +EMSGSIZE = ZMQ_EMSGSIZE |
| +EAFNOSUPPORT = ZMQ_EAFNOSUPPORT |
| +ENETUNREACH = ZMQ_ENETUNREACH |
| +ECONNABORTED = ZMQ_ECONNABORTED |
| +ECONNRESET = ZMQ_ECONNRESET |
| +ENOTCONN = ZMQ_ENOTCONN |
| +ETIMEDOUT = ZMQ_ETIMEDOUT |
| +EHOSTUNREACH = ZMQ_EHOSTUNREACH |
| +ENETRESET = ZMQ_ENETRESET |
| + |
| +# 0MQ Native |
| +EFSM = ZMQ_EFSM |
| +ENOCOMPATPROTO = ZMQ_ENOCOMPATPROTO |
| +ETERM = ZMQ_ETERM |
| +EMTHREAD = ZMQ_EMTHREAD |
| + |
| +#----------------------------------------------------------------------------- |
| +# Symbols to export |
| +#----------------------------------------------------------------------------- |
| +_names = list(locals().keys()) |
| +__all__ = [ key for key in _names if not key.startswith('_') ] |
| diff --git a/zmq/core/_zcontext.pxd b/zmq/core/_zcontext.pxd |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zcontext.pxd |
| @@ -0,0 +1,40 @@ |
| +"""0MQ Context class declaration.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| +cdef class Context: |
| + """Manage the lifecycle of a 0MQ context.""" |
| + |
| + cdef object __weakref__ # enable weakref |
| + cdef void *handle # The C handle for the underlying zmq object. |
| + cdef void **_sockets # A C-array containg socket handles |
| + cdef size_t _n_sockets # the number of sockets |
| + cdef size_t _max_sockets # the size of the _sockets array |
| + cdef int _pid # the pid of the process which created me (for fork safety) |
| + |
| + cdef public object closed # bool property for a closed context. |
| + # helpers for events on _sockets in Socket.__cinit__()/close() |
| + cdef inline void _add_socket(self, void* handle) |
| + cdef inline void _remove_socket(self, void* handle) |
| + |
| diff --git a/zmq/core/_zcontext.pyx b/zmq/core/_zcontext.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zcontext.pyx |
| @@ -0,0 +1,254 @@ |
| +"""0MQ Context class.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libc.stdlib cimport free, malloc, realloc |
| + |
| +from libzmq cimport * |
| + |
| +cdef extern from "getpid_compat.h": |
| + int getpid() |
| + |
| +from zmq.error import ZMQError |
| +from zmq.core.checkrc cimport _check_rc |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| +_instance = None |
| + |
| +cdef class Context: |
| + """Context(io_threads=1) |
| + |
| + Manage the lifecycle of a 0MQ context. |
| + |
| + Parameters |
| + ---------- |
| + io_threads : int |
| + The number of IO threads. |
| + """ |
| + |
| + def __cinit__(self, int io_threads = 1, **kwargs): |
| + self.handle = NULL |
| + self._sockets = NULL |
| + |
| + if ZMQ_VERSION_MAJOR >= 3: |
| + self.handle = zmq_ctx_new() |
| + else: |
| + self.handle = zmq_init(io_threads) |
| + |
| + if self.handle == NULL: |
| + raise ZMQError() |
| + |
| + cdef int rc = 0 |
| + if ZMQ_VERSION_MAJOR >= 3: |
| + rc = zmq_ctx_set(self.handle, ZMQ_IO_THREADS, io_threads) |
| + _check_rc(rc) |
| + |
| + self.closed = False |
| + self._n_sockets = 0 |
| + self._max_sockets = 32 |
| + |
| + self._sockets = <void **>malloc(self._max_sockets*sizeof(void *)) |
| + if self._sockets == NULL: |
| + raise MemoryError("Could not allocate _sockets array") |
| + |
| + self._pid = getpid() |
| + |
| + def __init__(self, io_threads=1): |
| + # no-op |
| + pass |
| + |
| + |
| + def __del__(self): |
| + """deleting a Context should terminate it, without trying non-threadsafe destroy""" |
| + self.term() |
| + |
| + def __dealloc__(self): |
| + """don't touch members in dealloc, just cleanup allocations""" |
| + cdef int rc |
| + if self._sockets != NULL: |
| + free(self._sockets) |
| + self._sockets = NULL |
| + self._n_sockets = 0 |
| + self.term() |
| + |
| + cdef inline void _add_socket(self, void* handle): |
| + """Add a socket handle to be closed when Context terminates. |
| + |
| + This is to be called in the Socket constructor. |
| + """ |
| + # print self._n_sockets, self._max_sockets |
| + if self._n_sockets >= self._max_sockets: |
| + self._max_sockets *= 2 |
| + self._sockets = <void **>realloc(self._sockets, self._max_sockets*sizeof(void *)) |
| + if self._sockets == NULL: |
| + raise MemoryError("Could not reallocate _sockets array") |
| + |
| + self._sockets[self._n_sockets] = handle |
| + self._n_sockets += 1 |
| + # print self._n_sockets, self._max_sockets |
| + |
| + cdef inline void _remove_socket(self, void* handle): |
| + """Remove a socket from the collected handles. |
| + |
| + This should be called by Socket.close, to prevent trying to |
| + close a socket a second time. |
| + """ |
| + cdef bint found = False |
| + |
| + for idx in range(self._n_sockets): |
| + if self._sockets[idx] == handle: |
| + found=True |
| + break |
| + |
| + if found: |
| + self._n_sockets -= 1 |
| + if self._n_sockets: |
| + # move last handle to closed socket's index |
| + self._sockets[idx] = self._sockets[self._n_sockets] |
| + |
| + @property |
| + def _handle(self): |
| + return <Py_ssize_t> self.handle |
| + |
| + def term(self): |
| + """ctx.term() |
| + |
| + Close or terminate the context. |
| + |
| + This can be called to close the context by hand. If this is not called, |
| + the context will automatically be closed when it is garbage collected. |
| + """ |
| + cdef int rc |
| + cdef int i=-1 |
| + |
| + if self.handle != NULL and not self.closed and getpid() == self._pid: |
| + with nogil: |
| + rc = zmq_ctx_destroy(self.handle) |
| + _check_rc(rc) |
| + self.handle = NULL |
| + self.closed = True |
| + |
| + def set(self, int option, optval): |
| + """ctx.set(option, optval) |
| + |
| + Set context options. |
| + |
| + See the 0MQ API documentation for zmq_ctx_set |
| + for details on specific options. |
| + |
| + New in libzmq-3.2 |
| + |
| + Parameters |
| + ---------- |
| + option : int |
| + The option to set. Available values will depend on your |
| + version of libzmq. Examples include:: |
| + |
| + zmq.IO_THREADS, zmq.MAX_SOCKETS |
| + |
| + optval : int |
| + The value of the option to set. |
| + """ |
| + cdef int optval_int_c |
| + cdef int rc |
| + cdef char* optval_c |
| + |
| + if self.closed: |
| + raise RuntimeError("Context has been destroyed") |
| + |
| + if not isinstance(optval, int): |
| + raise TypeError('expected int, got: %r' % optval) |
| + optval_int_c = optval |
| + rc = zmq_ctx_set(self.handle, option, optval_int_c) |
| + _check_rc(rc) |
| + |
| + def get(self, int option): |
| + """ctx.get(option) |
| + |
| + Get the value of a context option. |
| + |
| + See the 0MQ API documentation for zmq_ctx_get |
| + for details on specific options. |
| + |
| + New in libzmq-3.2 |
| + |
| + Parameters |
| + ---------- |
| + option : int |
| + The option to get. Available values will depend on your |
| + version of libzmq. Examples include:: |
| + |
| + zmq.IO_THREADS, zmq.MAX_SOCKETS |
| + |
| + Returns |
| + ------- |
| + optval : int |
| + The value of the option as an integer. |
| + """ |
| + cdef int optval_int_c |
| + cdef size_t sz |
| + cdef int rc |
| + |
| + if self.closed: |
| + raise RuntimeError("Context has been destroyed") |
| + |
| + rc = zmq_ctx_get(self.handle, option) |
| + _check_rc(rc) |
| + |
| + return rc |
| + |
| + def destroy(self, linger=None): |
| + """ctx.destroy(linger=None) |
| + |
| + Close all sockets associated with this context, and then terminate |
| + the context. If linger is specified, |
| + the LINGER sockopt of the sockets will be set prior to closing. |
| + |
| + WARNING: |
| + |
| + destroy involves calling zmq_close(), which is *NOT* threadsafe. |
| + If there are active sockets in other threads, this must not be called. |
| + """ |
| + |
| + cdef int linger_c |
| + cdef bint setlinger=False |
| + |
| + if linger is not None: |
| + linger_c = linger |
| + setlinger=True |
| + if self.handle != NULL and not self.closed and self._n_sockets: |
| + while self._n_sockets: |
| + if setlinger: |
| + zmq_setsockopt(self._sockets[0], ZMQ_LINGER, &linger_c, sizeof(int)) |
| + rc = zmq_close(self._sockets[0]) |
| + if rc < 0 and zmq_errno() != ZMQ_ENOTSOCK: |
| + raise ZMQError() |
| + self._n_sockets -= 1 |
| + self._sockets[0] = self._sockets[self._n_sockets] |
| + self.term() |
| + |
| +__all__ = ['Context'] |
| diff --git a/zmq/core/_zerror.pyx b/zmq/core/_zerror.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zerror.pyx |
| @@ -0,0 +1,56 @@ |
| +"""0MQ Error classes and functions.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +# allow const char* |
| +cdef extern from *: |
| + ctypedef char* const_char_ptr "const char*" |
| + |
| +from libzmq cimport zmq_strerror, zmq_errno as zmq_errno_c |
| + |
| +from zmq.utils.strtypes import bytes |
| + |
| +def strerror(int errno): |
| + """strerror(errno) |
| + |
| + Return the error string given the error number. |
| + """ |
| + cdef const_char_ptr str_e |
| + # char * will be a bytes object: |
| + str_e = zmq_strerror(errno) |
| + if str is bytes: |
| + # Python 2: str is bytes, so we already have the right type |
| + return str_e |
| + else: |
| + # Python 3: decode bytes to unicode str |
| + return str_e.decode() |
| + |
| +def zmq_errno(): |
| + """zmq_errno() |
| + |
| + Return the integer errno of the most recent zmq error. |
| + """ |
| + return zmq_errno_c() |
| + |
| +__all__ = ['strerror', 'zmq_errno'] |
| diff --git a/zmq/core/_zmessage.pxd b/zmq/core/_zmessage.pxd |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zmessage.pxd |
| @@ -0,0 +1,66 @@ |
| +"""0MQ Message related class declarations.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from cpython cimport PyBytes_FromStringAndSize |
| + |
| +from libzmq cimport zmq_msg_t, zmq_msg_data, zmq_msg_size |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| +cdef class MessageTracker(object): |
| + """A class for tracking if 0MQ is done using one or more messages.""" |
| + |
| + cdef set events # Message Event objects to track. |
| + cdef set peers # Other Message or MessageTracker objects. |
| + |
| + |
| +cdef class Frame: |
| + """A Message Frame class for non-copy send/recvs.""" |
| + |
| + cdef zmq_msg_t zmq_msg |
| + cdef object _data # The actual message data as a Python object. |
| + cdef object _buffer # A Python Buffer/View of the message contents |
| + cdef object _bytes # A bytes/str copy of the message. |
| + cdef bint _failed_init # Flag to handle failed zmq_msg_init |
| + cdef public object tracker_event # Event for use with zmq_free_fn. |
| + cdef public object tracker # MessageTracker object. |
| + cdef public bint more # whether RCVMORE was set |
| + |
| + cdef Frame fast_copy(self) # Create shallow copy of Message object. |
| + cdef object _getbuffer(self) # Construct self._buffer. |
| + |
| + |
| +cdef inline object copy_zmq_msg_bytes(zmq_msg_t *zmq_msg): |
| + """ Copy the data from a zmq_msg_t """ |
| + cdef char *data_c = NULL |
| + cdef Py_ssize_t data_len_c |
| + with nogil: |
| + data_c = <char *>zmq_msg_data(zmq_msg) |
| + data_len_c = zmq_msg_size(zmq_msg) |
| + return PyBytes_FromStringAndSize(data_c, data_len_c) |
| + |
| + |
| diff --git a/zmq/core/_zmessage.pyx b/zmq/core/_zmessage.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zmessage.pyx |
| @@ -0,0 +1,297 @@ |
| +"""0MQ Message related classes.""" |
| + |
| +# |
| +# Copyright (c) 2013 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +# get version-independent aliases: |
| +cdef extern from "pyversion_compat.h": |
| + pass |
| + |
| +from cpython cimport Py_DECREF, Py_INCREF |
| + |
| +from buffers cimport asbuffer_r, viewfromobject_r |
| + |
| +cdef extern from "Python.h": |
| + ctypedef int Py_ssize_t |
| + |
| +from libzmq cimport * |
| + |
| +import time |
| + |
| +try: |
| + # below 3.3 |
| + from threading import _Event as Event |
| +except (ImportError, AttributeError): |
| + # python throws ImportError, cython throws AttributeError |
| + from threading import Event |
| + |
| +import zmq |
| +from zmq.core.checkrc cimport _check_rc |
| +from zmq.utils.strtypes import bytes,unicode,basestring |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| + |
| +cdef void free_python_msg(void *data, void *hint) with gil: |
| + """A function for DECREF'ing Python based messages.""" |
| + if hint != NULL: |
| + tracker_event = (<tuple>hint)[1] |
| + Py_DECREF(<object>hint) |
| + if isinstance(tracker_event, Event): |
| + # don't assert before DECREF: |
| + # assert tracker_queue.empty(), "somebody else wrote to my Queue!" |
| + tracker_event.set() |
| + tracker_event = None |
| + |
| + |
| +cdef class Frame: |
| + """Frame(data=None, track=False) |
| + |
| + A zmq message Frame class for non-copy send/recvs. |
| + |
| + This class is only needed if you want to do non-copying send and recvs. |
| + When you pass a string to this class, like ``Frame(s)``, the |
| + ref-count of `s` is increased by two: once because the Frame saves `s` as |
| + an instance attribute and another because a ZMQ message is created that |
| + points to the buffer of `s`. This second ref-count increase makes sure |
| + that `s` lives until all messages that use it have been sent. Once 0MQ |
| + sends all the messages and it doesn't need the buffer of s, 0MQ will call |
| + ``Py_DECREF(s)``. |
| + |
| + Parameters |
| + ---------- |
| + |
| + data : object, optional |
| + any object that provides the buffer interface will be used to |
| + construct the 0MQ message data. |
| + track : bool [default: False] |
| + whether a MessageTracker_ should be created to track this object. |
| + Tracking a message has a cost at creation, because it creates a threadsafe |
| + Event object. |
| + |
| + """ |
| + |
| + def __cinit__(self, object data=None, track=False, **kwargs): |
| + cdef int rc |
| + cdef char *data_c = NULL |
| + cdef Py_ssize_t data_len_c=0 |
| + cdef object hint |
| + |
| + # init more as False |
| + self.more = False |
| + |
| + # Save the data object in case the user wants the the data as a str. |
| + self._data = data |
| + self._failed_init = True # bool switch for dealloc |
| + self._buffer = None # buffer view of data |
| + self._bytes = None # bytes copy of data |
| + |
| + # Event and MessageTracker for monitoring when zmq is done with data: |
| + if track: |
| + evt = Event() |
| + self.tracker_event = evt |
| + self.tracker = zmq.MessageTracker(evt) |
| + else: |
| + self.tracker_event = None |
| + self.tracker = None |
| + |
| + if isinstance(data, unicode): |
| + raise TypeError("Unicode objects not allowed. Only: str/bytes, buffer interfaces.") |
| + |
| + if data is None: |
| + with nogil: |
| + rc = zmq_msg_init(&self.zmq_msg) |
| + _check_rc(rc) |
| + self._failed_init = False |
| + return |
| + else: |
| + asbuffer_r(data, <void **>&data_c, &data_len_c) |
| + # We INCREF the *original* Python object (not self) and pass it |
| + # as the hint below. This allows other copies of this Frame |
| + # object to take over the ref counting of data properly. |
| + hint = (data, self.tracker_event) |
| + Py_INCREF(hint) |
| + with nogil: |
| + rc = zmq_msg_init_data( |
| + &self.zmq_msg, <void *>data_c, data_len_c, |
| + <zmq_free_fn *>free_python_msg, <void *>hint |
| + ) |
| + if rc != 0: |
| + Py_DECREF(hint) |
| + _check_rc(rc) |
| + self._failed_init = False |
| + |
| + def __init__(self, object data=None, track=False): |
| + """Enforce signature""" |
| + pass |
| + |
| + def __dealloc__(self): |
| + cdef int rc |
| + if self._failed_init: |
| + return |
| + # This simply decreases the 0MQ ref-count of zmq_msg. |
| + with nogil: |
| + rc = zmq_msg_close(&self.zmq_msg) |
| + _check_rc(rc) |
| + |
| + # buffer interface code adapted from petsc4py by Lisandro Dalcin, a BSD project |
| + |
| + def __getbuffer__(self, Py_buffer* buffer, int flags): |
| + # new-style (memoryview) buffer interface |
| + with nogil: |
| + buffer.buf = zmq_msg_data(&self.zmq_msg) |
| + buffer.len = zmq_msg_size(&self.zmq_msg) |
| + |
| + buffer.obj = self |
| + buffer.readonly = 1 |
| + buffer.format = "B" |
| + buffer.ndim = 0 |
| + buffer.shape = NULL |
| + buffer.strides = NULL |
| + buffer.suboffsets = NULL |
| + buffer.itemsize = 1 |
| + buffer.internal = NULL |
| + |
| + def __getsegcount__(self, Py_ssize_t *lenp): |
| + # required for getreadbuffer |
| + if lenp != NULL: |
| + with nogil: |
| + lenp[0] = zmq_msg_size(&self.zmq_msg) |
| + return 1 |
| + |
| + def __getreadbuffer__(self, Py_ssize_t idx, void **p): |
| + # old-style (buffer) interface |
| + cdef char *data_c = NULL |
| + cdef Py_ssize_t data_len_c |
| + if idx != 0: |
| + raise SystemError("accessing non-existent buffer segment") |
| + # read-only, because we don't want to allow |
| + # editing of the message in-place |
| + with nogil: |
| + data_c = <char *>zmq_msg_data(&self.zmq_msg) |
| + data_len_c = zmq_msg_size(&self.zmq_msg) |
| + if p != NULL: |
| + p[0] = <void*>data_c |
| + return data_len_c |
| + |
| + # end buffer interface |
| + |
| + def __copy__(self): |
| + """Create a shallow copy of the message. |
| + |
| + This does not copy the contents of the Frame, just the pointer. |
| + This will increment the 0MQ ref count of the message, but not |
| + the ref count of the Python object. That is only done once when |
| + the Python is first turned into a 0MQ message. |
| + """ |
| + return self.fast_copy() |
| + |
| + cdef Frame fast_copy(self): |
| + """Fast, cdef'd version of shallow copy of the Frame.""" |
| + cdef Frame new_msg |
| + new_msg = Frame() |
| + # This does not copy the contents, but just increases the ref-count |
| + # of the zmq_msg by one. |
| + with nogil: |
| + zmq_msg_copy(&new_msg.zmq_msg, &self.zmq_msg) |
| + # Copy the ref to data so the copy won't create a copy when str is |
| + # called. |
| + if self._data is not None: |
| + new_msg._data = self._data |
| + if self._buffer is not None: |
| + new_msg._buffer = self._buffer |
| + if self._bytes is not None: |
| + new_msg._bytes = self._bytes |
| + |
| + # Frame copies share the tracker and tracker_event |
| + new_msg.tracker_event = self.tracker_event |
| + new_msg.tracker = self.tracker |
| + |
| + return new_msg |
| + |
| + def __len__(self): |
| + """Return the length of the message in bytes.""" |
| + cdef size_t sz |
| + with nogil: |
| + sz = zmq_msg_size(&self.zmq_msg) |
| + return sz |
| + # return <int>zmq_msg_size(&self.zmq_msg) |
| + |
| + def __str__(self): |
| + """Return the str form of the message.""" |
| + if isinstance(self._data, bytes): |
| + b = self._data |
| + else: |
| + b = self.bytes |
| + if str is unicode: |
| + return b.decode() |
| + else: |
| + return b |
| + |
| + cdef inline object _getbuffer(self): |
| + """Create a Python buffer/view of the message data. |
| + |
| + This will be called only once, the first time the `buffer` property |
| + is accessed. Subsequent calls use a cached copy. |
| + """ |
| + if self._data is None: |
| + return viewfromobject_r(self) |
| + else: |
| + return viewfromobject_r(self._data) |
| + |
| + @property |
| + def buffer(self): |
| + """Get a read-only buffer view of the message contents.""" |
| + if self._buffer is None: |
| + self._buffer = self._getbuffer() |
| + return self._buffer |
| + |
| + @property |
| + def bytes(self): |
| + """Get the message content as a Python str/bytes object. |
| + |
| + The first time this property is accessed, a copy of the message |
| + contents is made. From then on that same copy of the message is |
| + returned. |
| + """ |
| + if self._bytes is None: |
| + self._bytes = copy_zmq_msg_bytes(&self.zmq_msg) |
| + return self._bytes |
| + |
| + def set(self, int option, int value): |
| + """Set a message property""" |
| + cdef int rc = zmq_msg_set(&self.zmq_msg, option, value) |
| + _check_rc(rc) |
| + |
| + def get(self, int option): |
| + """Get a message property""" |
| + cdef int rc = zmq_msg_get(&self.zmq_msg, option) |
| + _check_rc(rc) |
| + return rc |
| + |
| +# legacy Message name |
| +Message = Frame |
| + |
| +__all__ = ['Frame', 'Message'] |
| diff --git a/zmq/core/_zsocket.pxd b/zmq/core/_zsocket.pxd |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zsocket.pxd |
| @@ -0,0 +1,48 @@ |
| +"""0MQ Socket class declaration.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from _zcontext cimport Context |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| + |
| +cdef class Socket: |
| + """A 0MQ socket.""" |
| + |
| + cdef object __weakref__ # enable weakref |
| + cdef void *handle # The C handle for the underlying zmq object. |
| + cdef public int socket_type # The 0MQ socket type - REQ,REP, etc. |
| + # Hold on to a reference to the context to make sure it is not garbage |
| + # collected until the socket it done with it. |
| + cdef public Context context # The zmq Context object that owns this. |
| + cdef public bint _closed # bool property for a closed socket. |
| + cdef int _pid # the pid of the process which created me (for fork safety) |
| + |
| + # cpdef methods for direct-cython access: |
| + cpdef object send(self, object data, int flags=*, copy=*, track=*) |
| + cpdef object recv(self, int flags=*, copy=*, track=*) |
| + |
| diff --git a/zmq/core/_zsocket.pyx b/zmq/core/_zsocket.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zsocket.pyx |
| @@ -0,0 +1,628 @@ |
| +"""0MQ Socket class.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Cython Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +# get version-independent aliases: |
| +cdef extern from "pyversion_compat.h": |
| + pass |
| + |
| +from libc.errno cimport ENAMETOOLONG |
| +from libc.string cimport memcpy |
| + |
| +from cpython cimport PyBytes_FromStringAndSize |
| +from cpython cimport PyBytes_AsString, PyBytes_Size |
| +from cpython cimport Py_DECREF, Py_INCREF |
| + |
| +from buffers cimport asbuffer_r, viewfromobject_r |
| + |
| +from libzmq cimport * |
| +from _zmessage cimport Frame, copy_zmq_msg_bytes |
| + |
| +from _zcontext cimport Context |
| + |
| +cdef extern from "Python.h": |
| + ctypedef int Py_ssize_t |
| + |
| +cdef extern from "ipcmaxlen.h": |
| + int get_ipc_path_max_len() |
| + |
| +cdef extern from "getpid_compat.h": |
| + int getpid() |
| + |
| + |
| +#----------------------------------------------------------------------------- |
| +# Python Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +import copy as copy_mod |
| +import time |
| +import sys |
| +import random |
| +import struct |
| +import codecs |
| + |
| +from zmq.utils import jsonapi |
| + |
| +try: |
| + import cPickle |
| + pickle = cPickle |
| +except: |
| + cPickle = None |
| + import pickle |
| + |
| +import zmq |
| +from zmq.core import _zconstants as constants |
| +from zmq.core._zconstants import * |
| +from zmq.core.checkrc cimport _check_rc |
| +from zmq.error import ZMQError, ZMQBindError |
| +from zmq.utils.strtypes import bytes,unicode,basestring |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| +IPC_PATH_MAX_LEN = get_ipc_path_max_len() |
| + |
| +# inline some small socket submethods: |
| +# true methods frequently cannot be inlined, acc. Cython docs |
| + |
| +cdef inline _check_closed(Socket s, bint raise_notsup): |
| + cdef int rc |
| + cdef int errno |
| + cdef int stype |
| + cdef size_t sz=sizeof(int) |
| + if s._closed: |
| + if raise_notsup: |
| + raise ZMQError(ENOTSUP) |
| + else: |
| + return True |
| + else: |
| + rc = zmq_getsockopt(s.handle, ZMQ_TYPE, <void *>&stype, &sz) |
| + if rc < 0 and zmq_errno() == ENOTSOCK: |
| + s._closed = True |
| + if raise_notsup: |
| + raise ZMQError(ENOTSUP) |
| + else: |
| + return True |
| + else: |
| + _check_rc(rc) |
| + return False |
| + |
| +cdef inline Frame _recv_frame(void *handle, int flags=0, track=False): |
| + """Receive a message in a non-copying manner and return a Frame.""" |
| + cdef int rc |
| + cdef Frame msg |
| + msg = Frame(track=track) |
| + |
| + with nogil: |
| + rc = zmq_msg_recv(&msg.zmq_msg, handle, flags) |
| + |
| + _check_rc(rc) |
| + return msg |
| + |
| +cdef inline object _recv_copy(void *handle, int flags=0): |
| + """Receive a message and return a copy""" |
| + cdef zmq_msg_t zmq_msg |
| + with nogil: |
| + zmq_msg_init (&zmq_msg) |
| + rc = zmq_msg_recv(&zmq_msg, handle, flags) |
| + _check_rc(rc) |
| + msg_bytes = copy_zmq_msg_bytes(&zmq_msg) |
| + with nogil: |
| + zmq_msg_close(&zmq_msg) |
| + return msg_bytes |
| + |
| +cdef inline object _send_frame(void *handle, Frame msg, int flags=0): |
| + """Send a Frame on this socket in a non-copy manner.""" |
| + cdef int rc |
| + cdef Frame msg_copy |
| + |
| + # Always copy so the original message isn't garbage collected. |
| + # This doesn't do a real copy, just a reference. |
| + msg_copy = msg.fast_copy() |
| + |
| + with nogil: |
| + rc = zmq_msg_send(&msg_copy.zmq_msg, handle, flags) |
| + |
| + _check_rc(rc) |
| + return msg.tracker |
| + |
| + |
| +cdef inline object _send_copy(void *handle, object msg, int flags=0): |
| + """Send a message on this socket by copying its content.""" |
| + cdef int rc, rc2 |
| + cdef zmq_msg_t data |
| + cdef char *msg_c |
| + cdef Py_ssize_t msg_c_len=0 |
| + |
| + # copy to c array: |
| + asbuffer_r(msg, <void **>&msg_c, &msg_c_len) |
| + |
| + # Copy the msg before sending. This avoids any complications with |
| + # the GIL, etc. |
| + # If zmq_msg_init_* fails we must not call zmq_msg_close (Bus Error) |
| + with nogil: |
| + rc = zmq_msg_init_size(&data, msg_c_len) |
| + |
| + _check_rc(rc) |
| + |
| + with nogil: |
| + memcpy(zmq_msg_data(&data), msg_c, zmq_msg_size(&data)) |
| + rc = zmq_msg_send(&data, handle, flags) |
| + rc2 = zmq_msg_close(&data) |
| + _check_rc(rc) |
| + _check_rc(rc2) |
| + |
| + |
| +cdef class Socket: |
| + """Socket(context, socket_type) |
| + |
| + A 0MQ socket. |
| + |
| + These objects will generally be constructed via the socket() method of a Context object. |
| + |
| + Note: 0MQ Sockets are *not* threadsafe. **DO NOT** share them across threads. |
| + |
| + Parameters |
| + ---------- |
| + context : Context |
| + The 0MQ Context this Socket belongs to. |
| + socket_type : int |
| + The socket type, which can be any of the 0MQ socket types: |
| + REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB. |
| + |
| + See Also |
| + -------- |
| + .Context.socket : method for creating a socket bound to a Context. |
| + """ |
| + |
| + def __cinit__(self, Context context, int socket_type, *args, **kwrags): |
| + cdef Py_ssize_t c_handle |
| + c_handle = context._handle |
| + |
| + self.handle = NULL |
| + self.context = context |
| + self.socket_type = socket_type |
| + with nogil: |
| + self.handle = zmq_socket(<void *>c_handle, socket_type) |
| + if self.handle == NULL: |
| + raise ZMQError() |
| + self._closed = False |
| + self._pid = getpid() |
| + context._add_socket(self.handle) |
| + |
| + def __dealloc__(self): |
| + """close *and* remove from context's list |
| + |
| + But be careful that context might not exist if called during gc |
| + """ |
| + if self.handle != NULL and getpid() == self._pid: |
| + rc = zmq_close(self.handle) |
| + if rc != 0 and zmq_errno() != ENOTSOCK: |
| + # ignore ENOTSOCK (closed by Context) |
| + _check_rc(rc) |
| + # during gc, self.context might be NULL |
| + if self.context: |
| + self.context._remove_socket(self.handle) |
| + |
| + def __init__(self, context, socket_type): |
| + pass |
| + |
| + @property |
| + def closed(self): |
| + return _check_closed(self, False) |
| + |
| + def close(self, linger=None): |
| + """s.close(linger=None) |
| + |
| + Close the socket. |
| + |
| + If linger is specified, LINGER sockopt will be set prior to closing. |
| + |
| + This can be called to close the socket by hand. If this is not |
| + called, the socket will automatically be closed when it is |
| + garbage collected. |
| + """ |
| + cdef int rc=0 |
| + cdef int linger_c |
| + cdef bint setlinger=False |
| + |
| + if linger is not None: |
| + linger_c = linger |
| + setlinger=True |
| + |
| + if self.handle != NULL and not self._closed and getpid() == self._pid: |
| + if setlinger: |
| + zmq_setsockopt(self.handle, ZMQ_LINGER, &linger_c, sizeof(int)) |
| + rc = zmq_close(self.handle) |
| + if rc != 0 and zmq_errno() != ENOTSOCK: |
| + # ignore ENOTSOCK (closed by Context) |
| + _check_rc(rc) |
| + self._closed = True |
| + # during gc, self.context might be NULL |
| + if self.context: |
| + self.context._remove_socket(self.handle) |
| + self.handle = NULL |
| + |
| + def set(self, int option, optval): |
| + """s.set(option, optval) |
| + |
| + Set socket options. |
| + |
| + See the 0MQ API documentation for details on specific options. |
| + |
| + Parameters |
| + ---------- |
| + option : int |
| + The option to set. Available values will depend on your |
| + version of libzmq. Examples include:: |
| + |
| + zmq.SUBSCRIBE, UNSUBSCRIBE, IDENTITY, HWM, LINGER, FD |
| + |
| + optval : int or bytes |
| + The value of the option to set. |
| + """ |
| + cdef int64_t optval_int64_c |
| + cdef int optval_int_c |
| + cdef int rc |
| + cdef char* optval_c |
| + cdef Py_ssize_t sz |
| + |
| + _check_closed(self, True) |
| + if isinstance(optval, unicode): |
| + raise TypeError("unicode not allowed, use setsockopt_string") |
| + |
| + if option in zmq.constants.bytes_sockopts: |
| + if not isinstance(optval, bytes): |
| + raise TypeError('expected bytes, got: %r' % optval) |
| + optval_c = PyBytes_AsString(optval) |
| + sz = PyBytes_Size(optval) |
| + with nogil: |
| + rc = zmq_setsockopt( |
| + self.handle, option, |
| + optval_c, sz |
| + ) |
| + elif option in zmq.constants.int64_sockopts: |
| + if not isinstance(optval, int): |
| + raise TypeError('expected int, got: %r' % optval) |
| + optval_int64_c = optval |
| + with nogil: |
| + rc = zmq_setsockopt( |
| + self.handle, option, |
| + &optval_int64_c, sizeof(int64_t) |
| + ) |
| + else: |
| + # default is to assume int, which is what most new sockopts will be |
| + # this lets pyzmq work with newer libzmq which may add constants |
| + # pyzmq has not yet added, rather than artificially raising. Invalid |
| + # sockopts will still raise just the same, but it will be libzmq doing |
| + # the raising. |
| + if not isinstance(optval, int): |
| + raise TypeError('expected int, got: %r' % optval) |
| + optval_int_c = optval |
| + with nogil: |
| + rc = zmq_setsockopt( |
| + self.handle, option, |
| + &optval_int_c, sizeof(int) |
| + ) |
| + |
| + _check_rc(rc) |
| + |
| + def get(self, int option): |
| + """s.get(option) |
| + |
| + Get the value of a socket option. |
| + |
| + See the 0MQ API documentation for details on specific options. |
| + |
| + Parameters |
| + ---------- |
| + option : int |
| + The option to get. Available values will depend on your |
| + version of libzmq. Examples include:: |
| + |
| + zmq.IDENTITY, HWM, LINGER, FD, EVENTS |
| + |
| + Returns |
| + ------- |
| + optval : int or bytes |
| + The value of the option as a bytestring or int. |
| + """ |
| + cdef int64_t optval_int64_c |
| + cdef int optval_int_c |
| + cdef fd_t optval_fd_c |
| + cdef char identity_str_c [255] |
| + cdef size_t sz |
| + cdef int rc |
| + |
| + _check_closed(self, True) |
| + |
| + if option in zmq.constants.bytes_sockopts: |
| + sz = 255 |
| + with nogil: |
| + rc = zmq_getsockopt(self.handle, option, <void *>identity_str_c, &sz) |
| + _check_rc(rc) |
| + result = PyBytes_FromStringAndSize(<char *>identity_str_c, sz) |
| + elif option in zmq.constants.int64_sockopts: |
| + sz = sizeof(int64_t) |
| + with nogil: |
| + rc = zmq_getsockopt(self.handle, option, <void *>&optval_int64_c, &sz) |
| + _check_rc(rc) |
| + result = optval_int64_c |
| + elif option == ZMQ_FD: |
| + sz = sizeof(fd_t) |
| + with nogil: |
| + rc = zmq_getsockopt(self.handle, option, <void *>&optval_fd_c, &sz) |
| + _check_rc(rc) |
| + result = optval_fd_c |
| + else: |
| + # default is to assume int, which is what most new sockopts will be |
| + # this lets pyzmq work with newer libzmq which may add constants |
| + # pyzmq has not yet added, rather than artificially raising. Invalid |
| + # sockopts will still raise just the same, but it will be libzmq doing |
| + # the raising. |
| + sz = sizeof(int) |
| + with nogil: |
| + rc = zmq_getsockopt(self.handle, option, <void *>&optval_int_c, &sz) |
| + _check_rc(rc) |
| + result = optval_int_c |
| + |
| + return result |
| + |
| + def bind(self, addr): |
| + """s.bind(addr) |
| + |
| + Bind the socket to an address. |
| + |
| + This causes the socket to listen on a network port. Sockets on the |
| + other side of this connection will use ``Socket.connect(addr)`` to |
| + connect to this socket. |
| + |
| + Parameters |
| + ---------- |
| + addr : str |
| + The address string. This has the form 'protocol://interface:port', |
| + for example 'tcp://127.0.0.1:5555'. Protocols supported include |
| + tcp, udp, pgm, epgm, inproc and ipc. If the address is unicode, it is |
| + encoded to utf-8 first. |
| + """ |
| + cdef int rc |
| + cdef char* c_addr |
| + |
| + _check_closed(self, True) |
| + if isinstance(addr, unicode): |
| + addr = addr.encode('utf-8') |
| + if not isinstance(addr, bytes): |
| + raise TypeError('expected str, got: %r' % addr) |
| + c_addr = addr |
| + rc = zmq_bind(self.handle, c_addr) |
| + if rc != 0: |
| + if IPC_PATH_MAX_LEN and zmq_errno() == ENAMETOOLONG: |
| + # py3compat: addr is bytes, but msg wants str |
| + if str is unicode: |
| + addr = addr.decode('utf-8', 'replace') |
| + path = addr.split('://', 1)[-1] |
| + msg = ('ipc path "{0}" is longer than {1} ' |
| + 'characters (sizeof(sockaddr_un.sun_path)). ' |
| + 'zmq.IPC_PATH_MAX_LEN constant can be used ' |
| + 'to check addr length (if it is defined).' |
| + .format(path, IPC_PATH_MAX_LEN)) |
| + raise ZMQError(msg=msg) |
| + _check_rc(rc) |
| + |
| + def connect(self, addr): |
| + """s.connect(addr) |
| + |
| + Connect to a remote 0MQ socket. |
| + |
| + Parameters |
| + ---------- |
| + addr : str |
| + The address string. This has the form 'protocol://interface:port', |
| + for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| + tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| + encoded to utf-8 first. |
| + """ |
| + cdef int rc |
| + cdef char* c_addr |
| + |
| + _check_closed(self, True) |
| + if isinstance(addr, unicode): |
| + addr = addr.encode('utf-8') |
| + if not isinstance(addr, bytes): |
| + raise TypeError('expected str, got: %r' % addr) |
| + c_addr = addr |
| + |
| + rc = zmq_connect(self.handle, c_addr) |
| + if rc != 0: |
| + raise ZMQError() |
| + |
| + def unbind(self, addr): |
| + """s.unbind(addr) |
| + |
| + Unbind from an address (undoes a call to bind). |
| + |
| + This feature requires libzmq-3 |
| + |
| + Parameters |
| + ---------- |
| + addr : str |
| + The address string. This has the form 'protocol://interface:port', |
| + for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| + tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| + encoded to utf-8 first. |
| + """ |
| + cdef int rc |
| + cdef char* c_addr |
| + |
| + if ZMQ_VERSION_MAJOR < 3: |
| + raise NotImplementedError("unbind requires libzmq >= 3.0, have %s" % zmq.zmq_version()) |
| + |
| + |
| + _check_closed(self, True) |
| + if isinstance(addr, unicode): |
| + addr = addr.encode('utf-8') |
| + if not isinstance(addr, bytes): |
| + raise TypeError('expected str, got: %r' % addr) |
| + c_addr = addr |
| + |
| + rc = zmq_unbind(self.handle, c_addr) |
| + if rc != 0: |
| + raise ZMQError() |
| + |
| + def disconnect(self, addr): |
| + """s.disconnect(addr) |
| + |
| + Disconnect from a remote 0MQ socket (undoes a call to connect). |
| + |
| + This feature requires libzmq-3 |
| + |
| + Parameters |
| + ---------- |
| + addr : str |
| + The address string. This has the form 'protocol://interface:port', |
| + for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| + tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| + encoded to utf-8 first. |
| + """ |
| + cdef int rc |
| + cdef char* c_addr |
| + |
| + if ZMQ_VERSION_MAJOR < 3: |
| + raise NotImplementedError("disconnect requires libzmq >= 3.0, have %s" % zmq.zmq_version()) |
| + |
| + _check_closed(self, True) |
| + if isinstance(addr, unicode): |
| + addr = addr.encode('utf-8') |
| + if not isinstance(addr, bytes): |
| + raise TypeError('expected str, got: %r' % addr) |
| + c_addr = addr |
| + |
| + rc = zmq_disconnect(self.handle, c_addr) |
| + if rc != 0: |
| + raise ZMQError() |
| + |
| + #------------------------------------------------------------------------- |
| + # Sending and receiving messages |
| + #------------------------------------------------------------------------- |
| + |
| + cpdef object send(self, object data, int flags=0, copy=True, track=False): |
| + """s.send(data, flags=0, copy=True, track=False) |
| + |
| + Send a message on this socket. |
| + |
| + This queues the message to be sent by the IO thread at a later time. |
| + |
| + Parameters |
| + ---------- |
| + data : object, str, Frame |
| + The content of the message. |
| + flags : int |
| + Any supported flag: NOBLOCK, SNDMORE. |
| + copy : bool |
| + Should the message be sent in a copying or non-copying manner. |
| + track : bool |
| + Should the message be tracked for notification that ZMQ has |
| + finished with it? (ignored if copy=True) |
| + |
| + Returns |
| + ------- |
| + None : if `copy` or not track |
| + None if message was sent, raises an exception otherwise. |
| + MessageTracker : if track and not copy |
| + a MessageTracker object, whose `pending` property will |
| + be True until the send is completed. |
| + |
| + Raises |
| + ------ |
| + TypeError |
| + If a unicode object is passed |
| + ValueError |
| + If `track=True`, but an untracked Frame is passed. |
| + ZMQError |
| + If the send does not succeed for any reason. |
| + |
| + """ |
| + _check_closed(self, True) |
| + |
| + if isinstance(data, unicode): |
| + raise TypeError("unicode not allowed, use send_unicode") |
| + |
| + if copy: |
| + # msg.bytes never returns the input data object |
| + # it is always a copy, but always the same copy |
| + if isinstance(data, Frame): |
| + data = data.buffer |
| + return _send_copy(self.handle, data, flags) |
| + else: |
| + if isinstance(data, Frame): |
| + if track and not data.tracker: |
| + raise ValueError('Not a tracked message') |
| + msg = data |
| + else: |
| + msg = Frame(data, track=track) |
| + return _send_frame(self.handle, msg, flags) |
| + |
| + cpdef object recv(self, int flags=0, copy=True, track=False): |
| + """s.recv(flags=0, copy=True, track=False) |
| + |
| + Receive a message. |
| + |
| + Parameters |
| + ---------- |
| + flags : int |
| + Any supported flag: NOBLOCK. If NOBLOCK is set, this method |
| + will raise a ZMQError with EAGAIN if a message is not ready. |
| + If NOBLOCK is not set, then this method will block until a |
| + message arrives. |
| + copy : bool |
| + Should the message be received in a copying or non-copying manner? |
| + If False a Frame object is returned, if True a string copy of |
| + message is returned. |
| + track : bool |
| + Should the message be tracked for notification that ZMQ has |
| + finished with it? (ignored if copy=True) |
| + |
| + Returns |
| + ------- |
| + msg : bytes, Frame |
| + The received message frame. If `copy` is False, then it will be a Frame, |
| + otherwise it will be bytes. |
| + |
| + Raises |
| + ------ |
| + ZMQError |
| + for any of the reasons zmq_msg_recv might fail. |
| + """ |
| + _check_closed(self, True) |
| + |
| + if copy: |
| + return _recv_copy(self.handle, flags) |
| + else: |
| + frame = _recv_frame(self.handle, flags, track) |
| + frame.more = self.getsockopt(zmq.RCVMORE) |
| + return frame |
| + |
| + |
| +__all__ = ['Socket', 'IPC_PATH_MAX_LEN'] |
| diff --git a/zmq/core/_zstopwatch.pxd b/zmq/core/_zstopwatch.pxd |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zstopwatch.pxd |
| @@ -0,0 +1,31 @@ |
| +"""0MQ Stopwatch class declaration.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| + |
| +cdef class Stopwatch: |
| + """A simple stopwatch based on zmq_stopwatch_start/stop.""" |
| + |
| + cdef void *watch # The C handle for the underlying zmq object |
| + |
| diff --git a/zmq/core/_zstopwatch.pyx b/zmq/core/_zstopwatch.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/core/_zstopwatch.pyx |
| @@ -0,0 +1,90 @@ |
| +"""0MQ Stopwatch class.""" |
| + |
| +# |
| +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq. |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libzmq cimport zmq_stopwatch_start, zmq_stopwatch_stop, zmq_sleep |
| + |
| +from zmq.error import ZMQError |
| + |
| +#----------------------------------------------------------------------------- |
| +# Code |
| +#----------------------------------------------------------------------------- |
| + |
| +cdef class Stopwatch: |
| + """Stopwatch() |
| + |
| + A simple stopwatch based on zmq_stopwatch_start/stop. |
| + |
| + This class should be used for benchmarking and timing 0MQ code. |
| + """ |
| + |
| + def __cinit__(self): |
| + self.watch = NULL |
| + |
| + def __dealloc__(self): |
| + try: |
| + self.stop() |
| + except ZMQError: |
| + pass |
| + |
| + def start(self): |
| + """s.start() |
| + |
| + Start the stopwatch. |
| + """ |
| + if self.watch == NULL: |
| + with nogil: |
| + self.watch = zmq_stopwatch_start() |
| + else: |
| + raise ZMQError('Stopwatch is already runing.') |
| + |
| + def stop(self): |
| + """s.stop() |
| + |
| + Stop the stopwatch. |
| + |
| + Returns |
| + ------- |
| + t : unsigned long int |
| + the number of microseconds since ``start()`` was called. |
| + """ |
| + cdef unsigned long time |
| + if self.watch == NULL: |
| + raise ZMQError('Must start the Stopwatch before calling stop.') |
| + else: |
| + with nogil: |
| + time = zmq_stopwatch_stop(self.watch) |
| + self.watch = NULL |
| + return time |
| + |
| + def sleep(self, int seconds): |
| + """s.sleep(seconds) |
| + |
| + Sleep for an integer number of seconds. |
| + """ |
| + with nogil: |
| + zmq_sleep(seconds) |
| + |
| + |
| +__all__ = ['Stopwatch'] |
| diff --git a/zmq/core/constants.pyx b/zmq/core/constants.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/constants.pyx |
| +++ /dev/null |
| @@ -1,190 +0,0 @@ |
| -"""0MQ Constants.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libzmq cimport * |
| - |
| -#----------------------------------------------------------------------------- |
| -# Python module level constants |
| -#----------------------------------------------------------------------------- |
| - |
| -_optionals = [] |
| - |
| -if ZMQ_VERSION < 30000: |
| - # backport DONTWAIT as alias to NOBLOCK |
| - NOBLOCK = ZMQ_NOBLOCK |
| - DONTWAIT = ZMQ_NOBLOCK |
| -else: |
| - # keep NOBLOCK as alias for new DONTWAIT |
| - NOBLOCK = ZMQ_DONTWAIT |
| - DONTWAIT = ZMQ_DONTWAIT |
| - |
| -VERSION = ZMQ_VERSION |
| - |
| -# socket types |
| -PAIR = ZMQ_PAIR |
| -PUB = ZMQ_PUB |
| -SUB = ZMQ_SUB |
| -REQ = ZMQ_REQ |
| -REP = ZMQ_REP |
| -DEALER = ZMQ_DEALER |
| -ROUTER = ZMQ_ROUTER |
| -PULL = ZMQ_PULL |
| -PUSH = ZMQ_PUSH |
| -XPUB = ZMQ_XPUB |
| -XSUB = ZMQ_XSUB |
| - |
| -# keep deprecated aliases |
| -XREQ = DEALER |
| -XREP = ROUTER |
| -UPSTREAM = PULL |
| -DOWNSTREAM = PUSH |
| - |
| - |
| -# socket options |
| -AFFINITY = ZMQ_AFFINITY |
| -IDENTITY = ZMQ_IDENTITY |
| -SUBSCRIBE = ZMQ_SUBSCRIBE |
| -UNSUBSCRIBE = ZMQ_UNSUBSCRIBE |
| -RATE = ZMQ_RATE |
| -RECOVERY_IVL = ZMQ_RECOVERY_IVL |
| -RECONNECT_IVL_MAX = ZMQ_RECONNECT_IVL_MAX |
| -SNDBUF = ZMQ_SNDBUF |
| -RCVBUF = ZMQ_RCVBUF |
| -RCVMORE = ZMQ_RCVMORE |
| -SNDMORE = ZMQ_SNDMORE |
| -POLLIN = ZMQ_POLLIN |
| -POLLOUT = ZMQ_POLLOUT |
| -POLLERR = ZMQ_POLLERR |
| - |
| -STREAMER = ZMQ_STREAMER |
| -FORWARDER = ZMQ_FORWARDER |
| -QUEUE = ZMQ_QUEUE |
| - |
| -# sockopts new in 2.2.0 |
| -SNDTIMEO = ZMQ_SNDTIMEO |
| -RCVTIMEO = ZMQ_RCVTIMEO |
| - |
| -# sockopts removed in 3.0.0 |
| -HWM = ZMQ_HWM |
| -SWAP = ZMQ_SWAP |
| -MCAST_LOOP = ZMQ_MCAST_LOOP |
| -RECOVERY_IVL_MSEC = ZMQ_RECOVERY_IVL_MSEC |
| - |
| -# new in 3.x |
| -IO_THREADS = ZMQ_IO_THREADS |
| -MAX_SOCKETS = ZMQ_MAX_SOCKETS |
| - |
| -MORE = ZMQ_MORE |
| - |
| -MAXMSGSIZE = ZMQ_MAXMSGSIZE |
| -SNDHWM = ZMQ_SNDHWM |
| -RCVHWM = ZMQ_RCVHWM |
| -MULTICAST_HOPS = ZMQ_MULTICAST_HOPS |
| -IPV4ONLY = ZMQ_IPV4ONLY |
| -LAST_ENDPOINT = ZMQ_LAST_ENDPOINT |
| - |
| -ROUTER_MANDATORY = ZMQ_ROUTER_MANDATORY |
| -# aliases |
| -ROUTER_BEHAVIOR = ROUTER_MANDATORY |
| -FAIL_UNROUTABLE = ROUTER_MANDATORY |
| - |
| -TCP_KEEPALIVE = ZMQ_TCP_KEEPALIVE |
| -TCP_KEEPALIVE_CNT = ZMQ_TCP_KEEPALIVE_CNT |
| -TCP_KEEPALIVE_IDLE = ZMQ_TCP_KEEPALIVE_IDLE |
| -TCP_KEEPALIVE_INTVL = ZMQ_TCP_KEEPALIVE_INTVL |
| -TCP_ACCEPT_FILTER = ZMQ_TCP_ACCEPT_FILTER |
| -DELAY_ATTACH_ON_CONNECT = ZMQ_DELAY_ATTACH_ON_CONNECT |
| -XPUB_VERBOSE = ZMQ_XPUB_VERBOSE |
| -ROUTER_RAW = ZMQ_ROUTER_RAW |
| - |
| -EVENT_CONNECTED = ZMQ_EVENT_CONNECTED |
| -EVENT_CONNECT_DELAYED = ZMQ_EVENT_CONNECT_DELAYED |
| -EVENT_CONNECT_RETRIED = ZMQ_EVENT_CONNECT_RETRIED |
| -EVENT_LISTENING = ZMQ_EVENT_LISTENING |
| -EVENT_BIND_FAILED = ZMQ_EVENT_BIND_FAILED |
| -EVENT_ACCEPTED = ZMQ_EVENT_ACCEPTED |
| -EVENT_ACCEPT_FAILED = ZMQ_EVENT_ACCEPT_FAILED |
| -EVENT_CLOSED = ZMQ_EVENT_CLOSED |
| -EVENT_CLOSE_FAILED = ZMQ_EVENT_CLOSE_FAILED |
| -EVENT_DISCONNECTED = ZMQ_EVENT_DISCONNECTED |
| - |
| -FD = ZMQ_FD |
| -EVENTS = ZMQ_EVENTS |
| -TYPE = ZMQ_TYPE |
| -LINGER = ZMQ_LINGER |
| -RECONNECT_IVL = ZMQ_RECONNECT_IVL |
| -BACKLOG = ZMQ_BACKLOG |
| - |
| -# As new constants are added in future versions, add a new block here |
| -# like the two above, checking agains the relevant value for ZMQ_VERSION. |
| -# The constants will need to be added to libzmq.pxd and utils/zmq_compat.h |
| -# as well. |
| - |
| -#----------------------------------------------------------------------------- |
| -# Error handling |
| -#----------------------------------------------------------------------------- |
| - |
| -# Often used standard errnos |
| -from errno import ( |
| - EAGAIN, |
| - EINVAL, |
| - EFAULT, |
| - ENOMEM, |
| - ENODEV |
| -) |
| - |
| -# For Windows compatability |
| -ENOTSUP = ZMQ_ENOTSUP |
| -EPROTONOSUPPORT = ZMQ_EPROTONOSUPPORT |
| -ENOBUFS = ZMQ_ENOBUFS |
| -ENETDOWN = ZMQ_ENETDOWN |
| -EADDRINUSE = ZMQ_EADDRINUSE |
| -EADDRNOTAVAIL = ZMQ_EADDRNOTAVAIL |
| -ECONNREFUSED = ZMQ_ECONNREFUSED |
| -EINPROGRESS = ZMQ_EINPROGRESS |
| -ENOTSOCK = ZMQ_ENOTSOCK |
| - |
| -# new errnos in zmq3 |
| -EMSGSIZE = ZMQ_EMSGSIZE |
| -EAFNOSUPPORT = ZMQ_EAFNOSUPPORT |
| -ENETUNREACH = ZMQ_ENETUNREACH |
| -ECONNABORTED = ZMQ_ECONNABORTED |
| -ECONNRESET = ZMQ_ECONNRESET |
| -ENOTCONN = ZMQ_ENOTCONN |
| -ETIMEDOUT = ZMQ_ETIMEDOUT |
| -EHOSTUNREACH = ZMQ_EHOSTUNREACH |
| -ENETRESET = ZMQ_ENETRESET |
| - |
| -# 0MQ Native |
| -EFSM = ZMQ_EFSM |
| -ENOCOMPATPROTO = ZMQ_ENOCOMPATPROTO |
| -ETERM = ZMQ_ETERM |
| -EMTHREAD = ZMQ_EMTHREAD |
| - |
| -#----------------------------------------------------------------------------- |
| -# Symbols to export |
| -#----------------------------------------------------------------------------- |
| -_names = list(locals().keys()) |
| -__all__ = [ key for key in _names if not key.startswith('_') ] |
| diff --git a/zmq/core/context.pxd b/zmq/core/context.pxd |
| deleted file mode 100644 |
| --- a/zmq/core/context.pxd |
| +++ /dev/null |
| @@ -1,40 +0,0 @@ |
| -"""0MQ Context class declaration.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| -cdef class Context: |
| - """Manage the lifecycle of a 0MQ context.""" |
| - |
| - cdef object __weakref__ # enable weakref |
| - cdef void *handle # The C handle for the underlying zmq object. |
| - cdef void **_sockets # A C-array containg socket handles |
| - cdef size_t _n_sockets # the number of sockets |
| - cdef size_t _max_sockets # the size of the _sockets array |
| - cdef int _pid # the pid of the process which created me (for fork safety) |
| - |
| - cdef public object closed # bool property for a closed context. |
| - # helpers for events on _sockets in Socket.__cinit__()/close() |
| - cdef inline void _add_socket(self, void* handle) |
| - cdef inline void _remove_socket(self, void* handle) |
| - |
| diff --git a/zmq/core/context.pyx b/zmq/core/context.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/context.pyx |
| +++ /dev/null |
| @@ -1,254 +0,0 @@ |
| -"""0MQ Context class.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libc.stdlib cimport free, malloc, realloc |
| - |
| -from libzmq cimport * |
| - |
| -cdef extern from "getpid_compat.h": |
| - int getpid() |
| - |
| -from zmq.error import ZMQError |
| -from zmq.core.checkrc cimport _check_rc |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| -_instance = None |
| - |
| -cdef class Context: |
| - """Context(io_threads=1) |
| - |
| - Manage the lifecycle of a 0MQ context. |
| - |
| - Parameters |
| - ---------- |
| - io_threads : int |
| - The number of IO threads. |
| - """ |
| - |
| - def __cinit__(self, int io_threads = 1, **kwargs): |
| - self.handle = NULL |
| - self._sockets = NULL |
| - |
| - if ZMQ_VERSION_MAJOR >= 3: |
| - self.handle = zmq_ctx_new() |
| - else: |
| - self.handle = zmq_init(io_threads) |
| - |
| - if self.handle == NULL: |
| - raise ZMQError() |
| - |
| - cdef int rc = 0 |
| - if ZMQ_VERSION_MAJOR >= 3: |
| - rc = zmq_ctx_set(self.handle, ZMQ_IO_THREADS, io_threads) |
| - _check_rc(rc) |
| - |
| - self.closed = False |
| - self._n_sockets = 0 |
| - self._max_sockets = 32 |
| - |
| - self._sockets = <void **>malloc(self._max_sockets*sizeof(void *)) |
| - if self._sockets == NULL: |
| - raise MemoryError("Could not allocate _sockets array") |
| - |
| - self._pid = getpid() |
| - |
| - def __init__(self, io_threads=1): |
| - # no-op |
| - pass |
| - |
| - |
| - def __del__(self): |
| - """deleting a Context should terminate it, without trying non-threadsafe destroy""" |
| - self.term() |
| - |
| - def __dealloc__(self): |
| - """don't touch members in dealloc, just cleanup allocations""" |
| - cdef int rc |
| - if self._sockets != NULL: |
| - free(self._sockets) |
| - self._sockets = NULL |
| - self._n_sockets = 0 |
| - self.term() |
| - |
| - cdef inline void _add_socket(self, void* handle): |
| - """Add a socket handle to be closed when Context terminates. |
| - |
| - This is to be called in the Socket constructor. |
| - """ |
| - # print self._n_sockets, self._max_sockets |
| - if self._n_sockets >= self._max_sockets: |
| - self._max_sockets *= 2 |
| - self._sockets = <void **>realloc(self._sockets, self._max_sockets*sizeof(void *)) |
| - if self._sockets == NULL: |
| - raise MemoryError("Could not reallocate _sockets array") |
| - |
| - self._sockets[self._n_sockets] = handle |
| - self._n_sockets += 1 |
| - # print self._n_sockets, self._max_sockets |
| - |
| - cdef inline void _remove_socket(self, void* handle): |
| - """Remove a socket from the collected handles. |
| - |
| - This should be called by Socket.close, to prevent trying to |
| - close a socket a second time. |
| - """ |
| - cdef bint found = False |
| - |
| - for idx in range(self._n_sockets): |
| - if self._sockets[idx] == handle: |
| - found=True |
| - break |
| - |
| - if found: |
| - self._n_sockets -= 1 |
| - if self._n_sockets: |
| - # move last handle to closed socket's index |
| - self._sockets[idx] = self._sockets[self._n_sockets] |
| - |
| - @property |
| - def _handle(self): |
| - return <Py_ssize_t> self.handle |
| - |
| - def term(self): |
| - """ctx.term() |
| - |
| - Close or terminate the context. |
| - |
| - This can be called to close the context by hand. If this is not called, |
| - the context will automatically be closed when it is garbage collected. |
| - """ |
| - cdef int rc |
| - cdef int i=-1 |
| - |
| - if self.handle != NULL and not self.closed and getpid() == self._pid: |
| - with nogil: |
| - rc = zmq_ctx_destroy(self.handle) |
| - _check_rc(rc) |
| - self.handle = NULL |
| - self.closed = True |
| - |
| - def set(self, int option, optval): |
| - """ctx.set(option, optval) |
| - |
| - Set context options. |
| - |
| - See the 0MQ API documentation for zmq_ctx_set |
| - for details on specific options. |
| - |
| - New in libzmq-3.2 |
| - |
| - Parameters |
| - ---------- |
| - option : int |
| - The option to set. Available values will depend on your |
| - version of libzmq. Examples include:: |
| - |
| - zmq.IO_THREADS, zmq.MAX_SOCKETS |
| - |
| - optval : int |
| - The value of the option to set. |
| - """ |
| - cdef int optval_int_c |
| - cdef int rc |
| - cdef char* optval_c |
| - |
| - if self.closed: |
| - raise RuntimeError("Context has been destroyed") |
| - |
| - if not isinstance(optval, int): |
| - raise TypeError('expected int, got: %r' % optval) |
| - optval_int_c = optval |
| - rc = zmq_ctx_set(self.handle, option, optval_int_c) |
| - _check_rc(rc) |
| - |
| - def get(self, int option): |
| - """ctx.get(option) |
| - |
| - Get the value of a context option. |
| - |
| - See the 0MQ API documentation for zmq_ctx_get |
| - for details on specific options. |
| - |
| - New in libzmq-3.2 |
| - |
| - Parameters |
| - ---------- |
| - option : int |
| - The option to get. Available values will depend on your |
| - version of libzmq. Examples include:: |
| - |
| - zmq.IO_THREADS, zmq.MAX_SOCKETS |
| - |
| - Returns |
| - ------- |
| - optval : int |
| - The value of the option as an integer. |
| - """ |
| - cdef int optval_int_c |
| - cdef size_t sz |
| - cdef int rc |
| - |
| - if self.closed: |
| - raise RuntimeError("Context has been destroyed") |
| - |
| - rc = zmq_ctx_get(self.handle, option) |
| - _check_rc(rc) |
| - |
| - return rc |
| - |
| - def destroy(self, linger=None): |
| - """ctx.destroy(linger=None) |
| - |
| - Close all sockets associated with this context, and then terminate |
| - the context. If linger is specified, |
| - the LINGER sockopt of the sockets will be set prior to closing. |
| - |
| - WARNING: |
| - |
| - destroy involves calling zmq_close(), which is *NOT* threadsafe. |
| - If there are active sockets in other threads, this must not be called. |
| - """ |
| - |
| - cdef int linger_c |
| - cdef bint setlinger=False |
| - |
| - if linger is not None: |
| - linger_c = linger |
| - setlinger=True |
| - if self.handle != NULL and not self.closed and self._n_sockets: |
| - while self._n_sockets: |
| - if setlinger: |
| - zmq_setsockopt(self._sockets[0], ZMQ_LINGER, &linger_c, sizeof(int)) |
| - rc = zmq_close(self._sockets[0]) |
| - if rc < 0 and zmq_errno() != ZMQ_ENOTSOCK: |
| - raise ZMQError() |
| - self._n_sockets -= 1 |
| - self._sockets[0] = self._sockets[self._n_sockets] |
| - self.term() |
| - |
| -__all__ = ['Context'] |
| diff --git a/zmq/core/error.pyx b/zmq/core/error.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/error.pyx |
| +++ /dev/null |
| @@ -1,56 +0,0 @@ |
| -"""0MQ Error classes and functions.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -# allow const char* |
| -cdef extern from *: |
| - ctypedef char* const_char_ptr "const char*" |
| - |
| -from libzmq cimport zmq_strerror, zmq_errno as zmq_errno_c |
| - |
| -from zmq.utils.strtypes import bytes |
| - |
| -def strerror(int errno): |
| - """strerror(errno) |
| - |
| - Return the error string given the error number. |
| - """ |
| - cdef const_char_ptr str_e |
| - # char * will be a bytes object: |
| - str_e = zmq_strerror(errno) |
| - if str is bytes: |
| - # Python 2: str is bytes, so we already have the right type |
| - return str_e |
| - else: |
| - # Python 3: decode bytes to unicode str |
| - return str_e.decode() |
| - |
| -def zmq_errno(): |
| - """zmq_errno() |
| - |
| - Return the integer errno of the most recent zmq error. |
| - """ |
| - return zmq_errno_c() |
| - |
| -__all__ = ['strerror', 'zmq_errno'] |
| diff --git a/zmq/core/message.pxd b/zmq/core/message.pxd |
| deleted file mode 100644 |
| --- a/zmq/core/message.pxd |
| +++ /dev/null |
| @@ -1,66 +0,0 @@ |
| -"""0MQ Message related class declarations.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from cpython cimport PyBytes_FromStringAndSize |
| - |
| -from libzmq cimport zmq_msg_t, zmq_msg_data, zmq_msg_size |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| -cdef class MessageTracker(object): |
| - """A class for tracking if 0MQ is done using one or more messages.""" |
| - |
| - cdef set events # Message Event objects to track. |
| - cdef set peers # Other Message or MessageTracker objects. |
| - |
| - |
| -cdef class Frame: |
| - """A Message Frame class for non-copy send/recvs.""" |
| - |
| - cdef zmq_msg_t zmq_msg |
| - cdef object _data # The actual message data as a Python object. |
| - cdef object _buffer # A Python Buffer/View of the message contents |
| - cdef object _bytes # A bytes/str copy of the message. |
| - cdef bint _failed_init # Flag to handle failed zmq_msg_init |
| - cdef public object tracker_event # Event for use with zmq_free_fn. |
| - cdef public object tracker # MessageTracker object. |
| - cdef public bint more # whether RCVMORE was set |
| - |
| - cdef Frame fast_copy(self) # Create shallow copy of Message object. |
| - cdef object _getbuffer(self) # Construct self._buffer. |
| - |
| - |
| -cdef inline object copy_zmq_msg_bytes(zmq_msg_t *zmq_msg): |
| - """ Copy the data from a zmq_msg_t """ |
| - cdef char *data_c = NULL |
| - cdef Py_ssize_t data_len_c |
| - with nogil: |
| - data_c = <char *>zmq_msg_data(zmq_msg) |
| - data_len_c = zmq_msg_size(zmq_msg) |
| - return PyBytes_FromStringAndSize(data_c, data_len_c) |
| - |
| - |
| diff --git a/zmq/core/message.pyx b/zmq/core/message.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/message.pyx |
| +++ /dev/null |
| @@ -1,297 +0,0 @@ |
| -"""0MQ Message related classes.""" |
| - |
| -# |
| -# Copyright (c) 2013 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -# get version-independent aliases: |
| -cdef extern from "pyversion_compat.h": |
| - pass |
| - |
| -from cpython cimport Py_DECREF, Py_INCREF |
| - |
| -from buffers cimport asbuffer_r, viewfromobject_r |
| - |
| -cdef extern from "Python.h": |
| - ctypedef int Py_ssize_t |
| - |
| -from libzmq cimport * |
| - |
| -import time |
| - |
| -try: |
| - # below 3.3 |
| - from threading import _Event as Event |
| -except (ImportError, AttributeError): |
| - # python throws ImportError, cython throws AttributeError |
| - from threading import Event |
| - |
| -import zmq |
| -from zmq.core.checkrc cimport _check_rc |
| -from zmq.utils.strtypes import bytes,unicode,basestring |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| - |
| -cdef void free_python_msg(void *data, void *hint) with gil: |
| - """A function for DECREF'ing Python based messages.""" |
| - if hint != NULL: |
| - tracker_event = (<tuple>hint)[1] |
| - Py_DECREF(<object>hint) |
| - if isinstance(tracker_event, Event): |
| - # don't assert before DECREF: |
| - # assert tracker_queue.empty(), "somebody else wrote to my Queue!" |
| - tracker_event.set() |
| - tracker_event = None |
| - |
| - |
| -cdef class Frame: |
| - """Frame(data=None, track=False) |
| - |
| - A zmq message Frame class for non-copy send/recvs. |
| - |
| - This class is only needed if you want to do non-copying send and recvs. |
| - When you pass a string to this class, like ``Frame(s)``, the |
| - ref-count of `s` is increased by two: once because the Frame saves `s` as |
| - an instance attribute and another because a ZMQ message is created that |
| - points to the buffer of `s`. This second ref-count increase makes sure |
| - that `s` lives until all messages that use it have been sent. Once 0MQ |
| - sends all the messages and it doesn't need the buffer of s, 0MQ will call |
| - ``Py_DECREF(s)``. |
| - |
| - Parameters |
| - ---------- |
| - |
| - data : object, optional |
| - any object that provides the buffer interface will be used to |
| - construct the 0MQ message data. |
| - track : bool [default: False] |
| - whether a MessageTracker_ should be created to track this object. |
| - Tracking a message has a cost at creation, because it creates a threadsafe |
| - Event object. |
| - |
| - """ |
| - |
| - def __cinit__(self, object data=None, track=False, **kwargs): |
| - cdef int rc |
| - cdef char *data_c = NULL |
| - cdef Py_ssize_t data_len_c=0 |
| - cdef object hint |
| - |
| - # init more as False |
| - self.more = False |
| - |
| - # Save the data object in case the user wants the the data as a str. |
| - self._data = data |
| - self._failed_init = True # bool switch for dealloc |
| - self._buffer = None # buffer view of data |
| - self._bytes = None # bytes copy of data |
| - |
| - # Event and MessageTracker for monitoring when zmq is done with data: |
| - if track: |
| - evt = Event() |
| - self.tracker_event = evt |
| - self.tracker = zmq.MessageTracker(evt) |
| - else: |
| - self.tracker_event = None |
| - self.tracker = None |
| - |
| - if isinstance(data, unicode): |
| - raise TypeError("Unicode objects not allowed. Only: str/bytes, buffer interfaces.") |
| - |
| - if data is None: |
| - with nogil: |
| - rc = zmq_msg_init(&self.zmq_msg) |
| - _check_rc(rc) |
| - self._failed_init = False |
| - return |
| - else: |
| - asbuffer_r(data, <void **>&data_c, &data_len_c) |
| - # We INCREF the *original* Python object (not self) and pass it |
| - # as the hint below. This allows other copies of this Frame |
| - # object to take over the ref counting of data properly. |
| - hint = (data, self.tracker_event) |
| - Py_INCREF(hint) |
| - with nogil: |
| - rc = zmq_msg_init_data( |
| - &self.zmq_msg, <void *>data_c, data_len_c, |
| - <zmq_free_fn *>free_python_msg, <void *>hint |
| - ) |
| - if rc != 0: |
| - Py_DECREF(hint) |
| - _check_rc(rc) |
| - self._failed_init = False |
| - |
| - def __init__(self, object data=None, track=False): |
| - """Enforce signature""" |
| - pass |
| - |
| - def __dealloc__(self): |
| - cdef int rc |
| - if self._failed_init: |
| - return |
| - # This simply decreases the 0MQ ref-count of zmq_msg. |
| - with nogil: |
| - rc = zmq_msg_close(&self.zmq_msg) |
| - _check_rc(rc) |
| - |
| - # buffer interface code adapted from petsc4py by Lisandro Dalcin, a BSD project |
| - |
| - def __getbuffer__(self, Py_buffer* buffer, int flags): |
| - # new-style (memoryview) buffer interface |
| - with nogil: |
| - buffer.buf = zmq_msg_data(&self.zmq_msg) |
| - buffer.len = zmq_msg_size(&self.zmq_msg) |
| - |
| - buffer.obj = self |
| - buffer.readonly = 1 |
| - buffer.format = "B" |
| - buffer.ndim = 0 |
| - buffer.shape = NULL |
| - buffer.strides = NULL |
| - buffer.suboffsets = NULL |
| - buffer.itemsize = 1 |
| - buffer.internal = NULL |
| - |
| - def __getsegcount__(self, Py_ssize_t *lenp): |
| - # required for getreadbuffer |
| - if lenp != NULL: |
| - with nogil: |
| - lenp[0] = zmq_msg_size(&self.zmq_msg) |
| - return 1 |
| - |
| - def __getreadbuffer__(self, Py_ssize_t idx, void **p): |
| - # old-style (buffer) interface |
| - cdef char *data_c = NULL |
| - cdef Py_ssize_t data_len_c |
| - if idx != 0: |
| - raise SystemError("accessing non-existent buffer segment") |
| - # read-only, because we don't want to allow |
| - # editing of the message in-place |
| - with nogil: |
| - data_c = <char *>zmq_msg_data(&self.zmq_msg) |
| - data_len_c = zmq_msg_size(&self.zmq_msg) |
| - if p != NULL: |
| - p[0] = <void*>data_c |
| - return data_len_c |
| - |
| - # end buffer interface |
| - |
| - def __copy__(self): |
| - """Create a shallow copy of the message. |
| - |
| - This does not copy the contents of the Frame, just the pointer. |
| - This will increment the 0MQ ref count of the message, but not |
| - the ref count of the Python object. That is only done once when |
| - the Python is first turned into a 0MQ message. |
| - """ |
| - return self.fast_copy() |
| - |
| - cdef Frame fast_copy(self): |
| - """Fast, cdef'd version of shallow copy of the Frame.""" |
| - cdef Frame new_msg |
| - new_msg = Frame() |
| - # This does not copy the contents, but just increases the ref-count |
| - # of the zmq_msg by one. |
| - with nogil: |
| - zmq_msg_copy(&new_msg.zmq_msg, &self.zmq_msg) |
| - # Copy the ref to data so the copy won't create a copy when str is |
| - # called. |
| - if self._data is not None: |
| - new_msg._data = self._data |
| - if self._buffer is not None: |
| - new_msg._buffer = self._buffer |
| - if self._bytes is not None: |
| - new_msg._bytes = self._bytes |
| - |
| - # Frame copies share the tracker and tracker_event |
| - new_msg.tracker_event = self.tracker_event |
| - new_msg.tracker = self.tracker |
| - |
| - return new_msg |
| - |
| - def __len__(self): |
| - """Return the length of the message in bytes.""" |
| - cdef size_t sz |
| - with nogil: |
| - sz = zmq_msg_size(&self.zmq_msg) |
| - return sz |
| - # return <int>zmq_msg_size(&self.zmq_msg) |
| - |
| - def __str__(self): |
| - """Return the str form of the message.""" |
| - if isinstance(self._data, bytes): |
| - b = self._data |
| - else: |
| - b = self.bytes |
| - if str is unicode: |
| - return b.decode() |
| - else: |
| - return b |
| - |
| - cdef inline object _getbuffer(self): |
| - """Create a Python buffer/view of the message data. |
| - |
| - This will be called only once, the first time the `buffer` property |
| - is accessed. Subsequent calls use a cached copy. |
| - """ |
| - if self._data is None: |
| - return viewfromobject_r(self) |
| - else: |
| - return viewfromobject_r(self._data) |
| - |
| - @property |
| - def buffer(self): |
| - """Get a read-only buffer view of the message contents.""" |
| - if self._buffer is None: |
| - self._buffer = self._getbuffer() |
| - return self._buffer |
| - |
| - @property |
| - def bytes(self): |
| - """Get the message content as a Python str/bytes object. |
| - |
| - The first time this property is accessed, a copy of the message |
| - contents is made. From then on that same copy of the message is |
| - returned. |
| - """ |
| - if self._bytes is None: |
| - self._bytes = copy_zmq_msg_bytes(&self.zmq_msg) |
| - return self._bytes |
| - |
| - def set(self, int option, int value): |
| - """Set a message property""" |
| - cdef int rc = zmq_msg_set(&self.zmq_msg, option, value) |
| - _check_rc(rc) |
| - |
| - def get(self, int option): |
| - """Get a message property""" |
| - cdef int rc = zmq_msg_get(&self.zmq_msg, option) |
| - _check_rc(rc) |
| - return rc |
| - |
| -# legacy Message name |
| -Message = Frame |
| - |
| -__all__ = ['Frame', 'Message'] |
| diff --git a/zmq/core/socket.pxd b/zmq/core/socket.pxd |
| deleted file mode 100644 |
| --- a/zmq/core/socket.pxd |
| +++ /dev/null |
| @@ -1,48 +0,0 @@ |
| -"""0MQ Socket class declaration.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from context cimport Context |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| - |
| -cdef class Socket: |
| - """A 0MQ socket.""" |
| - |
| - cdef object __weakref__ # enable weakref |
| - cdef void *handle # The C handle for the underlying zmq object. |
| - cdef public int socket_type # The 0MQ socket type - REQ,REP, etc. |
| - # Hold on to a reference to the context to make sure it is not garbage |
| - # collected until the socket it done with it. |
| - cdef public Context context # The zmq Context object that owns this. |
| - cdef public bint _closed # bool property for a closed socket. |
| - cdef int _pid # the pid of the process which created me (for fork safety) |
| - |
| - # cpdef methods for direct-cython access: |
| - cpdef object send(self, object data, int flags=*, copy=*, track=*) |
| - cpdef object recv(self, int flags=*, copy=*, track=*) |
| - |
| diff --git a/zmq/core/socket.pyx b/zmq/core/socket.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/socket.pyx |
| +++ /dev/null |
| @@ -1,628 +0,0 @@ |
| -"""0MQ Socket class.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Cython Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -# get version-independent aliases: |
| -cdef extern from "pyversion_compat.h": |
| - pass |
| - |
| -from libc.errno cimport ENAMETOOLONG |
| -from libc.string cimport memcpy |
| - |
| -from cpython cimport PyBytes_FromStringAndSize |
| -from cpython cimport PyBytes_AsString, PyBytes_Size |
| -from cpython cimport Py_DECREF, Py_INCREF |
| - |
| -from buffers cimport asbuffer_r, viewfromobject_r |
| - |
| -from libzmq cimport * |
| -from message cimport Frame, copy_zmq_msg_bytes |
| - |
| -from context cimport Context |
| - |
| -cdef extern from "Python.h": |
| - ctypedef int Py_ssize_t |
| - |
| -cdef extern from "ipcmaxlen.h": |
| - int get_ipc_path_max_len() |
| - |
| -cdef extern from "getpid_compat.h": |
| - int getpid() |
| - |
| - |
| -#----------------------------------------------------------------------------- |
| -# Python Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -import copy as copy_mod |
| -import time |
| -import sys |
| -import random |
| -import struct |
| -import codecs |
| - |
| -from zmq.utils import jsonapi |
| - |
| -try: |
| - import cPickle |
| - pickle = cPickle |
| -except: |
| - cPickle = None |
| - import pickle |
| - |
| -import zmq |
| -from zmq.core import constants |
| -from zmq.core.constants import * |
| -from zmq.core.checkrc cimport _check_rc |
| -from zmq.error import ZMQError, ZMQBindError |
| -from zmq.utils.strtypes import bytes,unicode,basestring |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| -IPC_PATH_MAX_LEN = get_ipc_path_max_len() |
| - |
| -# inline some small socket submethods: |
| -# true methods frequently cannot be inlined, acc. Cython docs |
| - |
| -cdef inline _check_closed(Socket s, bint raise_notsup): |
| - cdef int rc |
| - cdef int errno |
| - cdef int stype |
| - cdef size_t sz=sizeof(int) |
| - if s._closed: |
| - if raise_notsup: |
| - raise ZMQError(ENOTSUP) |
| - else: |
| - return True |
| - else: |
| - rc = zmq_getsockopt(s.handle, ZMQ_TYPE, <void *>&stype, &sz) |
| - if rc < 0 and zmq_errno() == ENOTSOCK: |
| - s._closed = True |
| - if raise_notsup: |
| - raise ZMQError(ENOTSUP) |
| - else: |
| - return True |
| - else: |
| - _check_rc(rc) |
| - return False |
| - |
| -cdef inline Frame _recv_frame(void *handle, int flags=0, track=False): |
| - """Receive a message in a non-copying manner and return a Frame.""" |
| - cdef int rc |
| - cdef Frame msg |
| - msg = Frame(track=track) |
| - |
| - with nogil: |
| - rc = zmq_msg_recv(&msg.zmq_msg, handle, flags) |
| - |
| - _check_rc(rc) |
| - return msg |
| - |
| -cdef inline object _recv_copy(void *handle, int flags=0): |
| - """Receive a message and return a copy""" |
| - cdef zmq_msg_t zmq_msg |
| - with nogil: |
| - zmq_msg_init (&zmq_msg) |
| - rc = zmq_msg_recv(&zmq_msg, handle, flags) |
| - _check_rc(rc) |
| - msg_bytes = copy_zmq_msg_bytes(&zmq_msg) |
| - with nogil: |
| - zmq_msg_close(&zmq_msg) |
| - return msg_bytes |
| - |
| -cdef inline object _send_frame(void *handle, Frame msg, int flags=0): |
| - """Send a Frame on this socket in a non-copy manner.""" |
| - cdef int rc |
| - cdef Frame msg_copy |
| - |
| - # Always copy so the original message isn't garbage collected. |
| - # This doesn't do a real copy, just a reference. |
| - msg_copy = msg.fast_copy() |
| - |
| - with nogil: |
| - rc = zmq_msg_send(&msg_copy.zmq_msg, handle, flags) |
| - |
| - _check_rc(rc) |
| - return msg.tracker |
| - |
| - |
| -cdef inline object _send_copy(void *handle, object msg, int flags=0): |
| - """Send a message on this socket by copying its content.""" |
| - cdef int rc, rc2 |
| - cdef zmq_msg_t data |
| - cdef char *msg_c |
| - cdef Py_ssize_t msg_c_len=0 |
| - |
| - # copy to c array: |
| - asbuffer_r(msg, <void **>&msg_c, &msg_c_len) |
| - |
| - # Copy the msg before sending. This avoids any complications with |
| - # the GIL, etc. |
| - # If zmq_msg_init_* fails we must not call zmq_msg_close (Bus Error) |
| - with nogil: |
| - rc = zmq_msg_init_size(&data, msg_c_len) |
| - |
| - _check_rc(rc) |
| - |
| - with nogil: |
| - memcpy(zmq_msg_data(&data), msg_c, zmq_msg_size(&data)) |
| - rc = zmq_msg_send(&data, handle, flags) |
| - rc2 = zmq_msg_close(&data) |
| - _check_rc(rc) |
| - _check_rc(rc2) |
| - |
| - |
| -cdef class Socket: |
| - """Socket(context, socket_type) |
| - |
| - A 0MQ socket. |
| - |
| - These objects will generally be constructed via the socket() method of a Context object. |
| - |
| - Note: 0MQ Sockets are *not* threadsafe. **DO NOT** share them across threads. |
| - |
| - Parameters |
| - ---------- |
| - context : Context |
| - The 0MQ Context this Socket belongs to. |
| - socket_type : int |
| - The socket type, which can be any of the 0MQ socket types: |
| - REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB. |
| - |
| - See Also |
| - -------- |
| - .Context.socket : method for creating a socket bound to a Context. |
| - """ |
| - |
| - def __cinit__(self, Context context, int socket_type, *args, **kwrags): |
| - cdef Py_ssize_t c_handle |
| - c_handle = context._handle |
| - |
| - self.handle = NULL |
| - self.context = context |
| - self.socket_type = socket_type |
| - with nogil: |
| - self.handle = zmq_socket(<void *>c_handle, socket_type) |
| - if self.handle == NULL: |
| - raise ZMQError() |
| - self._closed = False |
| - self._pid = getpid() |
| - context._add_socket(self.handle) |
| - |
| - def __dealloc__(self): |
| - """close *and* remove from context's list |
| - |
| - But be careful that context might not exist if called during gc |
| - """ |
| - if self.handle != NULL and getpid() == self._pid: |
| - rc = zmq_close(self.handle) |
| - if rc != 0 and zmq_errno() != ENOTSOCK: |
| - # ignore ENOTSOCK (closed by Context) |
| - _check_rc(rc) |
| - # during gc, self.context might be NULL |
| - if self.context: |
| - self.context._remove_socket(self.handle) |
| - |
| - def __init__(self, context, socket_type): |
| - pass |
| - |
| - @property |
| - def closed(self): |
| - return _check_closed(self, False) |
| - |
| - def close(self, linger=None): |
| - """s.close(linger=None) |
| - |
| - Close the socket. |
| - |
| - If linger is specified, LINGER sockopt will be set prior to closing. |
| - |
| - This can be called to close the socket by hand. If this is not |
| - called, the socket will automatically be closed when it is |
| - garbage collected. |
| - """ |
| - cdef int rc=0 |
| - cdef int linger_c |
| - cdef bint setlinger=False |
| - |
| - if linger is not None: |
| - linger_c = linger |
| - setlinger=True |
| - |
| - if self.handle != NULL and not self._closed and getpid() == self._pid: |
| - if setlinger: |
| - zmq_setsockopt(self.handle, ZMQ_LINGER, &linger_c, sizeof(int)) |
| - rc = zmq_close(self.handle) |
| - if rc != 0 and zmq_errno() != ENOTSOCK: |
| - # ignore ENOTSOCK (closed by Context) |
| - _check_rc(rc) |
| - self._closed = True |
| - # during gc, self.context might be NULL |
| - if self.context: |
| - self.context._remove_socket(self.handle) |
| - self.handle = NULL |
| - |
| - def set(self, int option, optval): |
| - """s.set(option, optval) |
| - |
| - Set socket options. |
| - |
| - See the 0MQ API documentation for details on specific options. |
| - |
| - Parameters |
| - ---------- |
| - option : int |
| - The option to set. Available values will depend on your |
| - version of libzmq. Examples include:: |
| - |
| - zmq.SUBSCRIBE, UNSUBSCRIBE, IDENTITY, HWM, LINGER, FD |
| - |
| - optval : int or bytes |
| - The value of the option to set. |
| - """ |
| - cdef int64_t optval_int64_c |
| - cdef int optval_int_c |
| - cdef int rc |
| - cdef char* optval_c |
| - cdef Py_ssize_t sz |
| - |
| - _check_closed(self, True) |
| - if isinstance(optval, unicode): |
| - raise TypeError("unicode not allowed, use setsockopt_string") |
| - |
| - if option in zmq.constants.bytes_sockopts: |
| - if not isinstance(optval, bytes): |
| - raise TypeError('expected bytes, got: %r' % optval) |
| - optval_c = PyBytes_AsString(optval) |
| - sz = PyBytes_Size(optval) |
| - with nogil: |
| - rc = zmq_setsockopt( |
| - self.handle, option, |
| - optval_c, sz |
| - ) |
| - elif option in zmq.constants.int64_sockopts: |
| - if not isinstance(optval, int): |
| - raise TypeError('expected int, got: %r' % optval) |
| - optval_int64_c = optval |
| - with nogil: |
| - rc = zmq_setsockopt( |
| - self.handle, option, |
| - &optval_int64_c, sizeof(int64_t) |
| - ) |
| - else: |
| - # default is to assume int, which is what most new sockopts will be |
| - # this lets pyzmq work with newer libzmq which may add constants |
| - # pyzmq has not yet added, rather than artificially raising. Invalid |
| - # sockopts will still raise just the same, but it will be libzmq doing |
| - # the raising. |
| - if not isinstance(optval, int): |
| - raise TypeError('expected int, got: %r' % optval) |
| - optval_int_c = optval |
| - with nogil: |
| - rc = zmq_setsockopt( |
| - self.handle, option, |
| - &optval_int_c, sizeof(int) |
| - ) |
| - |
| - _check_rc(rc) |
| - |
| - def get(self, int option): |
| - """s.get(option) |
| - |
| - Get the value of a socket option. |
| - |
| - See the 0MQ API documentation for details on specific options. |
| - |
| - Parameters |
| - ---------- |
| - option : int |
| - The option to get. Available values will depend on your |
| - version of libzmq. Examples include:: |
| - |
| - zmq.IDENTITY, HWM, LINGER, FD, EVENTS |
| - |
| - Returns |
| - ------- |
| - optval : int or bytes |
| - The value of the option as a bytestring or int. |
| - """ |
| - cdef int64_t optval_int64_c |
| - cdef int optval_int_c |
| - cdef fd_t optval_fd_c |
| - cdef char identity_str_c [255] |
| - cdef size_t sz |
| - cdef int rc |
| - |
| - _check_closed(self, True) |
| - |
| - if option in zmq.constants.bytes_sockopts: |
| - sz = 255 |
| - with nogil: |
| - rc = zmq_getsockopt(self.handle, option, <void *>identity_str_c, &sz) |
| - _check_rc(rc) |
| - result = PyBytes_FromStringAndSize(<char *>identity_str_c, sz) |
| - elif option in zmq.constants.int64_sockopts: |
| - sz = sizeof(int64_t) |
| - with nogil: |
| - rc = zmq_getsockopt(self.handle, option, <void *>&optval_int64_c, &sz) |
| - _check_rc(rc) |
| - result = optval_int64_c |
| - elif option == ZMQ_FD: |
| - sz = sizeof(fd_t) |
| - with nogil: |
| - rc = zmq_getsockopt(self.handle, option, <void *>&optval_fd_c, &sz) |
| - _check_rc(rc) |
| - result = optval_fd_c |
| - else: |
| - # default is to assume int, which is what most new sockopts will be |
| - # this lets pyzmq work with newer libzmq which may add constants |
| - # pyzmq has not yet added, rather than artificially raising. Invalid |
| - # sockopts will still raise just the same, but it will be libzmq doing |
| - # the raising. |
| - sz = sizeof(int) |
| - with nogil: |
| - rc = zmq_getsockopt(self.handle, option, <void *>&optval_int_c, &sz) |
| - _check_rc(rc) |
| - result = optval_int_c |
| - |
| - return result |
| - |
| - def bind(self, addr): |
| - """s.bind(addr) |
| - |
| - Bind the socket to an address. |
| - |
| - This causes the socket to listen on a network port. Sockets on the |
| - other side of this connection will use ``Socket.connect(addr)`` to |
| - connect to this socket. |
| - |
| - Parameters |
| - ---------- |
| - addr : str |
| - The address string. This has the form 'protocol://interface:port', |
| - for example 'tcp://127.0.0.1:5555'. Protocols supported include |
| - tcp, udp, pgm, epgm, inproc and ipc. If the address is unicode, it is |
| - encoded to utf-8 first. |
| - """ |
| - cdef int rc |
| - cdef char* c_addr |
| - |
| - _check_closed(self, True) |
| - if isinstance(addr, unicode): |
| - addr = addr.encode('utf-8') |
| - if not isinstance(addr, bytes): |
| - raise TypeError('expected str, got: %r' % addr) |
| - c_addr = addr |
| - rc = zmq_bind(self.handle, c_addr) |
| - if rc != 0: |
| - if IPC_PATH_MAX_LEN and zmq_errno() == ENAMETOOLONG: |
| - # py3compat: addr is bytes, but msg wants str |
| - if str is unicode: |
| - addr = addr.decode('utf-8', 'replace') |
| - path = addr.split('://', 1)[-1] |
| - msg = ('ipc path "{0}" is longer than {1} ' |
| - 'characters (sizeof(sockaddr_un.sun_path)). ' |
| - 'zmq.IPC_PATH_MAX_LEN constant can be used ' |
| - 'to check addr length (if it is defined).' |
| - .format(path, IPC_PATH_MAX_LEN)) |
| - raise ZMQError(msg=msg) |
| - _check_rc(rc) |
| - |
| - def connect(self, addr): |
| - """s.connect(addr) |
| - |
| - Connect to a remote 0MQ socket. |
| - |
| - Parameters |
| - ---------- |
| - addr : str |
| - The address string. This has the form 'protocol://interface:port', |
| - for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| - tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| - encoded to utf-8 first. |
| - """ |
| - cdef int rc |
| - cdef char* c_addr |
| - |
| - _check_closed(self, True) |
| - if isinstance(addr, unicode): |
| - addr = addr.encode('utf-8') |
| - if not isinstance(addr, bytes): |
| - raise TypeError('expected str, got: %r' % addr) |
| - c_addr = addr |
| - |
| - rc = zmq_connect(self.handle, c_addr) |
| - if rc != 0: |
| - raise ZMQError() |
| - |
| - def unbind(self, addr): |
| - """s.unbind(addr) |
| - |
| - Unbind from an address (undoes a call to bind). |
| - |
| - This feature requires libzmq-3 |
| - |
| - Parameters |
| - ---------- |
| - addr : str |
| - The address string. This has the form 'protocol://interface:port', |
| - for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| - tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| - encoded to utf-8 first. |
| - """ |
| - cdef int rc |
| - cdef char* c_addr |
| - |
| - if ZMQ_VERSION_MAJOR < 3: |
| - raise NotImplementedError("unbind requires libzmq >= 3.0, have %s" % zmq.zmq_version()) |
| - |
| - |
| - _check_closed(self, True) |
| - if isinstance(addr, unicode): |
| - addr = addr.encode('utf-8') |
| - if not isinstance(addr, bytes): |
| - raise TypeError('expected str, got: %r' % addr) |
| - c_addr = addr |
| - |
| - rc = zmq_unbind(self.handle, c_addr) |
| - if rc != 0: |
| - raise ZMQError() |
| - |
| - def disconnect(self, addr): |
| - """s.disconnect(addr) |
| - |
| - Disconnect from a remote 0MQ socket (undoes a call to connect). |
| - |
| - This feature requires libzmq-3 |
| - |
| - Parameters |
| - ---------- |
| - addr : str |
| - The address string. This has the form 'protocol://interface:port', |
| - for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| - tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| - encoded to utf-8 first. |
| - """ |
| - cdef int rc |
| - cdef char* c_addr |
| - |
| - if ZMQ_VERSION_MAJOR < 3: |
| - raise NotImplementedError("disconnect requires libzmq >= 3.0, have %s" % zmq.zmq_version()) |
| - |
| - _check_closed(self, True) |
| - if isinstance(addr, unicode): |
| - addr = addr.encode('utf-8') |
| - if not isinstance(addr, bytes): |
| - raise TypeError('expected str, got: %r' % addr) |
| - c_addr = addr |
| - |
| - rc = zmq_disconnect(self.handle, c_addr) |
| - if rc != 0: |
| - raise ZMQError() |
| - |
| - #------------------------------------------------------------------------- |
| - # Sending and receiving messages |
| - #------------------------------------------------------------------------- |
| - |
| - cpdef object send(self, object data, int flags=0, copy=True, track=False): |
| - """s.send(data, flags=0, copy=True, track=False) |
| - |
| - Send a message on this socket. |
| - |
| - This queues the message to be sent by the IO thread at a later time. |
| - |
| - Parameters |
| - ---------- |
| - data : object, str, Frame |
| - The content of the message. |
| - flags : int |
| - Any supported flag: NOBLOCK, SNDMORE. |
| - copy : bool |
| - Should the message be sent in a copying or non-copying manner. |
| - track : bool |
| - Should the message be tracked for notification that ZMQ has |
| - finished with it? (ignored if copy=True) |
| - |
| - Returns |
| - ------- |
| - None : if `copy` or not track |
| - None if message was sent, raises an exception otherwise. |
| - MessageTracker : if track and not copy |
| - a MessageTracker object, whose `pending` property will |
| - be True until the send is completed. |
| - |
| - Raises |
| - ------ |
| - TypeError |
| - If a unicode object is passed |
| - ValueError |
| - If `track=True`, but an untracked Frame is passed. |
| - ZMQError |
| - If the send does not succeed for any reason. |
| - |
| - """ |
| - _check_closed(self, True) |
| - |
| - if isinstance(data, unicode): |
| - raise TypeError("unicode not allowed, use send_unicode") |
| - |
| - if copy: |
| - # msg.bytes never returns the input data object |
| - # it is always a copy, but always the same copy |
| - if isinstance(data, Frame): |
| - data = data.buffer |
| - return _send_copy(self.handle, data, flags) |
| - else: |
| - if isinstance(data, Frame): |
| - if track and not data.tracker: |
| - raise ValueError('Not a tracked message') |
| - msg = data |
| - else: |
| - msg = Frame(data, track=track) |
| - return _send_frame(self.handle, msg, flags) |
| - |
| - cpdef object recv(self, int flags=0, copy=True, track=False): |
| - """s.recv(flags=0, copy=True, track=False) |
| - |
| - Receive a message. |
| - |
| - Parameters |
| - ---------- |
| - flags : int |
| - Any supported flag: NOBLOCK. If NOBLOCK is set, this method |
| - will raise a ZMQError with EAGAIN if a message is not ready. |
| - If NOBLOCK is not set, then this method will block until a |
| - message arrives. |
| - copy : bool |
| - Should the message be received in a copying or non-copying manner? |
| - If False a Frame object is returned, if True a string copy of |
| - message is returned. |
| - track : bool |
| - Should the message be tracked for notification that ZMQ has |
| - finished with it? (ignored if copy=True) |
| - |
| - Returns |
| - ------- |
| - msg : bytes, Frame |
| - The received message frame. If `copy` is False, then it will be a Frame, |
| - otherwise it will be bytes. |
| - |
| - Raises |
| - ------ |
| - ZMQError |
| - for any of the reasons zmq_msg_recv might fail. |
| - """ |
| - _check_closed(self, True) |
| - |
| - if copy: |
| - return _recv_copy(self.handle, flags) |
| - else: |
| - frame = _recv_frame(self.handle, flags, track) |
| - frame.more = self.getsockopt(zmq.RCVMORE) |
| - return frame |
| - |
| - |
| -__all__ = ['Socket', 'IPC_PATH_MAX_LEN'] |
| diff --git a/zmq/core/stopwatch.pxd b/zmq/core/stopwatch.pxd |
| deleted file mode 100644 |
| --- a/zmq/core/stopwatch.pxd |
| +++ /dev/null |
| @@ -1,31 +0,0 @@ |
| -"""0MQ Stopwatch class declaration.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| - |
| -cdef class Stopwatch: |
| - """A simple stopwatch based on zmq_stopwatch_start/stop.""" |
| - |
| - cdef void *watch # The C handle for the underlying zmq object |
| - |
| diff --git a/zmq/core/stopwatch.pyx b/zmq/core/stopwatch.pyx |
| deleted file mode 100644 |
| --- a/zmq/core/stopwatch.pyx |
| +++ /dev/null |
| @@ -1,90 +0,0 @@ |
| -"""0MQ Stopwatch class.""" |
| - |
| -# |
| -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq. |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libzmq cimport zmq_stopwatch_start, zmq_stopwatch_stop, zmq_sleep |
| - |
| -from zmq.error import ZMQError |
| - |
| -#----------------------------------------------------------------------------- |
| -# Code |
| -#----------------------------------------------------------------------------- |
| - |
| -cdef class Stopwatch: |
| - """Stopwatch() |
| - |
| - A simple stopwatch based on zmq_stopwatch_start/stop. |
| - |
| - This class should be used for benchmarking and timing 0MQ code. |
| - """ |
| - |
| - def __cinit__(self): |
| - self.watch = NULL |
| - |
| - def __dealloc__(self): |
| - try: |
| - self.stop() |
| - except ZMQError: |
| - pass |
| - |
| - def start(self): |
| - """s.start() |
| - |
| - Start the stopwatch. |
| - """ |
| - if self.watch == NULL: |
| - with nogil: |
| - self.watch = zmq_stopwatch_start() |
| - else: |
| - raise ZMQError('Stopwatch is already runing.') |
| - |
| - def stop(self): |
| - """s.stop() |
| - |
| - Stop the stopwatch. |
| - |
| - Returns |
| - ------- |
| - t : unsigned long int |
| - the number of microseconds since ``start()`` was called. |
| - """ |
| - cdef unsigned long time |
| - if self.watch == NULL: |
| - raise ZMQError('Must start the Stopwatch before calling stop.') |
| - else: |
| - with nogil: |
| - time = zmq_stopwatch_stop(self.watch) |
| - self.watch = NULL |
| - return time |
| - |
| - def sleep(self, int seconds): |
| - """s.sleep(seconds) |
| - |
| - Sleep for an integer number of seconds. |
| - """ |
| - with nogil: |
| - zmq_sleep(seconds) |
| - |
| - |
| -__all__ = ['Stopwatch'] |
| diff --git a/zmq/devices/__init__.py b/zmq/devices/__init__.py |
| --- a/zmq/devices/__init__.py |
| +++ b/zmq/devices/__init__.py |
| @@ -14,11 +14,12 @@ |
| #----------------------------------------------------------------------------- |
| |
| from zmq import device |
| -from zmq.devices import basedevice, proxydevice, monitoredqueue, monitoredqueuedevice |
| +from zmq.devices import basedevice, proxydevice, monitoredqueuedevice |
| +from zmq.devices import _zmonitoredqueue as monitoredqueue |
| |
| from zmq.devices.basedevice import * |
| from zmq.devices.proxydevice import * |
| -from zmq.devices.monitoredqueue import * |
| +from zmq.devices._zmonitoredqueue import * |
| from zmq.devices.monitoredqueuedevice import * |
| |
| __all__ = ['device'] |
| diff --git a/zmq/devices/_zmonitoredqueue.pxd b/zmq/devices/_zmonitoredqueue.pxd |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/devices/_zmonitoredqueue.pxd |
| @@ -0,0 +1,166 @@ |
| +"""MonitoredQueue class declarations. |
| + |
| +Authors |
| +------- |
| +* MinRK |
| +* Brian Granger |
| +""" |
| + |
| +# |
| +# Copyright (c) 2010 Min Ragan-Kelley, Brian Granger |
| +# |
| +# This file is part of pyzmq, but is derived and adapted from zmq_queue.cpp |
| +# originally from libzmq-2.1.6, used under LGPLv3 |
| +# |
| +# pyzmq is free software; you can redistribute it and/or modify it under |
| +# the terms of the Lesser GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# pyzmq is distributed in the hope that it will be useful, |
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| +# Lesser GNU General Public License for more details. |
| +# |
| +# You should have received a copy of the Lesser GNU General Public License |
| +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| +# |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +from libzmq cimport * |
| + |
| +#----------------------------------------------------------------------------- |
| +# MonitoredQueue C functions |
| +#----------------------------------------------------------------------------- |
| + |
| +cdef inline int _relay(void *insocket_, void *outsocket_, void *sidesocket_, |
| + zmq_msg_t msg, zmq_msg_t side_msg, zmq_msg_t id_msg, |
| + bint swap_ids) nogil: |
| + cdef int rc |
| + cdef int64_t flag_2 |
| + cdef int flag_3 |
| + cdef int flags |
| + cdef bint more |
| + cdef size_t flagsz |
| + cdef void * flag_ptr |
| + |
| + if ZMQ_VERSION_MAJOR < 3: |
| + flagsz = sizeof (int64_t) |
| + flag_ptr = &flag_2 |
| + else: |
| + flagsz = sizeof (int) |
| + flag_ptr = &flag_3 |
| + |
| + if swap_ids:# both router, must send second identity first |
| + # recv two ids into msg, id_msg |
| + rc = zmq_msg_recv(&msg, insocket_, 0) |
| + rc = zmq_msg_recv(&id_msg, insocket_, 0) |
| + |
| + # send second id (id_msg) first |
| + #!!!! always send a copy before the original !!!! |
| + rc = zmq_msg_copy(&side_msg, &id_msg) |
| + rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| + rc = zmq_msg_send(&id_msg, sidesocket_, ZMQ_SNDMORE) |
| + # send first id (msg) second |
| + rc = zmq_msg_copy(&side_msg, &msg) |
| + rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| + rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| + if rc < 0: |
| + return rc |
| + while (True): |
| + rc = zmq_msg_recv(&msg, insocket_, 0) |
| + # assert (rc == 0) |
| + rc = zmq_getsockopt (insocket_, ZMQ_RCVMORE, flag_ptr, &flagsz) |
| + flags = 0 |
| + if ZMQ_VERSION_MAJOR < 3: |
| + if flag_2: |
| + flags |= ZMQ_SNDMORE |
| + else: |
| + if flag_3: |
| + flags |= ZMQ_SNDMORE |
| + # LABEL has been removed: |
| + # rc = zmq_getsockopt (insocket_, ZMQ_RCVLABEL, flag_ptr, &flagsz) |
| + # if flag_3: |
| + # flags |= ZMQ_SNDLABEL |
| + # assert (rc == 0) |
| + |
| + rc = zmq_msg_copy(&side_msg, &msg) |
| + if flags: |
| + rc = zmq_msg_send(&side_msg, outsocket_, flags) |
| + # only SNDMORE for side-socket |
| + rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| + else: |
| + rc = zmq_msg_send(&side_msg, outsocket_, 0) |
| + rc = zmq_msg_send(&msg, sidesocket_, 0) |
| + break |
| + return rc |
| + |
| +# the MonitoredQueue C function, adapted from zmq::queue.cpp : |
| +cdef inline int c_monitored_queue (void *insocket_, void *outsocket_, |
| + void *sidesocket_, zmq_msg_t *in_msg_ptr, |
| + zmq_msg_t *out_msg_ptr, int swap_ids) nogil: |
| + """The actual C function for a monitored queue device. |
| + |
| + See ``monitored_queue()`` for details. |
| + """ |
| + |
| + cdef zmq_msg_t msg |
| + cdef int rc = zmq_msg_init (&msg) |
| + cdef zmq_msg_t id_msg |
| + rc = zmq_msg_init (&id_msg) |
| + cdef zmq_msg_t side_msg |
| + rc = zmq_msg_init (&side_msg) |
| + # assert (rc == 0) |
| + |
| + |
| + cdef zmq_pollitem_t items [2] |
| + items [0].socket = insocket_ |
| + items [0].fd = 0 |
| + items [0].events = ZMQ_POLLIN |
| + items [0].revents = 0 |
| + items [1].socket = outsocket_ |
| + items [1].fd = 0 |
| + items [1].events = ZMQ_POLLIN |
| + items [1].revents = 0 |
| + # I don't think sidesocket should be polled? |
| + # items [2].socket = sidesocket_ |
| + # items [2].fd = 0 |
| + # items [2].events = ZMQ_POLLIN |
| + # items [2].revents = 0 |
| + |
| + while (True): |
| + |
| + # // Wait while there are either requests or replies to process. |
| + rc = zmq_poll (&items [0], 2, -1) |
| + if rc < 0: |
| + return rc |
| + # // The algorithm below asumes ratio of request and replies processed |
| + # // under full load to be 1:1. Although processing requests replies |
| + # // first is tempting it is suspectible to DoS attacks (overloading |
| + # // the system with unsolicited replies). |
| + # |
| + # // Process a request. |
| + if (items [0].revents & ZMQ_POLLIN): |
| + # send in_prefix to side socket |
| + rc = zmq_msg_copy(&side_msg, in_msg_ptr) |
| + rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| + if rc < 0: |
| + return rc |
| + # relay the rest of the message |
| + rc = _relay(insocket_, outsocket_, sidesocket_, msg, side_msg, id_msg, swap_ids) |
| + if rc < 0: |
| + return rc |
| + if (items [1].revents & ZMQ_POLLIN): |
| + # send out_prefix to side socket |
| + rc = zmq_msg_copy(&side_msg, out_msg_ptr) |
| + rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| + if rc < 0: |
| + return rc |
| + # relay the rest of the message |
| + rc = _relay(outsocket_, insocket_, sidesocket_, msg, side_msg, id_msg, swap_ids) |
| + if rc < 0: |
| + return rc |
| + return 0 |
| diff --git a/zmq/devices/_zmonitoredqueue.pyx b/zmq/devices/_zmonitoredqueue.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/devices/_zmonitoredqueue.pyx |
| @@ -0,0 +1,108 @@ |
| +"""MonitoredQueue classes and functions. |
| + |
| +Authors |
| +------- |
| +* MinRK |
| +* Brian Granger |
| +""" |
| + |
| +#----------------------------------------------------------------------------- |
| +# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq |
| +# |
| +# Distributed under the terms of the New BSD License. The full license is in |
| +# the file COPYING.BSD, distributed as part of this software. |
| +#----------------------------------------------------------------------------- |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +cdef extern from "Python.h": |
| + ctypedef int Py_ssize_t |
| + |
| +from libc.string cimport memcpy |
| + |
| +from buffers cimport asbuffer_r |
| +from libzmq cimport * |
| + |
| +from zmq.core._zsocket cimport Socket |
| +from zmq.core.checkrc cimport _check_rc |
| + |
| +from zmq import ROUTER, ZMQError |
| + |
| +#----------------------------------------------------------------------------- |
| +# MonitoredQueue functions |
| +#----------------------------------------------------------------------------- |
| + |
| + |
| +def monitored_queue(Socket in_socket, Socket out_socket, Socket mon_socket, |
| + bytes in_prefix=b'in', bytes out_prefix=b'out'): |
| + """monitored_queue(in_socket, out_socket, mon_socket, |
| + in_prefix='in', out_prefix='out') |
| + |
| + Start a monitored queue device. |
| + |
| + A monitored queue behaves just like a zmq QUEUE device as far as in_socket |
| + and out_socket are concerned, except that all messages *also* go out on |
| + mon_socket. mon_socket also prefixes the messages coming from each with a |
| + prefix, by default 'in' and 'out', so all messages sent by mon_socket are |
| + multipart. |
| + |
| + The only difference between this and a QUEUE as far as in/out are |
| + concerned is that it works with two ROUTER sockets by swapping the IDENT |
| + prefixes. |
| + |
| + Parameters |
| + ---------- |
| + in_socket : Socket |
| + One of the sockets to the Queue. Its messages will be prefixed with |
| + 'in'. |
| + out_socket : Socket |
| + One of the sockets to the Queue. Its messages will be prefixed with |
| + 'out'. The only difference between in/out socket is this prefix. |
| + mon_socket : Socket |
| + This socket sends out every message received by each of the others |
| + with an in/out prefix specifying which one it was. |
| + in_prefix : str |
| + Prefix added to broadcast messages from in_socket. |
| + out_prefix : str |
| + Prefix added to broadcast messages from out_socket. |
| + """ |
| + |
| + cdef void *ins=in_socket.handle |
| + cdef void *outs=out_socket.handle |
| + cdef void *mons=mon_socket.handle |
| + cdef zmq_msg_t in_msg |
| + cdef zmq_msg_t out_msg |
| + cdef bint swap_ids |
| + cdef char *msg_c = NULL |
| + cdef Py_ssize_t msg_c_len |
| + cdef int rc |
| + |
| + # force swap_ids if both ROUTERs |
| + swap_ids = (in_socket.socket_type == ROUTER and |
| + out_socket.socket_type == ROUTER) |
| + |
| + # build zmq_msg objects from str prefixes |
| + asbuffer_r(in_prefix, <void **>&msg_c, &msg_c_len) |
| + with nogil: |
| + rc = zmq_msg_init_size(&in_msg, msg_c_len) |
| + _check_rc(rc) |
| + |
| + with nogil: |
| + memcpy(zmq_msg_data(&in_msg), msg_c, zmq_msg_size(&in_msg)) |
| + |
| + asbuffer_r(out_prefix, <void **>&msg_c, &msg_c_len) |
| + |
| + with nogil: |
| + rc = zmq_msg_init_size(&out_msg, msg_c_len) |
| + _check_rc(rc) |
| + |
| + with nogil: |
| + memcpy(zmq_msg_data(&out_msg), msg_c, zmq_msg_size(&out_msg)) |
| + rc = c_monitored_queue(ins, outs, mons, &in_msg, &out_msg, swap_ids) |
| + return rc |
| + |
| +__all__ = ['monitored_queue'] |
| diff --git a/zmq/devices/basedevice.py b/zmq/devices/basedevice.py |
| --- a/zmq/devices/basedevice.py |
| +++ b/zmq/devices/basedevice.py |
| @@ -20,8 +20,15 @@ Authors |
| #----------------------------------------------------------------------------- |
| |
| import time |
| -from threading import Thread |
| -from multiprocessing import Process |
| +try: |
| + from threading import Thread |
| +except ImportError: |
| + Thread = None |
| + |
| +try: |
| + from multiprocessing import Process |
| +except ImportError: |
| + Process = None |
| |
| from zmq import device, QUEUE, Context |
| |
| diff --git a/zmq/devices/monitoredqueue.pxd b/zmq/devices/monitoredqueue.pxd |
| deleted file mode 100644 |
| --- a/zmq/devices/monitoredqueue.pxd |
| +++ /dev/null |
| @@ -1,166 +0,0 @@ |
| -"""MonitoredQueue class declarations. |
| - |
| -Authors |
| -------- |
| -* MinRK |
| -* Brian Granger |
| -""" |
| - |
| -# |
| -# Copyright (c) 2010 Min Ragan-Kelley, Brian Granger |
| -# |
| -# This file is part of pyzmq, but is derived and adapted from zmq_queue.cpp |
| -# originally from libzmq-2.1.6, used under LGPLv3 |
| -# |
| -# pyzmq is free software; you can redistribute it and/or modify it under |
| -# the terms of the Lesser GNU General Public License as published by |
| -# the Free Software Foundation; either version 3 of the License, or |
| -# (at your option) any later version. |
| -# |
| -# pyzmq is distributed in the hope that it will be useful, |
| -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -# Lesser GNU General Public License for more details. |
| -# |
| -# You should have received a copy of the Lesser GNU General Public License |
| -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| -# |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -from libzmq cimport * |
| - |
| -#----------------------------------------------------------------------------- |
| -# MonitoredQueue C functions |
| -#----------------------------------------------------------------------------- |
| - |
| -cdef inline int _relay(void *insocket_, void *outsocket_, void *sidesocket_, |
| - zmq_msg_t msg, zmq_msg_t side_msg, zmq_msg_t id_msg, |
| - bint swap_ids) nogil: |
| - cdef int rc |
| - cdef int64_t flag_2 |
| - cdef int flag_3 |
| - cdef int flags |
| - cdef bint more |
| - cdef size_t flagsz |
| - cdef void * flag_ptr |
| - |
| - if ZMQ_VERSION_MAJOR < 3: |
| - flagsz = sizeof (int64_t) |
| - flag_ptr = &flag_2 |
| - else: |
| - flagsz = sizeof (int) |
| - flag_ptr = &flag_3 |
| - |
| - if swap_ids:# both router, must send second identity first |
| - # recv two ids into msg, id_msg |
| - rc = zmq_msg_recv(&msg, insocket_, 0) |
| - rc = zmq_msg_recv(&id_msg, insocket_, 0) |
| - |
| - # send second id (id_msg) first |
| - #!!!! always send a copy before the original !!!! |
| - rc = zmq_msg_copy(&side_msg, &id_msg) |
| - rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| - rc = zmq_msg_send(&id_msg, sidesocket_, ZMQ_SNDMORE) |
| - # send first id (msg) second |
| - rc = zmq_msg_copy(&side_msg, &msg) |
| - rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| - rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| - if rc < 0: |
| - return rc |
| - while (True): |
| - rc = zmq_msg_recv(&msg, insocket_, 0) |
| - # assert (rc == 0) |
| - rc = zmq_getsockopt (insocket_, ZMQ_RCVMORE, flag_ptr, &flagsz) |
| - flags = 0 |
| - if ZMQ_VERSION_MAJOR < 3: |
| - if flag_2: |
| - flags |= ZMQ_SNDMORE |
| - else: |
| - if flag_3: |
| - flags |= ZMQ_SNDMORE |
| - # LABEL has been removed: |
| - # rc = zmq_getsockopt (insocket_, ZMQ_RCVLABEL, flag_ptr, &flagsz) |
| - # if flag_3: |
| - # flags |= ZMQ_SNDLABEL |
| - # assert (rc == 0) |
| - |
| - rc = zmq_msg_copy(&side_msg, &msg) |
| - if flags: |
| - rc = zmq_msg_send(&side_msg, outsocket_, flags) |
| - # only SNDMORE for side-socket |
| - rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| - else: |
| - rc = zmq_msg_send(&side_msg, outsocket_, 0) |
| - rc = zmq_msg_send(&msg, sidesocket_, 0) |
| - break |
| - return rc |
| - |
| -# the MonitoredQueue C function, adapted from zmq::queue.cpp : |
| -cdef inline int c_monitored_queue (void *insocket_, void *outsocket_, |
| - void *sidesocket_, zmq_msg_t *in_msg_ptr, |
| - zmq_msg_t *out_msg_ptr, int swap_ids) nogil: |
| - """The actual C function for a monitored queue device. |
| - |
| - See ``monitored_queue()`` for details. |
| - """ |
| - |
| - cdef zmq_msg_t msg |
| - cdef int rc = zmq_msg_init (&msg) |
| - cdef zmq_msg_t id_msg |
| - rc = zmq_msg_init (&id_msg) |
| - cdef zmq_msg_t side_msg |
| - rc = zmq_msg_init (&side_msg) |
| - # assert (rc == 0) |
| - |
| - |
| - cdef zmq_pollitem_t items [2] |
| - items [0].socket = insocket_ |
| - items [0].fd = 0 |
| - items [0].events = ZMQ_POLLIN |
| - items [0].revents = 0 |
| - items [1].socket = outsocket_ |
| - items [1].fd = 0 |
| - items [1].events = ZMQ_POLLIN |
| - items [1].revents = 0 |
| - # I don't think sidesocket should be polled? |
| - # items [2].socket = sidesocket_ |
| - # items [2].fd = 0 |
| - # items [2].events = ZMQ_POLLIN |
| - # items [2].revents = 0 |
| - |
| - while (True): |
| - |
| - # // Wait while there are either requests or replies to process. |
| - rc = zmq_poll (&items [0], 2, -1) |
| - if rc < 0: |
| - return rc |
| - # // The algorithm below asumes ratio of request and replies processed |
| - # // under full load to be 1:1. Although processing requests replies |
| - # // first is tempting it is suspectible to DoS attacks (overloading |
| - # // the system with unsolicited replies). |
| - # |
| - # // Process a request. |
| - if (items [0].revents & ZMQ_POLLIN): |
| - # send in_prefix to side socket |
| - rc = zmq_msg_copy(&side_msg, in_msg_ptr) |
| - rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| - if rc < 0: |
| - return rc |
| - # relay the rest of the message |
| - rc = _relay(insocket_, outsocket_, sidesocket_, msg, side_msg, id_msg, swap_ids) |
| - if rc < 0: |
| - return rc |
| - if (items [1].revents & ZMQ_POLLIN): |
| - # send out_prefix to side socket |
| - rc = zmq_msg_copy(&side_msg, out_msg_ptr) |
| - rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| - if rc < 0: |
| - return rc |
| - # relay the rest of the message |
| - rc = _relay(outsocket_, insocket_, sidesocket_, msg, side_msg, id_msg, swap_ids) |
| - if rc < 0: |
| - return rc |
| - return 0 |
| diff --git a/zmq/devices/monitoredqueue.pyx b/zmq/devices/monitoredqueue.pyx |
| deleted file mode 100644 |
| --- a/zmq/devices/monitoredqueue.pyx |
| +++ /dev/null |
| @@ -1,108 +0,0 @@ |
| -"""MonitoredQueue classes and functions. |
| - |
| -Authors |
| -------- |
| -* MinRK |
| -* Brian Granger |
| -""" |
| - |
| -#----------------------------------------------------------------------------- |
| -# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq |
| -# |
| -# Distributed under the terms of the New BSD License. The full license is in |
| -# the file COPYING.BSD, distributed as part of this software. |
| -#----------------------------------------------------------------------------- |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -cdef extern from "Python.h": |
| - ctypedef int Py_ssize_t |
| - |
| -from libc.string cimport memcpy |
| - |
| -from buffers cimport asbuffer_r |
| -from libzmq cimport * |
| - |
| -from zmq.core.socket cimport Socket |
| -from zmq.core.checkrc cimport _check_rc |
| - |
| -from zmq import ROUTER, ZMQError |
| - |
| -#----------------------------------------------------------------------------- |
| -# MonitoredQueue functions |
| -#----------------------------------------------------------------------------- |
| - |
| - |
| -def monitored_queue(Socket in_socket, Socket out_socket, Socket mon_socket, |
| - bytes in_prefix=b'in', bytes out_prefix=b'out'): |
| - """monitored_queue(in_socket, out_socket, mon_socket, |
| - in_prefix='in', out_prefix='out') |
| - |
| - Start a monitored queue device. |
| - |
| - A monitored queue behaves just like a zmq QUEUE device as far as in_socket |
| - and out_socket are concerned, except that all messages *also* go out on |
| - mon_socket. mon_socket also prefixes the messages coming from each with a |
| - prefix, by default 'in' and 'out', so all messages sent by mon_socket are |
| - multipart. |
| - |
| - The only difference between this and a QUEUE as far as in/out are |
| - concerned is that it works with two ROUTER sockets by swapping the IDENT |
| - prefixes. |
| - |
| - Parameters |
| - ---------- |
| - in_socket : Socket |
| - One of the sockets to the Queue. Its messages will be prefixed with |
| - 'in'. |
| - out_socket : Socket |
| - One of the sockets to the Queue. Its messages will be prefixed with |
| - 'out'. The only difference between in/out socket is this prefix. |
| - mon_socket : Socket |
| - This socket sends out every message received by each of the others |
| - with an in/out prefix specifying which one it was. |
| - in_prefix : str |
| - Prefix added to broadcast messages from in_socket. |
| - out_prefix : str |
| - Prefix added to broadcast messages from out_socket. |
| - """ |
| - |
| - cdef void *ins=in_socket.handle |
| - cdef void *outs=out_socket.handle |
| - cdef void *mons=mon_socket.handle |
| - cdef zmq_msg_t in_msg |
| - cdef zmq_msg_t out_msg |
| - cdef bint swap_ids |
| - cdef char *msg_c = NULL |
| - cdef Py_ssize_t msg_c_len |
| - cdef int rc |
| - |
| - # force swap_ids if both ROUTERs |
| - swap_ids = (in_socket.socket_type == ROUTER and |
| - out_socket.socket_type == ROUTER) |
| - |
| - # build zmq_msg objects from str prefixes |
| - asbuffer_r(in_prefix, <void **>&msg_c, &msg_c_len) |
| - with nogil: |
| - rc = zmq_msg_init_size(&in_msg, msg_c_len) |
| - _check_rc(rc) |
| - |
| - with nogil: |
| - memcpy(zmq_msg_data(&in_msg), msg_c, zmq_msg_size(&in_msg)) |
| - |
| - asbuffer_r(out_prefix, <void **>&msg_c, &msg_c_len) |
| - |
| - with nogil: |
| - rc = zmq_msg_init_size(&out_msg, msg_c_len) |
| - _check_rc(rc) |
| - |
| - with nogil: |
| - memcpy(zmq_msg_data(&out_msg), msg_c, zmq_msg_size(&out_msg)) |
| - rc = c_monitored_queue(ins, outs, mons, &in_msg, &out_msg, swap_ids) |
| - return rc |
| - |
| -__all__ = ['monitored_queue'] |
| diff --git a/zmq/devices/monitoredqueuedevice.py b/zmq/devices/monitoredqueuedevice.py |
| --- a/zmq/devices/monitoredqueuedevice.py |
| +++ b/zmq/devices/monitoredqueuedevice.py |
| @@ -24,7 +24,7 @@ import time |
| |
| from zmq import ZMQError, PUB |
| from zmq.devices.proxydevice import ProxyBase, Proxy, ThreadProxy, ProcessProxy |
| -from zmq.devices.monitoredqueue import monitored_queue |
| +from zmq.devices._zmonitoredqueue import monitored_queue |
| |
| #----------------------------------------------------------------------------- |
| # Classes |
| diff --git a/zmq/sugar/backend.py b/zmq/sugar/backend.py |
| --- a/zmq/sugar/backend.py |
| +++ b/zmq/sugar/backend.py |
| @@ -23,8 +23,9 @@ try: |
| strerror, zmq_errno, |
| zmq_poll, |
| zmq_version_info, |
| - constants, |
| + _zconstants, |
| ) |
| + constants = _zconstants |
| except ImportError: |
| from zmq.cffi_core import ( |
| Context, |
| diff --git a/zmq/sugar/context.py b/zmq/sugar/context.py |
| --- a/zmq/sugar/context.py |
| +++ b/zmq/sugar/context.py |
| @@ -128,4 +128,4 @@ class Context(ContextBase, AttributeSetter): |
| else: |
| del self.sockopts[opt] |
| |
| -__all__ = ['Context'] |
| \ No newline at end of file |
| +__all__ = ['Context'] |
| diff --git a/zmq/utils/_zinitthreads.pyx b/zmq/utils/_zinitthreads.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/utils/_zinitthreads.pyx |
| @@ -0,0 +1,23 @@ |
| +"""Utility to initialize threads.""" |
| + |
| +#----------------------------------------------------------------------------- |
| +# Copyright (c) 2010 Brian Granger, Min Ragan-Kelley |
| +# |
| +# Distributed under the terms of the New BSD License. The full license is in |
| +# the file COPYING.BSD, distributed as part of this software. |
| +#----------------------------------------------------------------------------- |
| + |
| +#----------------------------------------------------------------------------- |
| +# Imports |
| +#----------------------------------------------------------------------------- |
| + |
| +cdef extern from "Python.h": |
| + cdef void PyEval_InitThreads() |
| + |
| +# It seems that in only *some* version of Python/Cython we need to call this |
| +# by hand to get threads initialized. Not clear why this is the case though. |
| +# If we don't have this, pyzmq will segfault. |
| +def init_threads(): |
| + PyEval_InitThreads() |
| + |
| +__all__ = ['init_threads'] |
| diff --git a/zmq/utils/_zrebuffer.pyx b/zmq/utils/_zrebuffer.pyx |
| new file mode 100644 |
| --- /dev/null |
| +++ b/zmq/utils/_zrebuffer.pyx |
| @@ -0,0 +1,104 @@ |
| +""" |
| +Utility for changing itemsize of memoryviews, and getting |
| +numpy arrays from byte-arrays that should be interpreted with a different |
| +itemsize. |
| + |
| +Authors |
| +------- |
| +* MinRK |
| +""" |
| + |
| +#----------------------------------------------------------------------------- |
| +# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| +# |
| +# This file is part of pyzmq |
| +# |
| +# Distributed under the terms of the New BSD License. The full license is in |
| +# the file COPYING.BSD, distributed as part of this software. |
| +#----------------------------------------------------------------------------- |
| + |
| +from libc.stdlib cimport malloc |
| +from buffers cimport * |
| + |
| +cdef inline object _rebuffer(object obj, char * format, int itemsize): |
| + """clobber the format & itemsize of a 1-D |
| + |
| + This is the Python 3 model, but will work on Python >= 2.6. Currently, |
| + we use it only on >= 3.0. |
| + """ |
| + cdef Py_buffer view |
| + cdef int flags = PyBUF_SIMPLE |
| + cdef int mode = 0 |
| + # cdef Py_ssize_t *shape, *strides, *suboffsets |
| + |
| + mode = check_buffer(obj) |
| + if mode == 0: |
| + raise TypeError("%r does not provide a buffer interface."%obj) |
| + |
| + if mode == 3: |
| + flags = PyBUF_ANY_CONTIGUOUS |
| + if format: |
| + flags |= PyBUF_FORMAT |
| + PyObject_GetBuffer(obj, &view, flags) |
| + assert view.ndim <= 1, "Can only reinterpret 1-D memoryviews" |
| + assert view.len % itemsize == 0, "Buffer of length %i not divisible into items of size %i"%(view.len, itemsize) |
| + # hack the format |
| + view.ndim = 1 |
| + view.format = format |
| + view.itemsize = itemsize |
| + view.strides = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| + view.strides[0] = itemsize |
| + view.shape = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| + view.shape[0] = view.len/itemsize |
| + view.suboffsets = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| + view.suboffsets[0] = 0 |
| + # for debug: make buffer writable, for zero-copy testing |
| + # view.readonly = 0 |
| + |
| + return PyMemoryView_FromBuffer(&view) |
| + else: |
| + raise TypeError("This funciton is only for new-style buffer objects.") |
| + |
| +def rebuffer(obj, format, itemsize): |
| + """Change the itemsize of a memoryview. |
| + |
| + Only for 1D contiguous buffers. |
| + """ |
| + return _rebuffer(obj, format, itemsize) |
| + |
| +def array_from_buffer(view, dtype, shape): |
| + """Get a numpy array from a memoryview, regardless of the itemsize of the original |
| + memoryview. This is important, because pyzmq does not send memoryview shape data |
| + over the wire, so we need to change the memoryview itemsize before calling |
| + asarray. |
| + """ |
| + import numpy |
| + A = numpy.array([],dtype=dtype) |
| + ref = viewfromobject(A,0) |
| + fmt = ref.format.encode() |
| + buf = viewfromobject(view, 0) |
| + buf = _rebuffer(view, fmt, ref.itemsize) |
| + return numpy.asarray(buf, dtype=dtype).reshape(shape) |
| + |
| +def print_view_info(obj): |
| + """simple utility for printing info on a new-style buffer object""" |
| + cdef Py_buffer view |
| + cdef int flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT |
| + cdef int mode = 0 |
| + |
| + mode = check_buffer(obj) |
| + if mode == 0: |
| + raise TypeError("%r does not provide a buffer interface."%obj) |
| + |
| + if mode == 3: |
| + PyObject_GetBuffer(obj, &view, flags) |
| + print <Py_ssize_t>view.buf, view.len, view.format, view.ndim, |
| + if view.ndim: |
| + if view.shape: |
| + print view.shape[0], |
| + if view.strides: |
| + print view.strides[0], |
| + if view.suboffsets: |
| + print view.suboffsets[0], |
| + print |
| + |
| \ No newline at end of file |
| diff --git a/zmq/utils/initthreads.pyx b/zmq/utils/initthreads.pyx |
| deleted file mode 100644 |
| --- a/zmq/utils/initthreads.pyx |
| +++ /dev/null |
| @@ -1,23 +0,0 @@ |
| -"""Utility to initialize threads.""" |
| - |
| -#----------------------------------------------------------------------------- |
| -# Copyright (c) 2010 Brian Granger, Min Ragan-Kelley |
| -# |
| -# Distributed under the terms of the New BSD License. The full license is in |
| -# the file COPYING.BSD, distributed as part of this software. |
| -#----------------------------------------------------------------------------- |
| - |
| -#----------------------------------------------------------------------------- |
| -# Imports |
| -#----------------------------------------------------------------------------- |
| - |
| -cdef extern from "Python.h": |
| - cdef void PyEval_InitThreads() |
| - |
| -# It seems that in only *some* version of Python/Cython we need to call this |
| -# by hand to get threads initialized. Not clear why this is the case though. |
| -# If we don't have this, pyzmq will segfault. |
| -def init_threads(): |
| - PyEval_InitThreads() |
| - |
| -__all__ = ['init_threads'] |
| diff --git a/zmq/utils/rebuffer.pyx b/zmq/utils/rebuffer.pyx |
| deleted file mode 100644 |
| --- a/zmq/utils/rebuffer.pyx |
| +++ /dev/null |
| @@ -1,104 +0,0 @@ |
| -""" |
| -Utility for changing itemsize of memoryviews, and getting |
| -numpy arrays from byte-arrays that should be interpreted with a different |
| -itemsize. |
| - |
| -Authors |
| -------- |
| -* MinRK |
| -""" |
| - |
| -#----------------------------------------------------------------------------- |
| -# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| -# |
| -# This file is part of pyzmq |
| -# |
| -# Distributed under the terms of the New BSD License. The full license is in |
| -# the file COPYING.BSD, distributed as part of this software. |
| -#----------------------------------------------------------------------------- |
| - |
| -from libc.stdlib cimport malloc |
| -from buffers cimport * |
| - |
| -cdef inline object _rebuffer(object obj, char * format, int itemsize): |
| - """clobber the format & itemsize of a 1-D |
| - |
| - This is the Python 3 model, but will work on Python >= 2.6. Currently, |
| - we use it only on >= 3.0. |
| - """ |
| - cdef Py_buffer view |
| - cdef int flags = PyBUF_SIMPLE |
| - cdef int mode = 0 |
| - # cdef Py_ssize_t *shape, *strides, *suboffsets |
| - |
| - mode = check_buffer(obj) |
| - if mode == 0: |
| - raise TypeError("%r does not provide a buffer interface."%obj) |
| - |
| - if mode == 3: |
| - flags = PyBUF_ANY_CONTIGUOUS |
| - if format: |
| - flags |= PyBUF_FORMAT |
| - PyObject_GetBuffer(obj, &view, flags) |
| - assert view.ndim <= 1, "Can only reinterpret 1-D memoryviews" |
| - assert view.len % itemsize == 0, "Buffer of length %i not divisible into items of size %i"%(view.len, itemsize) |
| - # hack the format |
| - view.ndim = 1 |
| - view.format = format |
| - view.itemsize = itemsize |
| - view.strides = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| - view.strides[0] = itemsize |
| - view.shape = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| - view.shape[0] = view.len/itemsize |
| - view.suboffsets = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| - view.suboffsets[0] = 0 |
| - # for debug: make buffer writable, for zero-copy testing |
| - # view.readonly = 0 |
| - |
| - return PyMemoryView_FromBuffer(&view) |
| - else: |
| - raise TypeError("This funciton is only for new-style buffer objects.") |
| - |
| -def rebuffer(obj, format, itemsize): |
| - """Change the itemsize of a memoryview. |
| - |
| - Only for 1D contiguous buffers. |
| - """ |
| - return _rebuffer(obj, format, itemsize) |
| - |
| -def array_from_buffer(view, dtype, shape): |
| - """Get a numpy array from a memoryview, regardless of the itemsize of the original |
| - memoryview. This is important, because pyzmq does not send memoryview shape data |
| - over the wire, so we need to change the memoryview itemsize before calling |
| - asarray. |
| - """ |
| - import numpy |
| - A = numpy.array([],dtype=dtype) |
| - ref = viewfromobject(A,0) |
| - fmt = ref.format.encode() |
| - buf = viewfromobject(view, 0) |
| - buf = _rebuffer(view, fmt, ref.itemsize) |
| - return numpy.asarray(buf, dtype=dtype).reshape(shape) |
| - |
| -def print_view_info(obj): |
| - """simple utility for printing info on a new-style buffer object""" |
| - cdef Py_buffer view |
| - cdef int flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT |
| - cdef int mode = 0 |
| - |
| - mode = check_buffer(obj) |
| - if mode == 0: |
| - raise TypeError("%r does not provide a buffer interface."%obj) |
| - |
| - if mode == 3: |
| - PyObject_GetBuffer(obj, &view, flags) |
| - print <Py_ssize_t>view.buf, view.len, view.format, view.ndim, |
| - if view.ndim: |
| - if view.shape: |
| - print view.shape[0], |
| - if view.strides: |
| - print view.strides[0], |
| - if view.suboffsets: |
| - print view.suboffsets[0], |
| - print |
| - |
| \ No newline at end of file |