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/>.
|
++#
|
++
|
++#-----------------------------------------------------------------------------
|
++# 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/>.
|
++#
|
++
|
++#-----------------------------------------------------------------------------
|
++# 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],
|
++ print
|
++
|
+\ 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],
|
+- print
|
+-
|
+\ No newline at end of file
|
|
|