From 7d3be8c612e295820649779335288c197b80ccb2 Mon Sep 17 00:00:00 2001
From: Dan Klein <danklei@cisco.com>
Date: Mon, 24 Aug 2015 17:28:17 +0300
Subject: Changes location of console and fixed dependencies

---
 external_libs/python/zmq/backend/__init__.py       |  45 ++++
 external_libs/python/zmq/backend/cffi/__init__.py  |  22 ++
 external_libs/python/zmq/backend/cffi/_cdefs.h     |  68 ++++++
 external_libs/python/zmq/backend/cffi/_cffi.py     | 127 +++++++++++
 external_libs/python/zmq/backend/cffi/_poll.py     |  56 +++++
 external_libs/python/zmq/backend/cffi/_verify.c    |  12 +
 external_libs/python/zmq/backend/cffi/constants.py |  15 ++
 external_libs/python/zmq/backend/cffi/context.py   | 100 +++++++++
 external_libs/python/zmq/backend/cffi/devices.py   |  24 ++
 external_libs/python/zmq/backend/cffi/error.py     |  13 ++
 external_libs/python/zmq/backend/cffi/message.py   |  69 ++++++
 external_libs/python/zmq/backend/cffi/socket.py    | 244 +++++++++++++++++++++
 external_libs/python/zmq/backend/cffi/utils.py     |  62 ++++++
 .../python/zmq/backend/cython/__init__.py          |  23 ++
 external_libs/python/zmq/backend/cython/_device.py |   7 +
 external_libs/python/zmq/backend/cython/_poll.py   |   7 +
 .../python/zmq/backend/cython/_version.py          |   7 +
 .../python/zmq/backend/cython/checkrc.pxd          |  23 ++
 .../python/zmq/backend/cython/constants.py         |   7 +
 .../python/zmq/backend/cython/context.pxd          |  41 ++++
 external_libs/python/zmq/backend/cython/context.py |   7 +
 external_libs/python/zmq/backend/cython/error.py   |   7 +
 external_libs/python/zmq/backend/cython/libzmq.pxd | 110 ++++++++++
 .../python/zmq/backend/cython/message.pxd          |  63 ++++++
 external_libs/python/zmq/backend/cython/message.py |   7 +
 external_libs/python/zmq/backend/cython/socket.pxd |  47 ++++
 external_libs/python/zmq/backend/cython/socket.py  |   7 +
 external_libs/python/zmq/backend/cython/utils.pxd  |  29 +++
 external_libs/python/zmq/backend/cython/utils.py   |   7 +
 external_libs/python/zmq/backend/select.py         |  39 ++++
 30 files changed, 1295 insertions(+)
 create mode 100644 external_libs/python/zmq/backend/__init__.py
 create mode 100644 external_libs/python/zmq/backend/cffi/__init__.py
 create mode 100644 external_libs/python/zmq/backend/cffi/_cdefs.h
 create mode 100644 external_libs/python/zmq/backend/cffi/_cffi.py
 create mode 100644 external_libs/python/zmq/backend/cffi/_poll.py
 create mode 100644 external_libs/python/zmq/backend/cffi/_verify.c
 create mode 100644 external_libs/python/zmq/backend/cffi/constants.py
 create mode 100644 external_libs/python/zmq/backend/cffi/context.py
 create mode 100644 external_libs/python/zmq/backend/cffi/devices.py
 create mode 100644 external_libs/python/zmq/backend/cffi/error.py
 create mode 100644 external_libs/python/zmq/backend/cffi/message.py
 create mode 100644 external_libs/python/zmq/backend/cffi/socket.py
 create mode 100644 external_libs/python/zmq/backend/cffi/utils.py
 create mode 100644 external_libs/python/zmq/backend/cython/__init__.py
 create mode 100644 external_libs/python/zmq/backend/cython/_device.py
 create mode 100644 external_libs/python/zmq/backend/cython/_poll.py
 create mode 100644 external_libs/python/zmq/backend/cython/_version.py
 create mode 100644 external_libs/python/zmq/backend/cython/checkrc.pxd
 create mode 100644 external_libs/python/zmq/backend/cython/constants.py
 create mode 100644 external_libs/python/zmq/backend/cython/context.pxd
 create mode 100644 external_libs/python/zmq/backend/cython/context.py
 create mode 100644 external_libs/python/zmq/backend/cython/error.py
 create mode 100644 external_libs/python/zmq/backend/cython/libzmq.pxd
 create mode 100644 external_libs/python/zmq/backend/cython/message.pxd
 create mode 100644 external_libs/python/zmq/backend/cython/message.py
 create mode 100644 external_libs/python/zmq/backend/cython/socket.pxd
 create mode 100644 external_libs/python/zmq/backend/cython/socket.py
 create mode 100644 external_libs/python/zmq/backend/cython/utils.pxd
 create mode 100644 external_libs/python/zmq/backend/cython/utils.py
 create mode 100644 external_libs/python/zmq/backend/select.py

(limited to 'external_libs/python/zmq/backend')

diff --git a/external_libs/python/zmq/backend/__init__.py b/external_libs/python/zmq/backend/__init__.py
new file mode 100644
index 00000000..7cac725c
--- /dev/null
+++ b/external_libs/python/zmq/backend/__init__.py
@@ -0,0 +1,45 @@
+"""Import basic exposure of libzmq C API as a backend"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+
+import os
+import platform
+import sys
+
+from zmq.utils.sixcerpt import reraise
+
+from .select import public_api, select_backend
+
+if 'PYZMQ_BACKEND' in os.environ:
+    backend = os.environ['PYZMQ_BACKEND']
+    if backend in ('cython', 'cffi'):
+        backend = 'zmq.backend.%s' % backend
+    _ns = select_backend(backend)
+else:
+    # default to cython, fallback to cffi
+    # (reverse on PyPy)
+    if platform.python_implementation() == 'PyPy':
+        first, second = ('zmq.backend.cffi', 'zmq.backend.cython')
+    else:
+        first, second = ('zmq.backend.cython', 'zmq.backend.cffi')
+
+    try:
+        _ns = select_backend(first)
+    except Exception:
+        exc_info = sys.exc_info()
+        exc = exc_info[1]
+        try:
+            _ns = select_backend(second)
+        except ImportError:
+            # prevent 'During handling of the above exception...' on py3
+            # can't use `raise ... from` on Python 2
+            if hasattr(exc, '__cause__'):
+                exc.__cause__ = None
+            # raise the *first* error, not the fallback
+            reraise(*exc_info)
+
+globals().update(_ns)
+
+__all__ = public_api
diff --git a/external_libs/python/zmq/backend/cffi/__init__.py b/external_libs/python/zmq/backend/cffi/__init__.py
new file mode 100644
index 00000000..ca3164d3
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/__init__.py
@@ -0,0 +1,22 @@
+"""CFFI backend (for PyPY)"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+from zmq.backend.cffi import (constants, error, message, context, socket,
+                           _poll, devices, utils)
+
+__all__ = []
+for submod in (constants, error, message, context, socket,
+               _poll, devices, utils):
+    __all__.extend(submod.__all__)
+
+from .constants import *
+from .error import *
+from .message import *
+from .context import *
+from .socket import *
+from .devices import *
+from ._poll import *
+from ._cffi import zmq_version_info, ffi
+from .utils import *
diff --git a/external_libs/python/zmq/backend/cffi/_cdefs.h b/external_libs/python/zmq/backend/cffi/_cdefs.h
new file mode 100644
index 00000000..d3300575
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/_cdefs.h
@@ -0,0 +1,68 @@
+void zmq_version(int *major, int *minor, int *patch);
+
+void* zmq_socket(void *context, int type);
+int zmq_close(void *socket);
+
+int zmq_bind(void *socket, const char *endpoint);
+int zmq_connect(void *socket, const char *endpoint);
+
+int zmq_errno(void);
+const char * zmq_strerror(int errnum);
+
+void* zmq_stopwatch_start(void);
+unsigned long zmq_stopwatch_stop(void *watch);
+void zmq_sleep(int seconds_);
+int zmq_device(int device, void *frontend, void *backend);
+
+int zmq_unbind(void *socket, const char *endpoint);
+int zmq_disconnect(void *socket, const char *endpoint);
+void* zmq_ctx_new();
+int zmq_ctx_destroy(void *context);
+int zmq_ctx_get(void *context, int opt);
+int zmq_ctx_set(void *context, int opt, int optval);
+int zmq_proxy(void *frontend, void *backend, void *capture);
+int zmq_socket_monitor(void *socket, const char *addr, int events);
+
+int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);
+int zmq_has (const char *capability);
+
+typedef struct { ...; } zmq_msg_t;
+typedef ... zmq_free_fn;
+
+int zmq_msg_init(zmq_msg_t *msg);
+int zmq_msg_init_size(zmq_msg_t *msg, size_t size);
+int zmq_msg_init_data(zmq_msg_t *msg,
+                      void *data,
+                      size_t size,
+                      zmq_free_fn *ffn,
+                      void *hint);
+
+size_t zmq_msg_size(zmq_msg_t *msg);
+void *zmq_msg_data(zmq_msg_t *msg);
+int zmq_msg_close(zmq_msg_t *msg);
+
+int zmq_msg_send(zmq_msg_t *msg, void *socket, int flags);
+int zmq_msg_recv(zmq_msg_t *msg, void *socket, int flags);
+
+int zmq_getsockopt(void *socket,
+                   int option_name,
+                   void *option_value,
+                   size_t *option_len);
+
+int zmq_setsockopt(void *socket,
+                   int option_name,
+                   const void *option_value,
+                   size_t option_len);
+typedef struct
+{
+    void *socket;
+    int fd;
+    short events;
+    short revents;
+} zmq_pollitem_t;
+
+int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout);
+
+// miscellany
+void * memcpy(void *restrict s1, const void *restrict s2, size_t n);
+int get_ipc_path_max_len(void);
diff --git a/external_libs/python/zmq/backend/cffi/_cffi.py b/external_libs/python/zmq/backend/cffi/_cffi.py
new file mode 100644
index 00000000..c73ebf83
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/_cffi.py
@@ -0,0 +1,127 @@
+# coding: utf-8
+"""The main CFFI wrapping of libzmq"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+
+import json
+import os
+from os.path import dirname, join
+from cffi import FFI
+
+from zmq.utils.constant_names import all_names, no_prefix
+
+
+base_zmq_version = (3,2,2)
+
+def load_compiler_config():
+    """load pyzmq compiler arguments"""
+    import zmq
+    zmq_dir = dirname(zmq.__file__)
+    zmq_parent = dirname(zmq_dir)
+    
+    fname = join(zmq_dir, 'utils', 'compiler.json')
+    if os.path.exists(fname):
+        with open(fname) as f:
+            cfg = json.load(f)
+    else:
+        cfg = {}
+    
+    cfg.setdefault("include_dirs", [])
+    cfg.setdefault("library_dirs", [])
+    cfg.setdefault("runtime_library_dirs", [])
+    cfg.setdefault("libraries", ["zmq"])
+    
+    # cast to str, because cffi can't handle unicode paths (?!)
+    cfg['libraries'] = [str(lib) for lib in cfg['libraries']]
+    for key in ("include_dirs", "library_dirs", "runtime_library_dirs"):
+        # interpret paths relative to parent of zmq (like source tree)
+        abs_paths = []
+        for p in cfg[key]:
+            if p.startswith('zmq'):
+                p = join(zmq_parent, p)
+            abs_paths.append(str(p))
+        cfg[key] = abs_paths
+    return cfg
+
+
+def zmq_version_info():
+    """Get libzmq version as tuple of ints"""
+    major = ffi.new('int*')
+    minor = ffi.new('int*')
+    patch = ffi.new('int*')
+
+    C.zmq_version(major, minor, patch)
+
+    return (int(major[0]), int(minor[0]), int(patch[0]))
+
+
+cfg = load_compiler_config()
+ffi = FFI()
+
+def _make_defines(names):
+    _names = []
+    for name in names:
+        define_line = "#define %s ..." % (name)
+        _names.append(define_line)
+
+    return "\n".join(_names)
+
+c_constant_names = []
+for name in all_names:
+    if no_prefix(name):
+        c_constant_names.append(name)
+    else:
+        c_constant_names.append("ZMQ_" + name)
+
+# load ffi definitions
+here = os.path.dirname(__file__)
+with open(os.path.join(here, '_cdefs.h')) as f:
+    _cdefs = f.read()
+
+with open(os.path.join(here, '_verify.c')) as f:
+    _verify = f.read()
+
+ffi.cdef(_cdefs)
+ffi.cdef(_make_defines(c_constant_names))
+
+try:
+    C = ffi.verify(_verify,
+        modulename='_cffi_ext',
+        libraries=cfg['libraries'],
+        include_dirs=cfg['include_dirs'],
+        library_dirs=cfg['library_dirs'],
+        runtime_library_dirs=cfg['runtime_library_dirs'],
+    )
+    _version_info = zmq_version_info()
+except Exception as e:
+    raise ImportError("PyZMQ CFFI backend couldn't find zeromq: %s\n"
+    "Please check that you have zeromq headers and libraries." % e)
+
+if _version_info < (3,2,2):
+    raise ImportError("PyZMQ CFFI backend requires zeromq >= 3.2.2,"
+        " but found %i.%i.%i" % _version_info
+    )
+
+nsp = new_sizet_pointer = lambda length: ffi.new('size_t*', length)
+
+new_uint64_pointer = lambda: (ffi.new('uint64_t*'),
+                              nsp(ffi.sizeof('uint64_t')))
+new_int64_pointer = lambda: (ffi.new('int64_t*'),
+                             nsp(ffi.sizeof('int64_t')))
+new_int_pointer = lambda: (ffi.new('int*'),
+                           nsp(ffi.sizeof('int')))
+new_binary_data = lambda length: (ffi.new('char[%d]' % (length)),
+                                  nsp(ffi.sizeof('char') * length))
+
+value_uint64_pointer = lambda val : (ffi.new('uint64_t*', val),
+                                     ffi.sizeof('uint64_t'))
+value_int64_pointer = lambda val: (ffi.new('int64_t*', val),
+                                   ffi.sizeof('int64_t'))
+value_int_pointer = lambda val: (ffi.new('int*', val),
+                                 ffi.sizeof('int'))
+value_binary_data = lambda val, length: (ffi.new('char[%d]' % (length + 1), val),
+                                         ffi.sizeof('char') * length)
+
+IPC_PATH_MAX_LEN = C.get_ipc_path_max_len()
diff --git a/external_libs/python/zmq/backend/cffi/_poll.py b/external_libs/python/zmq/backend/cffi/_poll.py
new file mode 100644
index 00000000..9bca34ca
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/_poll.py
@@ -0,0 +1,56 @@
+# coding: utf-8
+"""zmq poll function"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+from ._cffi import C, ffi, zmq_version_info
+
+from .constants import *
+
+from zmq.error import _check_rc
+
+
+def _make_zmq_pollitem(socket, flags):
+    zmq_socket = socket._zmq_socket
+    zmq_pollitem = ffi.new('zmq_pollitem_t*')
+    zmq_pollitem.socket = zmq_socket
+    zmq_pollitem.fd = 0
+    zmq_pollitem.events = flags
+    zmq_pollitem.revents = 0
+    return zmq_pollitem[0]
+
+def _make_zmq_pollitem_fromfd(socket_fd, flags):
+    zmq_pollitem = ffi.new('zmq_pollitem_t*')
+    zmq_pollitem.socket = ffi.NULL
+    zmq_pollitem.fd = socket_fd
+    zmq_pollitem.events = flags
+    zmq_pollitem.revents = 0
+    return zmq_pollitem[0]
+
+def zmq_poll(sockets, timeout):
+    cffi_pollitem_list = []
+    low_level_to_socket_obj = {}
+    for item in sockets:
+        if isinstance(item[0], int):
+            low_level_to_socket_obj[item[0]] = item
+            cffi_pollitem_list.append(_make_zmq_pollitem_fromfd(item[0], item[1]))
+        else:
+            low_level_to_socket_obj[item[0]._zmq_socket] = item
+            cffi_pollitem_list.append(_make_zmq_pollitem(item[0], item[1]))
+    items = ffi.new('zmq_pollitem_t[]', cffi_pollitem_list)
+    list_length = ffi.cast('int', len(cffi_pollitem_list))
+    c_timeout = ffi.cast('long', timeout)
+    rc = C.zmq_poll(items, list_length, c_timeout)
+    _check_rc(rc)
+    result = []
+    for index in range(len(items)):
+        if not items[index].socket == ffi.NULL:
+            if items[index].revents > 0:
+                result.append((low_level_to_socket_obj[items[index].socket][0],
+                            items[index].revents))
+        else:
+            result.append((items[index].fd, items[index].revents))
+    return result
+
+__all__ = ['zmq_poll']
diff --git a/external_libs/python/zmq/backend/cffi/_verify.c b/external_libs/python/zmq/backend/cffi/_verify.c
new file mode 100644
index 00000000..547840eb
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/_verify.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <sys/un.h>
+#include <string.h>
+
+#include <zmq.h>
+#include <zmq_utils.h>
+#include "zmq_compat.h"
+
+int get_ipc_path_max_len(void) {
+    struct sockaddr_un *dummy;
+    return sizeof(dummy->sun_path) - 1;
+}
diff --git a/external_libs/python/zmq/backend/cffi/constants.py b/external_libs/python/zmq/backend/cffi/constants.py
new file mode 100644
index 00000000..ee293e74
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/constants.py
@@ -0,0 +1,15 @@
+# coding: utf-8
+"""zmq constants"""
+
+from ._cffi import C, c_constant_names
+from zmq.utils.constant_names import all_names
+
+g = globals()
+for cname in c_constant_names:
+    if cname.startswith("ZMQ_"):
+        name = cname[4:]
+    else:
+        name = cname
+    g[name] = getattr(C, cname)
+
+__all__ = all_names
diff --git a/external_libs/python/zmq/backend/cffi/context.py b/external_libs/python/zmq/backend/cffi/context.py
new file mode 100644
index 00000000..16a7b257
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/context.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+"""zmq Context class"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+import weakref
+
+from ._cffi import C, ffi
+
+from .socket import *
+from .constants import *
+
+from zmq.error import ZMQError, _check_rc
+
+class Context(object):
+    _zmq_ctx = None
+    _iothreads = None
+    _closed = None
+    _sockets = None
+    _shadow = False
+
+    def __init__(self, io_threads=1, shadow=None):
+        
+        if shadow:
+            self._zmq_ctx = ffi.cast("void *", shadow)
+            self._shadow = True
+        else:
+            self._shadow = False
+            if not io_threads >= 0:
+                raise ZMQError(EINVAL)
+        
+            self._zmq_ctx = C.zmq_ctx_new()
+        if self._zmq_ctx == ffi.NULL:
+            raise ZMQError(C.zmq_errno())
+        if not shadow:
+            C.zmq_ctx_set(self._zmq_ctx, IO_THREADS, io_threads)
+        self._closed = False
+        self._sockets = set()
+    
+    @property
+    def underlying(self):
+        """The address of the underlying libzmq context"""
+        return int(ffi.cast('size_t', self._zmq_ctx))
+    
+    @property
+    def closed(self):
+        return self._closed
+
+    def _add_socket(self, socket):
+        ref = weakref.ref(socket)
+        self._sockets.add(ref)
+        return ref
+
+    def _rm_socket(self, ref):
+        if ref in self._sockets:
+            self._sockets.remove(ref)
+
+    def set(self, option, value):
+        """set a context option
+        
+        see zmq_ctx_set
+        """
+        rc = C.zmq_ctx_set(self._zmq_ctx, option, value)
+        _check_rc(rc)
+
+    def get(self, option):
+        """get context option
+        
+        see zmq_ctx_get
+        """
+        rc = C.zmq_ctx_get(self._zmq_ctx, option)
+        _check_rc(rc)
+        return rc
+
+    def term(self):
+        if self.closed:
+            return
+
+        C.zmq_ctx_destroy(self._zmq_ctx)
+
+        self._zmq_ctx = None
+        self._closed = True
+
+    def destroy(self, linger=None):
+        if self.closed:
+            return
+
+        sockets = self._sockets
+        self._sockets = set()
+        for s in sockets:
+            s = s()
+            if s and not s.closed:
+                if linger:
+                    s.setsockopt(LINGER, linger)
+                s.close()
+        
+        self.term()
+
+__all__ = ['Context']
diff --git a/external_libs/python/zmq/backend/cffi/devices.py b/external_libs/python/zmq/backend/cffi/devices.py
new file mode 100644
index 00000000..c7a514a8
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/devices.py
@@ -0,0 +1,24 @@
+# coding: utf-8
+"""zmq device functions"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+from ._cffi import C, ffi, zmq_version_info
+from .socket import Socket
+from zmq.error import ZMQError, _check_rc
+
+def device(device_type, frontend, backend):
+    rc = C.zmq_proxy(frontend._zmq_socket, backend._zmq_socket, ffi.NULL)
+    _check_rc(rc)
+
+def proxy(frontend, backend, capture=None):
+    if isinstance(capture, Socket):
+        capture = capture._zmq_socket
+    else:
+        capture = ffi.NULL
+
+    rc = C.zmq_proxy(frontend._zmq_socket, backend._zmq_socket, capture)
+    _check_rc(rc)
+
+__all__ = ['device', 'proxy']
diff --git a/external_libs/python/zmq/backend/cffi/error.py b/external_libs/python/zmq/backend/cffi/error.py
new file mode 100644
index 00000000..3bb64de0
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/error.py
@@ -0,0 +1,13 @@
+"""zmq error functions"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+from ._cffi import C, ffi
+
+def strerror(errno):
+    return ffi.string(C.zmq_strerror(errno))
+
+zmq_errno = C.zmq_errno
+
+__all__ = ['strerror', 'zmq_errno']
diff --git a/external_libs/python/zmq/backend/cffi/message.py b/external_libs/python/zmq/backend/cffi/message.py
new file mode 100644
index 00000000..c35decb6
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/message.py
@@ -0,0 +1,69 @@
+"""Dummy Frame object"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+from ._cffi import ffi, C
+
+import zmq
+from zmq.utils.strtypes import unicode
+
+try:
+    view = memoryview
+except NameError:
+    view = buffer
+
+_content = lambda x: x.tobytes() if type(x) == memoryview else x
+
+class Frame(object):
+    _data = None
+    tracker = None
+    closed = False
+    more = False
+    buffer = None
+
+
+    def __init__(self, data, track=False):
+        try:
+            view(data)
+        except TypeError:
+            raise
+
+        self._data = data
+
+        if isinstance(data, unicode):
+            raise TypeError("Unicode objects not allowed. Only: str/bytes, " +
+                            "buffer interfaces.")
+
+        self.more = False
+        self.tracker = None
+        self.closed = False
+        if track:
+            self.tracker = zmq.MessageTracker()
+
+        self.buffer = view(self.bytes)
+
+    @property
+    def bytes(self):
+        data = _content(self._data)
+        return data
+
+    def __len__(self):
+        return len(self.bytes)
+
+    def __eq__(self, other):
+        return self.bytes == _content(other)
+
+    def __str__(self):
+        if str is unicode:
+            return self.bytes.decode()
+        else:
+            return self.bytes
+
+    @property
+    def done(self):
+        return True
+
+Message = Frame
+
+__all__ = ['Frame', 'Message']
diff --git a/external_libs/python/zmq/backend/cffi/socket.py b/external_libs/python/zmq/backend/cffi/socket.py
new file mode 100644
index 00000000..3c427739
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/socket.py
@@ -0,0 +1,244 @@
+# coding: utf-8
+"""zmq Socket class"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+import random
+import codecs
+
+import errno as errno_mod
+
+from ._cffi import (C, ffi, new_uint64_pointer, new_int64_pointer,
+                    new_int_pointer, new_binary_data, value_uint64_pointer,
+                    value_int64_pointer, value_int_pointer, value_binary_data,
+                    IPC_PATH_MAX_LEN)
+
+from .message import Frame
+from .constants import *
+
+import zmq
+from zmq.error import ZMQError, _check_rc, _check_version
+from zmq.utils.strtypes import unicode
+
+
+def new_pointer_from_opt(option, length=0):
+    from zmq.sugar.constants import (
+        int64_sockopts, bytes_sockopts,
+    )
+    if option in int64_sockopts:
+        return new_int64_pointer()
+    elif option in bytes_sockopts:
+        return new_binary_data(length)
+    else:
+        # default
+        return new_int_pointer()
+
+def value_from_opt_pointer(option, opt_pointer, length=0):
+    from zmq.sugar.constants import (
+        int64_sockopts, bytes_sockopts,
+    )
+    if option in int64_sockopts:
+        return int(opt_pointer[0])
+    elif option in bytes_sockopts:
+        return ffi.buffer(opt_pointer, length)[:]
+    else:
+        return int(opt_pointer[0])
+
+def initialize_opt_pointer(option, value, length=0):
+    from zmq.sugar.constants import (
+        int64_sockopts, bytes_sockopts,
+    )
+    if option in int64_sockopts:
+        return value_int64_pointer(value)
+    elif option in bytes_sockopts:
+        return value_binary_data(value, length)
+    else:
+        return value_int_pointer(value)
+
+
+class Socket(object):
+    context = None
+    socket_type = None
+    _zmq_socket = None
+    _closed = None
+    _ref = None
+    _shadow = False
+
+    def __init__(self, context=None, socket_type=None, shadow=None):
+        self.context = context
+        if shadow is not None:
+            self._zmq_socket = ffi.cast("void *", shadow)
+            self._shadow = True
+        else:
+            self._shadow = False
+            self._zmq_socket = C.zmq_socket(context._zmq_ctx, socket_type)
+        if self._zmq_socket == ffi.NULL:
+            raise ZMQError()
+        self._closed = False
+        if context:
+            self._ref = context._add_socket(self)
+    
+    @property
+    def underlying(self):
+        """The address of the underlying libzmq socket"""
+        return int(ffi.cast('size_t', self._zmq_socket))
+    
+    @property
+    def closed(self):
+        return self._closed
+
+    def close(self, linger=None):
+        rc = 0
+        if not self._closed and hasattr(self, '_zmq_socket'):
+            if self._zmq_socket is not None:
+                rc = C.zmq_close(self._zmq_socket)
+            self._closed = True
+            if self.context:
+                self.context._rm_socket(self._ref)
+        return rc
+
+    def bind(self, address):
+        if isinstance(address, unicode):
+            address = address.encode('utf8')
+        rc = C.zmq_bind(self._zmq_socket, address)
+        if rc < 0:
+            if IPC_PATH_MAX_LEN and C.zmq_errno() == errno_mod.ENAMETOOLONG:
+                # py3compat: address is bytes, but msg wants str
+                if str is unicode:
+                    address = address.decode('utf-8', 'replace')
+                path = address.split('://', 1)[-1]
+                msg = ('ipc path "{0}" is longer than {1} '
+                                'characters (sizeof(sockaddr_un.sun_path)).'
+                                .format(path, IPC_PATH_MAX_LEN))
+                raise ZMQError(C.zmq_errno(), msg=msg)
+            else:
+                _check_rc(rc)
+
+    def unbind(self, address):
+        _check_version((3,2), "unbind")
+        if isinstance(address, unicode):
+            address = address.encode('utf8')
+        rc = C.zmq_unbind(self._zmq_socket, address)
+        _check_rc(rc)
+
+    def connect(self, address):
+        if isinstance(address, unicode):
+            address = address.encode('utf8')
+        rc = C.zmq_connect(self._zmq_socket, address)
+        _check_rc(rc)
+
+    def disconnect(self, address):
+        _check_version((3,2), "disconnect")
+        if isinstance(address, unicode):
+            address = address.encode('utf8')
+        rc = C.zmq_disconnect(self._zmq_socket, address)
+        _check_rc(rc)
+
+    def set(self, option, value):
+        length = None
+        if isinstance(value, unicode):
+            raise TypeError("unicode not allowed, use bytes")
+        
+        if isinstance(value, bytes):
+            if option not in zmq.constants.bytes_sockopts:
+                raise TypeError("not a bytes sockopt: %s" % option)
+            length = len(value)
+        
+        c_data = initialize_opt_pointer(option, value, length)
+
+        c_value_pointer = c_data[0]
+        c_sizet = c_data[1]
+
+        rc = C.zmq_setsockopt(self._zmq_socket,
+                               option,
+                               ffi.cast('void*', c_value_pointer),
+                               c_sizet)
+        _check_rc(rc)
+
+    def get(self, option):
+        c_data = new_pointer_from_opt(option, length=255)
+
+        c_value_pointer = c_data[0]
+        c_sizet_pointer = c_data[1]
+
+        rc = C.zmq_getsockopt(self._zmq_socket,
+                               option,
+                               c_value_pointer,
+                               c_sizet_pointer)
+        _check_rc(rc)
+        
+        sz = c_sizet_pointer[0]
+        v = value_from_opt_pointer(option, c_value_pointer, sz)
+        if option != zmq.IDENTITY and option in zmq.constants.bytes_sockopts and v.endswith(b'\0'):
+            v = v[:-1]
+        return v
+
+    def send(self, message, flags=0, copy=False, track=False):
+        if isinstance(message, unicode):
+            raise TypeError("Message must be in bytes, not an unicode Object")
+
+        if isinstance(message, Frame):
+            message = message.bytes
+
+        zmq_msg = ffi.new('zmq_msg_t*')
+        c_message = ffi.new('char[]', message)
+        rc = C.zmq_msg_init_size(zmq_msg, len(message))
+        C.memcpy(C.zmq_msg_data(zmq_msg), c_message, len(message))
+
+        rc = C.zmq_msg_send(zmq_msg, self._zmq_socket, flags)
+        C.zmq_msg_close(zmq_msg)
+        _check_rc(rc)
+
+        if track:
+            return zmq.MessageTracker()
+
+    def recv(self, flags=0, copy=True, track=False):
+        zmq_msg = ffi.new('zmq_msg_t*')
+        C.zmq_msg_init(zmq_msg)
+
+        rc = C.zmq_msg_recv(zmq_msg, self._zmq_socket, flags)
+
+        if rc < 0:
+            C.zmq_msg_close(zmq_msg)
+            _check_rc(rc)
+
+        _buffer = ffi.buffer(C.zmq_msg_data(zmq_msg), C.zmq_msg_size(zmq_msg))
+        value = _buffer[:]
+        C.zmq_msg_close(zmq_msg)
+
+        frame = Frame(value, track=track)
+        frame.more = self.getsockopt(RCVMORE)
+
+        if copy:
+            return frame.bytes
+        else:
+            return frame
+    
+    def monitor(self, addr, events=-1):
+        """s.monitor(addr, flags)
+
+        Start publishing socket events on inproc.
+        See libzmq docs for zmq_monitor for details.
+        
+        Note: requires libzmq >= 3.2
+        
+        Parameters
+        ----------
+        addr : str
+            The inproc url used for monitoring. Passing None as
+            the addr will cause an existing socket monitor to be
+            deregistered.
+        events : int [default: zmq.EVENT_ALL]
+            The zmq event bitmask for which events will be sent to the monitor.
+        """
+        
+        _check_version((3,2), "monitor")
+        if events < 0:
+            events = zmq.EVENT_ALL
+        if addr is None:
+            addr = ffi.NULL
+        rc = C.zmq_socket_monitor(self._zmq_socket, addr, events)
+
+
+__all__ = ['Socket', 'IPC_PATH_MAX_LEN']
diff --git a/external_libs/python/zmq/backend/cffi/utils.py b/external_libs/python/zmq/backend/cffi/utils.py
new file mode 100644
index 00000000..fde7827b
--- /dev/null
+++ b/external_libs/python/zmq/backend/cffi/utils.py
@@ -0,0 +1,62 @@
+# coding: utf-8
+"""miscellaneous zmq_utils wrapping"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+from ._cffi import ffi, C
+
+from zmq.error import ZMQError, _check_rc, _check_version
+from zmq.utils.strtypes import unicode
+
+def has(capability):
+    """Check for zmq capability by name (e.g. 'ipc', 'curve')
+    
+    .. versionadded:: libzmq-4.1
+    .. versionadded:: 14.1
+    """
+    _check_version((4,1), 'zmq.has')
+    if isinstance(capability, unicode):
+        capability = capability.encode('utf8')
+    return bool(C.zmq_has(capability))
+    
+def curve_keypair():
+    """generate a Z85 keypair for use with zmq.CURVE security
+    
+    Requires libzmq (≥ 4.0) to have been linked with libsodium.
+    
+    Returns
+    -------
+    (public, secret) : two bytestrings
+        The public and private keypair as 40 byte z85-encoded bytestrings.
+    """
+    _check_version((3,2), "monitor")
+    public = ffi.new('char[64]')
+    private = ffi.new('char[64]')
+    rc = C.zmq_curve_keypair(public, private)
+    _check_rc(rc)
+    return ffi.buffer(public)[:40], ffi.buffer(private)[:40]
+
+
+class Stopwatch(object):
+    def __init__(self):
+        self.watch = ffi.NULL
+
+    def start(self):
+        if self.watch == ffi.NULL:
+            self.watch = C.zmq_stopwatch_start()
+        else:
+            raise ZMQError('Stopwatch is already runing.')
+
+    def stop(self):
+        if self.watch == ffi.NULL:
+            raise ZMQError('Must start the Stopwatch before calling stop.')
+        else:
+            time = C.zmq_stopwatch_stop(self.watch)
+            self.watch = ffi.NULL
+            return time
+
+    def sleep(self, seconds):
+        C.zmq_sleep(seconds)
+
+__all__ = ['has', 'curve_keypair', 'Stopwatch']
diff --git a/external_libs/python/zmq/backend/cython/__init__.py b/external_libs/python/zmq/backend/cython/__init__.py
new file mode 100644
index 00000000..e5358185
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/__init__.py
@@ -0,0 +1,23 @@
+"""Python bindings for core 0MQ objects."""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Lesser GNU Public License (LGPL).
+
+from . import (constants, error, message, context,
+                      socket, utils, _poll, _version, _device )
+
+__all__ = []
+for submod in (constants, error, message, context,
+               socket, utils, _poll, _version, _device):
+    __all__.extend(submod.__all__)
+
+from .constants import *
+from .error import *
+from .message import *
+from .context import *
+from .socket import *
+from ._poll import *
+from .utils import *
+from ._device import *
+from ._version import *
+
diff --git a/external_libs/python/zmq/backend/cython/_device.py b/external_libs/python/zmq/backend/cython/_device.py
new file mode 100644
index 00000000..3368ca2c
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/_device.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'_device.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/_poll.py b/external_libs/python/zmq/backend/cython/_poll.py
new file mode 100644
index 00000000..cb1d5d77
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/_poll.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'_poll.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/_version.py b/external_libs/python/zmq/backend/cython/_version.py
new file mode 100644
index 00000000..08262706
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/_version.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'_version.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/checkrc.pxd b/external_libs/python/zmq/backend/cython/checkrc.pxd
new file mode 100644
index 00000000..3bf69fc3
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/checkrc.pxd
@@ -0,0 +1,23 @@
+from libc.errno cimport EINTR, EAGAIN
+from cpython cimport PyErr_CheckSignals
+from libzmq cimport zmq_errno, ZMQ_ETERM
+
+cdef inline int _check_rc(int rc) except -1:
+    """internal utility for checking zmq return condition
+    
+    and raising the appropriate Exception class
+    """
+    cdef int errno = zmq_errno()
+    PyErr_CheckSignals()
+    if rc < 0:
+        if errno == EAGAIN:
+            from zmq.error import Again
+            raise Again(errno)
+        elif errno == ZMQ_ETERM:
+            from zmq.error import ContextTerminated
+            raise ContextTerminated(errno)
+        else:
+            from zmq.error import ZMQError
+            raise ZMQError(errno)
+        # return -1
+    return 0
diff --git a/external_libs/python/zmq/backend/cython/constants.py b/external_libs/python/zmq/backend/cython/constants.py
new file mode 100644
index 00000000..ea772ac0
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/constants.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'constants.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/context.pxd b/external_libs/python/zmq/backend/cython/context.pxd
new file mode 100644
index 00000000..9c9267a5
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/context.pxd
@@ -0,0 +1,41 @@
+"""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:
+
+    cdef object __weakref__     # enable weakref
+    cdef void *handle           # The C handle for the underlying zmq object.
+    cdef bint _shadow           # whether the Context is a shadow wrapper of another
+    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 bint closed   # bool property for a closed context.
+    cdef inline int _term(self)
+    # 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/external_libs/python/zmq/backend/cython/context.py b/external_libs/python/zmq/backend/cython/context.py
new file mode 100644
index 00000000..19f8ec7c
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/context.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'context.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/error.py b/external_libs/python/zmq/backend/cython/error.py
new file mode 100644
index 00000000..d3a4ea0e
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/error.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'error.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/libzmq.pxd b/external_libs/python/zmq/backend/cython/libzmq.pxd
new file mode 100644
index 00000000..e42f6d6b
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/libzmq.pxd
@@ -0,0 +1,110 @@
+"""All the C imports for 0MQ"""
+
+#
+#    Copyright (c) 2010 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
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# Import the C header files
+#-----------------------------------------------------------------------------
+
+cdef extern from *:
+    ctypedef void* const_void_ptr "const void *"
+    ctypedef char* const_char_ptr "const char *"
+
+cdef extern from "zmq_compat.h":
+    ctypedef signed long long int64_t "pyzmq_int64_t"
+
+include "constant_enums.pxi"
+
+cdef extern from "zmq.h" nogil:
+
+    void _zmq_version "zmq_version"(int *major, int *minor, int *patch)
+    
+    ctypedef int fd_t "ZMQ_FD_T"
+    
+    enum: errno
+    char *zmq_strerror (int errnum)
+    int zmq_errno()
+
+    void *zmq_ctx_new ()
+    int zmq_ctx_destroy (void *context)
+    int zmq_ctx_set (void *context, int option, int optval)
+    int zmq_ctx_get (void *context, int option)
+    void *zmq_init (int io_threads)
+    int zmq_term (void *context)
+    
+    # blackbox def for zmq_msg_t
+    ctypedef void * zmq_msg_t "zmq_msg_t"
+    
+    ctypedef void zmq_free_fn(void *data, void *hint)
+    
+    int zmq_msg_init (zmq_msg_t *msg)
+    int zmq_msg_init_size (zmq_msg_t *msg, size_t size)
+    int zmq_msg_init_data (zmq_msg_t *msg, void *data,
+        size_t size, zmq_free_fn *ffn, void *hint)
+    int zmq_msg_send (zmq_msg_t *msg, void *s, int flags)
+    int zmq_msg_recv (zmq_msg_t *msg, void *s, int flags)
+    int zmq_msg_close (zmq_msg_t *msg)
+    int zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src)
+    int zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src)
+    void *zmq_msg_data (zmq_msg_t *msg)
+    size_t zmq_msg_size (zmq_msg_t *msg)
+    int zmq_msg_more (zmq_msg_t *msg)
+    int zmq_msg_get (zmq_msg_t *msg, int option)
+    int zmq_msg_set (zmq_msg_t *msg, int option, int optval)
+    const_char_ptr zmq_msg_gets (zmq_msg_t *msg, const_char_ptr property)
+    int zmq_has (const_char_ptr capability)
+
+    void *zmq_socket (void *context, int type)
+    int zmq_close (void *s)
+    int zmq_setsockopt (void *s, int option, void *optval, size_t optvallen)
+    int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen)
+    int zmq_bind (void *s, char *addr)
+    int zmq_connect (void *s, char *addr)
+    int zmq_unbind (void *s, char *addr)
+    int zmq_disconnect (void *s, char *addr)
+
+    int zmq_socket_monitor (void *s, char *addr, int flags)
+    
+    # send/recv
+    int zmq_sendbuf (void *s, const_void_ptr buf, size_t n, int flags)
+    int zmq_recvbuf (void *s, void *buf, size_t n, int flags)
+
+    ctypedef struct zmq_pollitem_t:
+        void *socket
+        int fd
+        short events
+        short revents
+
+    int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout)
+
+    int zmq_device (int device_, void *insocket_, void *outsocket_)
+    int zmq_proxy (void *frontend, void *backend, void *capture)
+
+cdef extern from "zmq_utils.h" nogil:
+
+    void *zmq_stopwatch_start ()
+    unsigned long zmq_stopwatch_stop (void *watch_)
+    void zmq_sleep (int seconds_)
+    int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key)
+
diff --git a/external_libs/python/zmq/backend/cython/message.pxd b/external_libs/python/zmq/backend/cython/message.pxd
new file mode 100644
index 00000000..4781195f
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/message.pxd
@@ -0,0 +1,63 @@
+"""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):
+
+    cdef set events  # Message Event objects to track.
+    cdef set peers   # Other Message or MessageTracker objects.
+
+
+cdef class Frame:
+
+    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
+    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/external_libs/python/zmq/backend/cython/message.py b/external_libs/python/zmq/backend/cython/message.py
new file mode 100644
index 00000000..5e423b62
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/message.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'message.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/socket.pxd b/external_libs/python/zmq/backend/cython/socket.pxd
new file mode 100644
index 00000000..b8a331e2
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/socket.pxd
@@ -0,0 +1,47 @@
+"""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:
+
+    cdef object __weakref__     # enable weakref
+    cdef void *handle           # The C handle for the underlying zmq object.
+    cdef bint _shadow           # whether the Socket is a shadow wrapper of another
+    # 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/external_libs/python/zmq/backend/cython/socket.py b/external_libs/python/zmq/backend/cython/socket.py
new file mode 100644
index 00000000..faef8bee
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/socket.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'socket.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/cython/utils.pxd b/external_libs/python/zmq/backend/cython/utils.pxd
new file mode 100644
index 00000000..1d7117f1
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/utils.pxd
@@ -0,0 +1,29 @@
+"""Wrap zmq_utils.h"""
+
+#
+#    Copyright (c) 2010 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:
+    cdef void *watch # The C handle for the underlying zmq object
+
diff --git a/external_libs/python/zmq/backend/cython/utils.py b/external_libs/python/zmq/backend/cython/utils.py
new file mode 100644
index 00000000..fe928300
--- /dev/null
+++ b/external_libs/python/zmq/backend/cython/utils.py
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'utils.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()
diff --git a/external_libs/python/zmq/backend/select.py b/external_libs/python/zmq/backend/select.py
new file mode 100644
index 00000000..0a2e09a2
--- /dev/null
+++ b/external_libs/python/zmq/backend/select.py
@@ -0,0 +1,39 @@
+"""Import basic exposure of libzmq C API as a backend"""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+public_api = [
+    'Context',
+    'Socket',
+    'Frame',
+    'Message',
+    'Stopwatch',
+    'device',
+    'proxy',
+    'zmq_poll',
+    'strerror',
+    'zmq_errno',
+    'has',
+    'curve_keypair',
+    'constants',
+    'zmq_version_info',
+    'IPC_PATH_MAX_LEN',
+]
+
+def select_backend(name):
+    """Select the pyzmq backend"""
+    try:
+        mod = __import__(name, fromlist=public_api)
+    except ImportError:
+        raise
+    except Exception as e:
+        import sys
+        from zmq.utils.sixcerpt import reraise
+        exc_info = sys.exc_info()
+        reraise(ImportError, ImportError("Importing %s failed with %s" % (name, e)), exc_info[2])
+    
+    ns = {}
+    for key in public_api:
+        ns[key] = getattr(mod, key)
+    return ns
-- 
cgit