Index: ports/python_modules/pyzmq/nacl.patch |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/ports/python_modules/pyzmq/nacl.patch |
@@ -0,0 +1,5159 @@ |
+diff --git a/buildutils/config.py b/buildutils/config.py |
+index 66f61e3..de2cd6e 100644 |
+--- 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 |
+index 0000000..15686fc |
+--- /dev/null |
++++ b/setup.cfg |
+@@ -0,0 +1,3 @@ |
++[bdist_egg] |
++plat-name = pnacl |
++ |
+diff --git a/setup.py b/setup.py |
+index 5348c61..a204e23 100755 |
+--- 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], |
+ }, |
+ ) |
+ |
+ #----------------------------------------------------------------------------- |
+ # Main setup |
+ #----------------------------------------------------------------------------- |
+diff --git a/zmq/__init__.py b/zmq/__init__.py |
+index 19cb4a9..c55ac5c 100644 |
+--- 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 |
+index 862f1d5..275e47a 100644 |
+--- 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 |
+index 0000000..99bcc27 |
+--- /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/>. |
++# |
++ |
hamaji
2014/01/24 14:32:48
Why this file need to be added? Cannot we add a co
Matthew Turk
2014/01/28 19:39:20
Thanks for the tip, didn't know about it. But it
|
++#----------------------------------------------------------------------------- |
++# 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 |
+index 0000000..799b20b |
+--- /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/>. |
++# |
++ |
hamaji
2014/01/24 14:32:48
ditto. Why added?
Matthew Turk
2014/01/28 19:39:20
Done.
|
++#----------------------------------------------------------------------------- |
++# 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 |
+index 0000000..02cf6fc |
+--- /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 |
+index 5471e73..0000000 |
+--- 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 |
+index 9db19e1..0000000 |
+--- 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 |
+index 02cf6fc..0000000 |
+--- 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 |
+index 0000000..fa2695d |
+--- /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 |
+index 0000000..e399de5 |
+--- /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 |
+index 0000000..0917c66 |
+--- /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 |
+index 0000000..85e785f |
+--- /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 |
+index 0000000..a86a8e0 |
+--- /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 |
+index 0000000..1d358ab |
+--- /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 |
+index 0000000..68f96c8 |
+--- /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 |
+index 0000000..a5e507d |
+--- /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 |
+index 0000000..5d56166 |
+--- /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 |
+index 0000000..6d2fd61 |
+--- /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 |
+index fa2695d..0000000 |
+--- 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 |
+index e399de5..0000000 |
+--- 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 |
+index 0917c66..0000000 |
+--- 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 |
+index 85e785f..0000000 |
+--- 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 |
+index a86a8e0..0000000 |
+--- 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 |
+index 1d358ab..0000000 |
+--- 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 |
+index 92253eb..0000000 |
+--- 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 |
+index 16fbf7f..0000000 |
+--- 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 |
+index 5d56166..0000000 |
+--- 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 |
+index 6d2fd61..0000000 |
+--- 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 |
+index b5c8eb3..dcae13d 100644 |
+--- 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 |
+index 0000000..e04354a |
+--- /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 |
+index 0000000..a74ae8e |
+--- /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 |
+index f65ba1f..4b2c42b 100644 |
+--- 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 |
+index e04354a..0000000 |
+--- 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 |
+index 65db882..0000000 |
+--- 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 |
+index a9f5c3f..422715c 100644 |
+--- 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 |
+index ad07379..6f87c1b 100644 |
+--- 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 |
+index bcc4686..f0f3325 100644 |
+--- 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 |
+index 0000000..6c57c9f |
+--- /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 |
+index 0000000..ca240d3 |
+--- /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], |
++ |
+\ No newline at end of file |
+diff --git a/zmq/utils/initthreads.pyx b/zmq/utils/initthreads.pyx |
+deleted file mode 100644 |
+index 6c57c9f..0000000 |
+--- 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 |
+index ca240d3..0000000 |
+--- 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], |
+- |
+\ No newline at end of file |