Commits

Daniel Holth  committed bbce642

initial commit

  • Participants
  • Parent commits 12ee12a

Comments (0)

Files changed (21)

File COPYING.LESSER

+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+======================================================
+pyzmq-ctypes: Python bindings for 0MQ (ctypes version)
+======================================================
+
+This project is an attempt to build a partially-compatible version of
+PyZMQ running on pypy. Since I don't have time to write a Cython that
+compiles to Python instead of C, I decided to write some ctypes bindings
+for ZeroMQ.
+
+These bindings introspect parts of the ZeroMQ library by using the C
+compiler and a C parser, so you will still need those in order to
+use this.
+
+Authors
+=======
+
+The ctypes bindings were written by Daniel Holth <dholth@gmail.com>
+based on a copy of the original PyZMQ with the Cython bits taken out.
+
+The orginal PyZMQ was started by and continues to be led by Brian
+E. Granger (ellisonbg AT gmail DOT com).
+
+The following people have contributed to the project:
+
+* Carlos Rocha (carlos DOT rocha AT gmail DOT com)
+* Andrew Gwozdziewycz (git AT apgwoz DOT com)
+* Fernando Perez (fernando DOT perez AT berkeley DOT edu)
+* Nicholas Piel (nicholas AT nichol DOT as)
+* Eugene Chernyshov (chernyshov DOT eugene AT gmail DOT com)
+* Justin Riley (justin DOT t DOT riley AT gmail DOT com)
+* Ivo Danihelka (ivo AT denihelka DOT net)
+* Thomas Supra (tomspur AT fedoraproject DOT org)
+* Douglas Creager (dcreager AT dcreager DOT net)
+* Erick Tryzelaar (erick DOT tryzelaar AT gmail DOT com)
+* Min Ragan-Kelley (benjaminrk AT gmail DOT com)
+* Scott Sadler (github AT mashi DOT org)
+* spez (steve AT hipmunk DOT com)
+* Thomas Kluyver (takowl AT gmail DOT com)

File perf/local_lat.py

+#
+#    Copyright (c) 2007-2010 iMatix Corporation
+#
+#    This file is part of 0MQ.
+#
+#    0MQ 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.
+#
+#    0MQ 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/>.
+#
+
+import sys
+import time
+import zmq
+
+def main():
+    use_poll = '-p' in sys.argv
+    use_copy = '-c' in sys.argv
+    if use_copy:
+        sys.argv.remove('-c')
+    if use_poll:
+        sys.argv.remove('-p')
+
+    if len (sys.argv) != 4:
+        print 'usage: local_lat [-c use-copy] [-p use-poll] <bind-to> <message-size> <roundtrip-count>'
+        sys.exit (1)
+
+    try:
+        bind_to = sys.argv[1]
+        message_size = int(sys.argv[2])
+        roundtrip_count = int(sys.argv[3])
+    except (ValueError, OverflowError), e:
+        print 'message-size and roundtrip-count must be integers'
+        sys.exit(1)
+
+    ctx = zmq.Context()
+    s = ctx.socket(zmq.REP)
+
+    if use_poll:
+        p = zmq.Poller()
+        p.register(s)
+
+    s.bind(bind_to)
+
+    for i in range(0, roundtrip_count):
+        if use_poll:
+            res = p.poll()
+            assert(res[0][1] & zmq.POLLIN)
+        msg = s.recv(zmq.NOBLOCK if use_poll else 0, copy=use_copy)
+        assert len(msg) == message_size
+
+        if use_poll:
+            res = p.poll()
+            assert(res[0][1] & zmq.POLLOUT)
+        s.send(msg, zmq.NOBLOCK if use_poll else 0, copy=use_copy)
+
+    # Let the context finish messaging before ending.
+    # You may need to increase this time for longer or many messages.
+    time.sleep(2.0)
+
+if __name__ == '__main__':
+    main()

File perf/local_thr.py

+#
+#    Copyright (c) 2007-2010 iMatix Corporation
+#
+#    This file is part of 0MQ.
+#
+#    0MQ 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.
+#
+#    0MQ 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/>.
+#
+
+import sys
+import time
+import zmq
+
+def main ():
+    use_poll = '-p' in sys.argv
+    use_copy = '-c' in sys.argv
+    if use_copy:
+        sys.argv.remove('-c')
+    if use_poll:
+        sys.argv.remove('-p')
+
+    if len (sys.argv) != 4:
+        print 'usage: local_thr [-c use-copy] [-p use-poll] <bind-to> <message-size> <message-count>'
+        sys.exit(1)
+
+    try:
+        bind_to = sys.argv[1]
+        message_size = int(sys.argv[2])
+        message_count = int(sys.argv[3])
+    except (ValueError, OverflowError), e:
+        print 'message-size and message-count must be integers'
+        sys.exit(1)
+
+    ctx = zmq.Context()
+    s = ctx.socket(zmq.SUB)
+
+    #  Add your socket options here.
+    #  For example ZMQ_RATE, ZMQ_RECOVERY_IVL and ZMQ_MCAST_LOOP for PGM.
+    s.setsockopt(zmq.SUBSCRIBE , "");
+
+    if use_poll:
+        p = zmq.Poller()
+        p.register(s)
+
+    s.bind(bind_to)
+
+    # Wait for the other side to connect.
+    time.sleep(2.0)
+
+    msg = s.recv()
+    assert len (msg) == message_size
+
+    clock = zmq.Stopwatch()
+    start = 0
+    clock.start()
+    # start = time.clock()
+
+    for i in range (1, message_count):
+        if use_poll:
+            res = p.poll()
+            assert(res[0][1] & zmq.POLLIN)
+        msg = s.recv(zmq.NOBLOCK if use_poll else 0, copy=use_copy)
+        assert len(msg) == message_size
+
+        end = clock.stop()
+        # end = time.clock()
+
+    elapsed = (end - start)
+    # elapsed = (end - start) * 1000000 # use with time.clock
+    if elapsed == 0:
+    	elapsed = 1
+    throughput = (1000000.0 * float(message_count)) / float(elapsed)
+    megabits = float(throughput * message_size * 8) / 1000000
+
+    print "message size: %.0f [B]" % (message_size, )
+    print "message count: %.0f" % (message_count, )
+    print "mean throughput: %.0f [msg/s]" % (throughput, )
+    print "mean throughput: %.3f [Mb/s]" % (megabits, )
+
+    # Let the context finish messaging before ending.
+    # You may need to increase this time for longer or many messages.
+    time.sleep(2.0)
+
+if __name__ == "__main__":
+    main ()
+

File perf/remote_lat.py

+#
+#    Copyright (c) 2007-2010 iMatix Corporation
+#
+#    This file is part of 0MQ.
+#
+#    0MQ 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.
+#
+#    0MQ 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/>.
+#
+
+import sys
+import time
+import zmq
+
+
+def main ():
+    use_poll = '-p' in sys.argv
+    use_copy = '-c' in sys.argv
+    if use_copy:
+        sys.argv.remove('-c')
+    if use_poll:
+        sys.argv.remove('-p')
+
+    if len(sys.argv) != 4:
+        print 'usage: remote_lat [-c use-copy] [-p use-poll] <connect-to> <message-size> <roundtrip-count>'
+        sys.exit(1)
+
+    try:
+        connect_to = sys.argv[1]
+        message_size = int(sys.argv[2])
+        roundtrip_count = int(sys.argv[3])
+    except (ValueError, OverflowError), e:
+        print 'message-size and message-count must be integers'
+        sys.exit(1)
+
+    ctx = zmq.Context()
+    s = ctx.socket(zmq.REQ)
+    print connect_to
+    s.connect(connect_to)
+
+    if use_poll:
+        p = zmq.Poller()
+        p.register(s)
+
+    msg = ' ' * message_size
+
+    clock = zmq.Stopwatch()
+    start = 0
+    clock.start()
+    # start = time.clock()
+
+    for i in range (0, roundtrip_count):
+        if use_poll:
+            res = p.poll()
+            assert(res[0][1] & zmq.POLLOUT)
+        s.send(msg, zmq.NOBLOCK if use_poll else 0, copy=use_copy)
+
+        if use_poll:
+            res = p.poll()
+            assert(res[0][1] & zmq.POLLIN)
+        msg = s.recv(zmq.NOBLOCK if use_poll else 0, copy=use_copy)
+        assert len (msg) == message_size
+
+    end = clock.stop()
+    # end = time.clock()
+
+    time.sleep(1)
+
+    elapsed = (end - start)
+    # elapsed = (end - start) * 1000000 # use with time.clock
+    latency = elapsed / (roundtrip_count * 2)
+
+    print "message size: %.0f [B]" % (message_size, )
+    print "roundtrip count: %.0f" % (roundtrip_count, )
+    print "mean latency: %.3f [us]" % (latency, )
+
+    # Let the context finish messaging before ending.
+    # You may need to increase this time for longer or many messages.
+    time.sleep(2.0)
+
+if __name__ == "__main__":
+    main ()
+
+

File perf/remote_thr.py

+#
+#    Copyright (c) 2007-2010 iMatix Corporation
+#
+#    This file is part of 0MQ.
+#
+#    0MQ 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.
+#
+#    0MQ 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/>.
+#
+
+import sys
+import zmq
+import time
+
+def main ():
+    use_poll = '-p' in sys.argv
+    use_copy = '-c' in sys.argv
+    if use_copy:
+        sys.argv.remove('-c')
+    if use_poll:
+        sys.argv.remove('-p')
+
+    if len (sys.argv) != 4:
+        print 'usage: remote_thr [-c use-copy] [-p use-poll] <connect-to> <message-size> <message-count>'
+        sys.exit(1)
+
+    try:
+        connect_to = sys.argv[1]
+        message_size = int(sys.argv[2])
+        message_count = int(sys.argv[3])
+    except (ValueError, OverflowError), e:
+        print 'message-size and message-count must be integers'
+        sys.exit(1)
+
+    ctx = zmq.Context()
+    s = ctx.socket(zmq.PUB)
+
+    #  Add your socket options here.
+    #  For example ZMQ_RATE, ZMQ_RECOVERY_IVL and ZMQ_MCAST_LOOP for PGM.
+
+    if use_poll:
+        p = zmq.Poller()
+        p.register(s)
+
+    s.connect(connect_to)
+
+    # Wait for this side to connect.
+    time.sleep(2.0)
+
+    msg = ' ' * message_size
+
+    for i in range(0, message_count):
+        if use_poll:
+            res = p.poll()
+            assert(res[0][1] & zmq.POLLOUT)
+        s.send(msg, zmq.NOBLOCK if use_poll else 0, copy=use_copy)
+
+    # Let the context finish messaging before ending.
+    # You may need to increase this time for longer or many messages.
+    time.sleep(2.0)
+
+if __name__ == "__main__":
+    main ()
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright © 2011 Daniel Holth, Brian Granger
+#
+# This file is part of pyzmq-ctypes
+#
+# pyzmq-ctypes 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-ctypes 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/>.
+
+import os, sys
+
+from distutils.core import setup
+
+long_desc = \
+"""
+pyzmq-ctypes is a ctypes binding for the ZeroMQ library
+(http://www.zeromq.org) that will run on pypy.
+"""
+
+setup(
+    name = "pyzmq-ctypes",
+    version = "2.1.0",
+    packages = ['zmq'],
+    author = "Daniel Holth",
+    author_email = "dholth@fastmail.fm",
+    url = 'http://bitbucket.org/dholth/pyzmq-ctypes',
+    download_url = 'http://python.org/pypi/pyzmq-ctypes',
+    description = "Python bindings for 0MQ (ctypes version).",
+    install_requires = ['py', 'ctypes_configure', 'pycparser'],
+    long_description = long_desc,
+    license = "LGPL",
+    classifiers = [
+        'Development Status :: 2 - Pre-Alpha',
+        'Intended Audience :: Developers',
+        'Intended Audience :: Financial and Insurance Industry',
+        'Intended Audience :: Science/Research',
+        'Intended Audience :: System Administrators',
+        'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+        'Operating System :: POSIX',
+        'Topic :: System :: Networking'
+    ]
+)
+

File zmq/__init__.py

+from _zmq import *
+"""
+Low-level ctypes binding for the ZeroMQ library. Makes an attempt to
+emulate pyzmq.core.
+
+Daniel Holth <dholth@fastmail.fm>
+"""
+
+from ctypes import *
+from ctypes_configure import configure
+
+class CConfigure(object):
+    _compilation_info_ = configure.ExternalCompilationInfo(
+            includes = ['zmq.h'],
+            libraries = ['zmq']
+            )
+    size_t = configure.SimpleType('size_t', c_int)
+
+for cname in ['ZMQ_AFFINITY', 'ZMQ_DOWNSTREAM', 'EADDRINUSE',
+    'EADDRNOTAVAIL', 'EAGAIN', 'ECONNREFUSED', 'EFAULT', 'EFSM',
+    'EINPROGRESS', 'EINVAL', 'EMTHREAD', 'ENETDOWN', 'ENOBUFS',
+    'ENOCOMPATPROTO', 'ENODEV', 'ENOMEM', 'ENOTSUP', 'EPROTONOSUPPORT',
+    'ETERM', 'ZMQ_FORWARDER', 'ZMQ_HWM', 'ZMQ_IDENTITY', 'ZMQ_MCAST_LOOP',
+    'ZMQ_NOBLOCK', 'ZMQ_PAIR', 'ZMQ_POLLERR', 'ZMQ_POLLIN', 'ZMQ_POLLOUT',
+    'ZMQ_PUB', 'ZMQ_PULL', 'ZMQ_PUSH', 'ZMQ_QUEUE', 'ZMQ_RATE', 'ZMQ_RCVBUF',
+    'ZMQ_RCVMORE', 'ZMQ_RECOVERY_IVL', 'ZMQ_REP', 'ZMQ_REQ', 'ZMQ_SNDBUF',
+    'ZMQ_SNDMORE', 'ZMQ_STREAMER', 'ZMQ_SUB', 'ZMQ_SUBSCRIBE', 'ZMQ_SWAP',
+    'ZMQ_UNSUBSCRIBE', 'ZMQ_UPSTREAM', 'ZMQ_XREP', 'ZMQ_XREQ', 'ZMQ_MAX_VSM_SIZE']:
+        pyname = cname.split('_', 1)[-1]
+        setattr(CConfigure, pyname, configure.ConstantInteger(cname))
+
+info = configure.configure(CConfigure)
+globals().update(info)
+
+libzmq = cdll.LoadLibrary("libzmq.so")
+
+libzmq.zmq_version.restype = None
+libzmq.zmq_version.argtypes = [POINTER(c_int)]*3
+
+major = c_int()
+minor = c_int()
+patch = c_int()
+
+libzmq.zmq_version(byref(major), byref(minor), byref(patch))
+
+__version__ = tuple((x.value for x in (major, minor, patch)))
+
+# Error number as known by the 0MQ library
+
+libzmq.zmq_errno.argtypes = []
+
+libzmq.zmq_strerror.restype = c_char_p
+libzmq.zmq_strerror.argtypes = [c_int]
+
+# 0MQ infrastructure
+
+libzmq.zmq_init.restype = c_void_p
+libzmq.zmq_init.argtypes = [c_int]
+
+libzmq.zmq_term.restype = c_int
+libzmq.zmq_term.argtypes = [c_void_p]
+
+# 0MQ message definition
+
+class zmq_msg_t(Structure):
+    _fields_ = [
+            ('content', c_void_p),
+            ('flags', c_ubyte),
+            ('vsm_size', c_ubyte),
+            ('vsm_data', c_ubyte*MAX_VSM_SIZE)
+            ]
+
+libzmq.zmq_msg_init.argtypes = [POINTER(zmq_msg_t)]
+libzmq.zmq_msg_init_size.argtypes = [POINTER(zmq_msg_t), size_t]
+
+# requires a free function:
+libzmq.zmq_msg_init_data.argtypes = [POINTER(zmq_msg_t), c_void_p, size_t,
+                                     c_void_p, c_void_p]
+libzmq.zmq_msg_close.argtypes = [POINTER(zmq_msg_t)]
+libzmq.zmq_msg_move.argtypes = [POINTER(zmq_msg_t), POINTER(zmq_msg_t)]
+libzmq.zmq_msg_copy.argtypes = [POINTER(zmq_msg_t), POINTER(zmq_msg_t)]
+libzmq.zmq_msg_data.restype = c_void_p
+libzmq.zmq_msg_data.argtypes = [POINTER(zmq_msg_t)]
+libzmq.zmq_msg_size.restype = c_void_p
+libzmq.zmq_msg_size.argtypes = [POINTER(zmq_msg_t)]
+
+# 0MQ socket definition
+
+libzmq.zmq_socket.restype = c_void_p
+libzmq.zmq_socket.argtypes = [c_void_p, c_int]
+
+libzmq.zmq_close.argtypes = [c_void_p]
+
+libzmq.zmq_setsockopt.argtypes = [c_void_p, c_int, c_void_p, size_t]
+libzmq.zmq_getsockopt.argtypes = [c_void_p, c_int, c_void_p, size_t]
+libzmq.zmq_bind.argtypes = [c_void_p, c_char_p]
+libzmq.zmq_connect.argtypes = [c_void_p, c_char_p]
+libzmq.zmq_send.argtypes = [c_void_p, POINTER(zmq_msg_t), c_int]
+libzmq.zmq_recv.argtypes = [c_void_p, POINTER(zmq_msg_t), c_int]
+
+def _shortcuts():
+    for symbol in dir(libzmq):
+        if symbol.startswith('zmq_'):
+            globals()[symbol] = getattr(libzmq, symbol)
+
+_shortcuts()

File zmq/tests/__init__.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 sys
+
+from unittest import TestCase
+
+import zmq
+
+#-----------------------------------------------------------------------------
+# Utilities
+#-----------------------------------------------------------------------------
+
+
+class BaseZMQTestCase(TestCase):
+
+    def setUp(self):
+        self.context = zmq.Context()
+        self.sockets = []
+    
+    def tearDown(self):
+        while self.sockets:
+            sock = self.sockets.pop()
+            sock.close()
+        del self.context
+            
+
+    def create_bound_pair(self, type1, type2, interface='tcp://127.0.0.1'):
+        """Create a bound socket pair using a random port."""
+        s1 = zmq.Socket(self.context, type1)
+        port = s1.bind_to_random_port(interface)
+        s2 = zmq.Socket(self.context, type2)
+        s2.connect('%s:%s' % (interface, port))
+        self.sockets.extend([s1,s2])
+        return s1, s2
+
+    def ping_pong(self, s1, s2, msg):
+        s1.send(msg)
+        msg2 = s2.recv()
+        s2.send(msg2)
+        msg3 = s1.recv()
+        return msg3
+
+    def ping_pong_json(self, s1, s2, o):
+        s1.send_json(o)
+        o2 = s2.recv_json()
+        s2.send_json(o2)
+        o3 = s1.recv_json()
+        return o3
+
+    def ping_pong_pyobj(self, s1, s2, o):
+        s1.send_pyobj(o)
+        o2 = s2.recv_pyobj()
+        s2.send_pyobj(o2)
+        o3 = s1.recv_pyobj()
+        return o3
+
+    def assertRaisesErrno(self, errno, func, *args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except zmq.ZMQError:
+            e = sys.exc_info()[1]
+            self.assertEqual(e.errno, errno, "wrong error raised, expected '%s' \
+got '%s'" % (zmq.ZMQError(errno), zmq.ZMQError(e.errno)))
+        else:
+            self.fail("Function did not raise any error")
+        
+
+
+class PollZMQTestCase(BaseZMQTestCase):
+    pass
+

File zmq/tests/test_context.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 zmq
+from zmq.tests import BaseZMQTestCase
+
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+
+class TestContext(BaseZMQTestCase):
+
+    def test_init(self):
+        c1 = zmq.Context()
+        self.assert_(isinstance(c1, zmq.Context))
+        del c1
+        c2 = zmq.Context()
+        self.assert_(isinstance(c2, zmq.Context))
+        del c2
+        c3 = zmq.Context()
+        self.assert_(isinstance(c3, zmq.Context))
+        del c3
+
+    def test_term(self):
+        c = zmq.Context()
+        c.term()
+        self.assert_(c.closed)
+
+    def test_fail_init(self):
+        self.assertRaisesErrno(zmq.EINVAL, zmq.Context, 0)
+

File zmq/tests/test_device.py

+#
+#    Copyright (c) 2010 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 time
+
+import zmq
+from zmq import devices
+from zmq.tests import BaseZMQTestCase
+from zmq.utils.strtypes import (bytes,unicode,basestring)
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+
+class TestDevice(BaseZMQTestCase):
+
+    def test_device_types(self):
+        # a = self.context.socket(zmq.SUB)
+        for devtype in (zmq.STREAMER, zmq.FORWARDER, zmq.QUEUE):
+            dev = devices.Device(devtype, zmq.PAIR,zmq.PAIR)
+            self.assertEquals(dev.device_type, devtype)
+            del dev
+        # del a
+    
+    def test_device_attributes(self):
+        # a = self.context.socket(zmq.SUB)
+        # b = self.context.socket(zmq.PUB)
+        dev = devices.Device(zmq.FORWARDER, zmq.SUB, zmq.PUB)
+        self.assert_(dev.in_type == zmq.SUB)
+        self.assert_(dev.out_type == zmq.PUB)
+        self.assertEquals(dev.device_type, zmq.FORWARDER)
+        self.assertEquals(dev.daemon, True)
+        # del a
+        del dev
+    
+    def test_tsdevice_attributes(self):
+        dev = devices.Device(zmq.QUEUE, zmq.SUB, zmq.PUB)
+        self.assertEquals(dev.in_type, zmq.SUB)
+        self.assertEquals(dev.out_type, zmq.PUB)
+        self.assertEquals(dev.device_type, zmq.QUEUE)
+        self.assertEquals(dev.daemon, True)
+        del dev
+        
+    
+    def test_single_socket_forwarder_connect(self):
+        dev = devices.ThreadDevice(zmq.FORWARDER, zmq.REP, -1)
+        req = self.context.socket(zmq.REQ)
+        port = req.bind_to_random_port('tcp://127.0.0.1')
+        dev.connect_in('tcp://127.0.0.1:%i'%port)
+        dev.start()
+        time.sleep(.25)
+        msg = 'hello'.encode()
+        req.send(msg)
+        self.assertEquals(msg, req.recv())
+        del dev
+        del req
+        dev = devices.ThreadDevice(zmq.FORWARDER, zmq.REP, -1)
+        req = self.context.socket(zmq.REQ)
+        port = req.bind_to_random_port('tcp://127.0.0.1')
+        dev.connect_out('tcp://127.0.0.1:%i'%port)
+        dev.start()
+        time.sleep(.25)
+        msg = 'hello again'.encode()
+        req.send(msg)
+        self.assertEquals(msg, req.recv())
+        del dev
+        del req
+        
+    def test_single_socket_forwarder_bind(self):
+        dev = devices.ThreadDevice(zmq.FORWARDER, zmq.REP, -1)
+        req = self.context.socket(zmq.REQ)
+        port = 12345
+        req.connect('tcp://127.0.0.1:%i'%port)
+        dev.bind_in('tcp://127.0.0.1:%i'%port)
+        dev.start()
+        time.sleep(.25)
+        msg = 'hello'.encode()
+        req.send(msg)
+        self.assertEquals(msg, req.recv())
+        del dev
+        del req
+        dev = devices.ThreadDevice(zmq.FORWARDER, zmq.REP, -1)
+        req = self.context.socket(zmq.REQ)
+        port = 12346
+        req.connect('tcp://127.0.0.1:%i'%port)
+        dev.bind_in('tcp://127.0.0.1:%i'%port)
+        dev.start()
+        time.sleep(.25)
+        msg = 'hello again'.encode()
+        req.send(msg)
+        self.assertEquals(msg, req.recv())
+        del dev
+        del req

File zmq/tests/test_log.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 time
+from unittest import TestCase
+
+import zmq
+from zmq.tests import BaseZMQTestCase
+
+from zmq.log import handlers
+import logging
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+class TestPubLog(BaseZMQTestCase):
+    
+    iface = 'inproc://zmqlog'
+    topic='zmq'.encode()
+    
+    @property
+    def logger(self):
+        # print dir(self)
+        logger = logging.getLogger('zmqtest')
+        logger.setLevel(logging.DEBUG)
+        return logger
+    
+    def connect_handler(self):
+        logger = self.logger
+        pub,sub = self.create_bound_pair(zmq.PUB, zmq.SUB)
+        handler = handlers.PUBHandler(pub)
+        handler.setLevel(logging.DEBUG)
+        handler.root_topic = self.topic
+        logger.addHandler(handler)
+        sub.setsockopt(zmq.SUBSCRIBE, self.topic)
+        time.sleep(0.1)
+        return logger, handler, sub
+    
+    def test_init_iface(self):
+        logger = self.logger
+        ctx = self.context
+        handler = handlers.PUBHandler(self.iface)
+        self.assertFalse(handler.ctx is ctx)
+        handler.socket.close()
+        
+        handler = handlers.PUBHandler(self.iface, self.context)
+        self.assertTrue(handler.ctx is ctx)
+        
+        handler.setLevel(logging.DEBUG)
+        handler.root_topic = self.topic
+        logger.addHandler(handler)
+        
+        # handler.socket.close()
+        sub = ctx.socket(zmq.SUB)
+        sub.connect(self.iface)
+        sub.setsockopt(zmq.SUBSCRIBE, self.topic)
+        import time; time.sleep(0.1)
+        msg1 = 'message'
+        logger.info(msg1)
+        
+        (topic, msg2) = sub.recv_multipart()
+        self.assertEquals(topic, 'zmq.INFO'.encode())
+        self.assertEquals(msg2, (msg1+'\n').encode())
+        logger.removeHandler(handler)
+        # handler.socket.close()
+    
+    def test_init_socket(self):
+        pub,sub = self.create_bound_pair(zmq.PUB, zmq.SUB)
+        logger = self.logger
+        handler = handlers.PUBHandler(pub)
+        handler.setLevel(logging.DEBUG)
+        handler.root_topic = self.topic
+        logger.addHandler(handler)
+        
+        self.assertTrue(handler.socket is pub)
+        self.assertTrue(handler.ctx is pub.context)
+        self.assertTrue(handler.ctx is self.context)
+        # handler.socket.close()
+        sub.setsockopt(zmq.SUBSCRIBE, self.topic)
+        import time; time.sleep(0.1)
+        msg1 = 'message'
+        logger.info(msg1)
+        
+        (topic, msg2) = sub.recv_multipart()
+        self.assertEquals(topic, 'zmq.INFO'.encode())
+        self.assertEquals(msg2, (msg1+'\n').encode())
+        logger.removeHandler(handler)
+        # handler.socket.close()
+    
+    def test_root_topic(self):
+        logger, handler, sub = self.connect_handler()
+        handler.socket.bind(self.iface)
+        sub2 = sub.context.socket(zmq.SUB)
+        sub2.connect(self.iface)
+        sub2.setsockopt(zmq.SUBSCRIBE, ''.encode())
+        handler.root_topic = 'twoonly'.encode()
+        msg1 = 'ignored'
+        logger.info(msg1)
+        self.assertRaisesErrno(zmq.EAGAIN, sub.recv, zmq.NOBLOCK)
+        topic,msg2 = sub2.recv_multipart()
+        self.assertEquals(topic, 'twoonly.INFO'.encode())
+        self.assertEquals(msg2, (msg1+'\n').encode())
+        
+        
+        
+        logger.removeHandler(handler)
+

File zmq/tests/test_message.py

+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 copy
+import sys
+from sys import getrefcount as grc
+import time
+from pprint import pprint
+from unittest import TestCase
+
+import zmq
+from zmq.tests import BaseZMQTestCase
+from zmq.utils.strtypes import unicode,bytes
+
+try:
+    from nose import SkipTest
+except ImportError:
+    class SkipTest(Exception):
+        pass
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+x = 'x'.encode()
+
+class TestMessage(BaseZMQTestCase):
+
+    def test_above_30(self):
+        """Message above 30 bytes are never copied by 0MQ."""
+        for i in range(5, 16):  # 32, 64,..., 65536
+            s = (2**i)*x
+            self.assertEquals(grc(s), 2)
+            m = zmq.Message(s)
+            self.assertEquals(grc(s), 4)
+            del m
+            self.assertEquals(grc(s), 2)
+            del s
+
+    def test_str(self):
+        """Test the str representations of the Messages."""
+        for i in range(16):
+            s = (2**i)*x
+            m = zmq.Message(s)
+            self.assertEquals(s, str(m).encode())
+
+    def test_bytes(self):
+        """Test the Message.bytes property."""
+        for i in range(1,16):
+            s = (2**i)*x
+            m = zmq.Message(s)
+            b = m.bytes
+            self.assertEquals(s, m.bytes)
+            # check that it copies
+            self.assert_(b is not s)
+            # check that it copies only once
+            self.assert_(b is m.bytes)
+
+    def test_unicode(self):
+        """Test the unicode representations of the Messages."""
+        s = unicode('asdf')
+        self.assertRaises(TypeError, zmq.Message, s)
+        u = '§'
+        if str is not unicode:
+            u = u.decode('utf8')
+        for i in range(16):
+            s = (2**i)*u
+            m = zmq.Message(s.encode('utf8'))
+            self.assertEquals(s, unicode(m.bytes,'utf8'))
+
+    def test_len(self):
+        """Test the len of the Messages."""
+        for i in range(16):
+            s = (2**i)*x
+            m = zmq.Message(s)
+            self.assertEquals(len(s), len(m))
+
+    def test_lifecycle1(self):
+        """Run through a ref counting cycle with a copy."""
+        try:
+            view = memoryview
+        except NameError:
+            view = type(None)
+        for i in range(5, 16):  # 32, 64,..., 65536
+            s = (2**i)*x
+            rc = 2
+            self.assertEquals(grc(s), rc)
+            m = zmq.Message(s)
+            rc += 2
+            self.assertEquals(grc(s), rc)
+            m2 = copy.copy(m)
+            rc += 1
+            self.assertEquals(grc(s), rc)
+            b = m2.buffer
+            extra = int(isinstance(b,view))
+            # memoryview incs by 2
+            # buffer by 1
+            rc += 1+extra
+            self.assertEquals(grc(s), rc)
+
+            self.assertEquals(s, str(m).encode())
+            self.assertEquals(s, str(m2).encode())
+            self.assertEquals(s, m.bytes)
+            # self.assert_(s is str(m))
+            # self.assert_(s is str(m2))
+            del m2
+            rc -= 1
+            self.assertEquals(grc(s), rc)
+            rc -= 1+extra
+            del b
+            self.assertEquals(grc(s), rc)
+            del m
+            rc -= 2
+            self.assertEquals(grc(s), rc)
+            self.assertEquals(rc, 2)
+            del s
+
+    def test_lifecycle2(self):
+        """Run through a different ref counting cycle with a copy."""
+        try:
+            view = memoryview
+        except NameError:
+            view = type(None)
+        for i in range(5, 16):  # 32, 64,..., 65536
+            s = (2**i)*x
+            rc = 2
+            self.assertEquals(grc(s), rc)
+            m = zmq.Message(s)
+            rc += 2
+            self.assertEquals(grc(s), rc)
+            m2 = copy.copy(m)
+            rc += 1
+            self.assertEquals(grc(s), rc)
+            b = m.buffer
+            extra = int(isinstance(b,view))
+            rc += 1+extra
+            self.assertEquals(grc(s), rc)
+            self.assertEquals(s, str(m).encode())
+            self.assertEquals(s, str(m2).encode())
+            self.assertEquals(s, m2.bytes)
+            self.assertEquals(s, m.bytes)
+            # self.assert_(s is str(m))
+            # self.assert_(s is str(m2))
+            del b
+            self.assertEquals(grc(s), rc)
+            del m
+            # m.buffer is kept until m is del'd
+            rc -= 1+extra
+            rc -= 1
+            self.assertEquals(grc(s), rc)
+            del m2
+            rc -= 2
+            self.assertEquals(grc(s), rc)
+            self.assertEquals(rc, 2)
+            del s
+    
+    def test_tracker(self):
+        m = zmq.Message('asdf'.encode(), track=True)
+        self.assertFalse(m.done)
+        pm = zmq.MessageTracker(m)
+        self.assertFalse(pm.done)
+        del m
+        self.assertTrue(pm.done)
+    
+    def test_no_tracker(self):
+        m = zmq.Message('asdf'.encode(), track=False)
+        self.assertRaises(ValueError, getattr, m, 'done')
+        m2 = copy.copy(m)
+        self.assertRaises(ValueError, getattr, m2, 'done')
+        self.assertRaises(ValueError, zmq.MessageTracker, m)
+    
+    def test_multi_tracker(self):
+        m = zmq.Message('asdf'.encode(), track=True)
+        m2 = zmq.Message('whoda'.encode(), track=True)
+        mt = zmq.MessageTracker(m,m2)
+        self.assertFalse(m.done)
+        self.assertFalse(mt.done)
+        self.assertRaises(zmq.NotDone, mt.wait, 0.1)
+        del m
+        time.sleep(0.1)
+        self.assertRaises(zmq.NotDone, mt.wait, 0.1)
+        self.assertFalse(mt.done)
+        del m2
+        self.assertTrue(mt.wait() is None)
+        self.assertTrue(mt.done)
+        
+    
+    def test_buffer_in(self):
+        """test using a buffer as input"""
+        try:
+            view = memoryview
+        except NameError:
+            view = buffer
+        if unicode is str:
+            ins = "§§¶•ªº˜µ¬˚…∆˙åß∂©œ∑´†≈ç√".encode('utf8')
+        else:
+            ins = "§§¶•ªº˜µ¬˚…∆˙åß∂©œ∑´†≈ç√"
+        m = zmq.Message(view(ins))
+    
+    def test_bad_buffer_in(self):
+        """test using a bad object"""
+        self.assertRaises(TypeError, zmq.Message, 5)
+        self.assertRaises(TypeError, zmq.Message, object())
+        
+    def test_buffer_out(self):
+        """receiving buffered output"""
+        try:
+            view = memoryview
+        except NameError:
+            view = buffer
+        if unicode is str:
+            ins = "§§¶•ªº˜µ¬˚…∆˙åß∂©œ∑´†≈ç√".encode('utf8')
+        else:
+            ins = "§§¶•ªº˜µ¬˚…∆˙åß∂©œ∑´†≈ç√"
+        m = zmq.Message(ins)
+        outb = m.buffer
+        self.assertTrue(isinstance(outb, view))
+        self.assert_(outb is m.buffer)
+        self.assert_(m.buffer is m.buffer)
+    
+    def test_multisend(self):
+        """ensure that a message remains intact after multiple sends"""
+        a,b = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+        s = "message".encode()
+        m = zmq.Message(s)
+        self.assertEquals(s, m.bytes)
+        
+        a.send(m, copy=False)
+        time.sleep(0.1)
+        self.assertEquals(s, m.bytes)
+        a.send(m, copy=False)
+        time.sleep(0.1)
+        self.assertEquals(s, m.bytes)
+        a.send(m, copy=True)
+        time.sleep(0.1)
+        self.assertEquals(s, m.bytes)
+        a.send(m, copy=True)
+        time.sleep(0.1)
+        self.assertEquals(s, m.bytes)
+        for i in range(4):
+            r = b.recv()
+            self.assertEquals(s,r)
+        self.assertEquals(s, m.bytes)
+    
+    def test_buffer_numpy(self):
+        """test non-copying numpy array messages"""
+        try:
+            import numpy
+        except ImportError:
+            raise SkipTest
+        shapes = map(numpy.random.randint, [2]*5,[16]*5)
+        for i in range(1,len(shapes)+1):
+            shape = shapes[:i]
+            A = numpy.random.random(shape)
+            m = zmq.Message(A)
+            self.assertEquals(A.data, m.buffer)
+            B = numpy.frombuffer(m.buffer,dtype=A.dtype).reshape(A.shape)
+            self.assertEquals((A==B).all(), True)
+    
+    def test_memoryview(self):
+        """test messages from memoryview (only valid for python >= 2.7)"""
+        major,minor = sys.version_info[:2]
+        if not (major >= 3 or (major == 2 and minor >= 7)):
+            raise SkipTest
+
+        s = 'carrotjuice'.encode()
+        v = memoryview(s)
+        m = zmq.Message(s)
+        buf = m.buffer
+        s2 = buf.tobytes()
+        self.assertEquals(s2,s)
+        self.assertEquals(m.bytes,s)
+        
+

File zmq/tests/test_monqueue.py

+#
+#    Copyright (c) 2010 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 time
+from unittest import TestCase
+
+import zmq
+from zmq import devices
+from zmq.tests import BaseZMQTestCase
+
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+class TestMonitoredQueue(BaseZMQTestCase):
+    sockets = []
+    pass
+    
+    def build_device(self, mon_sub="".encode(), in_prefix='in'.encode(), out_prefix='out'.encode()):
+        self.device = devices.ThreadMonitoredQueue(zmq.PAIR, zmq.PAIR, zmq.PUB,
+                                            in_prefix, out_prefix)
+        alice = self.context.socket(zmq.PAIR)
+        bob = self.context.socket(zmq.PAIR)
+        mon = self.context.socket(zmq.SUB)
+        
+        aport = alice.bind_to_random_port('tcp://127.0.0.1')
+        bport = bob.bind_to_random_port('tcp://127.0.0.1')
+        mport = mon.bind_to_random_port('tcp://127.0.0.1')
+        mon.setsockopt(zmq.SUBSCRIBE, mon_sub)
+        
+        self.device.connect_in("tcp://127.0.0.1:%i"%aport)
+        self.device.connect_out("tcp://127.0.0.1:%i"%bport)
+        self.device.connect_mon("tcp://127.0.0.1:%i"%mport)
+        time.sleep(.2)
+        self.device.start()
+        self.sockets.extend([alice, bob, mon])
+        return alice, bob, mon
+        
+    
+    def teardown_device(self):
+        for socket in self.sockets:
+            socket.close()
+            del socket
+        del self.device
+        
+    def test_reply(self):
+        alice, bob, mon = self.build_device()
+        alices = "hello bob".encode().split()
+        alice.send_multipart(alices)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices, bobs)
+        bobs = "hello alice".encode().split()
+        bob.send_multipart(bobs)
+        alices = alice.recv_multipart()
+        self.assertEquals(alices, bobs)
+        self.teardown_device()
+    
+    def test_queue(self):
+        alice, bob, mon = self.build_device()
+        alices = "hello bob".encode().split()
+        alice.send_multipart(alices)
+        alices2 = "hello again".encode().split()
+        alice.send_multipart(alices2)
+        alices3 = "hello again and again".encode().split()
+        alice.send_multipart(alices3)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices, bobs)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices2, bobs)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices3, bobs)
+        bobs = "hello alice".encode().split()
+        bob.send_multipart(bobs)
+        alices = alice.recv_multipart()
+        self.assertEquals(alices, bobs)
+        self.teardown_device()
+    
+    def test_monitor(self):
+        alice, bob, mon = self.build_device()
+        alices = "hello bob".encode().split()
+        alice.send_multipart(alices)
+        alices2 = "hello again".encode().split()
+        alice.send_multipart(alices2)
+        alices3 = "hello again and again".encode().split()
+        alice.send_multipart(alices3)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['in'.encode()]+bobs, mons)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices2, bobs)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices3, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['in'.encode()]+alices2, mons)
+        bobs = "hello alice".encode().split()
+        bob.send_multipart(bobs)
+        alices = alice.recv_multipart()
+        self.assertEquals(alices, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['in'.encode()]+alices3, mons)
+        mons = mon.recv_multipart()
+        self.assertEquals(['out'.encode()]+bobs, mons)
+        self.teardown_device()
+    
+    def test_prefix(self):
+        alice, bob, mon = self.build_device("".encode(), 'foo'.encode(), 'bar'.encode())
+        alices = "hello bob".encode().split()
+        alice.send_multipart(alices)
+        alices2 = "hello again".encode().split()
+        alice.send_multipart(alices2)
+        alices3 = "hello again and again".encode().split()
+        alice.send_multipart(alices3)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['foo'.encode()]+bobs, mons)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices2, bobs)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices3, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['foo'.encode()]+alices2, mons)
+        bobs = "hello alice".encode().split()
+        bob.send_multipart(bobs)
+        alices = alice.recv_multipart()
+        self.assertEquals(alices, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['foo'.encode()]+alices3, mons)
+        mons = mon.recv_multipart()
+        self.assertEquals(['bar'.encode()]+bobs, mons)
+        self.teardown_device()
+    
+    def test_monitor_subscribe(self):
+        alice, bob, mon = self.build_device("out".encode())
+        alices = "hello bob".encode().split()
+        alice.send_multipart(alices)
+        alices2 = "hello again".encode().split()
+        alice.send_multipart(alices2)
+        alices3 = "hello again and again".encode().split()
+        alice.send_multipart(alices3)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices, bobs)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices2, bobs)
+        bobs = bob.recv_multipart()
+        self.assertEquals(alices3, bobs)
+        bobs = "hello alice".encode().split()
+        bob.send_multipart(bobs)
+        alices = alice.recv_multipart()
+        self.assertEquals(alices, bobs)
+        mons = mon.recv_multipart()
+        self.assertEquals(['out'.encode()]+bobs, mons)
+        self.teardown_device()
+    

File zmq/tests/test_multipart.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 zmq
+
+from zmq.tests import BaseZMQTestCase
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+class TestMultipart(BaseZMQTestCase):
+
+    def test_xrep_xreq(self):
+        xrep, xreq = self.create_bound_pair(zmq.XREP, zmq.XREQ)
+
+        msg1 = 'message1'.encode()
+        xreq.send(msg1)
+        ident = xrep.recv()
+        more = xrep.rcvmore()
+        self.assertEquals(more, True)
+        msg2 = xrep.recv()
+        self.assertEquals(msg1, msg2)
+        more = xrep.rcvmore()
+        self.assertEquals(more, False)
+

File zmq/tests/test_pair.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 zmq
+
+from zmq.tests import BaseZMQTestCase
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+x = ' '.encode()
+class TestPair(BaseZMQTestCase):
+
+    def test_basic(self):
+        s1, s2 = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+
+        msg1 = 'message1'.encode()
+        msg2 = self.ping_pong(s1, s2, msg1)
+        self.assertEquals(msg1, msg2)
+
+    def test_multiple(self):
+        s1, s2 = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+
+        for i in range(10):
+            msg = i*x
+            s1.send(msg)
+
+        for i in range(10):
+            msg = i*x
+            s2.send(msg)
+
+        for i in range(10):
+            msg = s1.recv()
+            self.assertEquals(msg, i*x)
+
+        for i in range(10):
+            msg = s2.recv()
+            self.assertEquals(msg, i*x)
+
+    def test_json(self):
+        s1, s2 = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+        o = dict(a=10,b=list(range(10)))
+        o2 = self.ping_pong_json(s1, s2, o)
+
+    def test_pyobj(self):
+        s1, s2 = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+        o = dict(a=10,b=range(10))
+        o2 = self.ping_pong_pyobj(s1, s2, o)
+

File zmq/tests/test_poll.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 time
+from unittest import TestCase
+
+import zmq
+from zmq.tests import PollZMQTestCase
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+def wait():
+    time.sleep(.25)
+
+
+class TestPoll(PollZMQTestCase):
+
+    # This test is failing due to this issue:
+    # http://github.com/sustrik/zeromq2/issues#issue/26
+    def test_pair(self):
+        s1, s2 = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+
+        # Sleep to allow sockets to connect.
+        wait()
+
+        poller = zmq.Poller()
+        poller.register(s1, zmq.POLLIN|zmq.POLLOUT)
+        poller.register(s2, zmq.POLLIN|zmq.POLLOUT)
+        # Poll result should contain both sockets
+        socks = dict(poller.poll())
+        # Now make sure that both are send ready.
+        self.assertEquals(socks[s1], zmq.POLLOUT)
+        self.assertEquals(socks[s2], zmq.POLLOUT)
+        # Now do a send on both, wait and test for zmq.POLLOUT|zmq.POLLIN
+        s1.send('msg1'.encode())
+        s2.send('msg2'.encode())
+        wait()
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s1], zmq.POLLOUT|zmq.POLLIN)
+        self.assertEquals(socks[s2], zmq.POLLOUT|zmq.POLLIN)
+        # Make sure that both are in POLLOUT after recv.
+        s1.recv()
+        s2.recv()
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s1], zmq.POLLOUT)
+        self.assertEquals(socks[s2], zmq.POLLOUT)
+
+        poller.unregister(s1)
+        poller.unregister(s2)
+
+        # Wait for everything to finish.
+        wait()
+
+    def test_reqrep(self):
+        s1, s2 = self.create_bound_pair(zmq.REP, zmq.REQ)
+
+        # Sleep to allow sockets to connect.
+        wait()
+
+        poller = zmq.Poller()
+        poller.register(s1, zmq.POLLIN|zmq.POLLOUT)
+        poller.register(s2, zmq.POLLIN|zmq.POLLOUT)
+
+        # Make sure that s1 is in state 0 and s2 is in POLLOUT
+        socks = dict(poller.poll())
+        self.assertEquals(s1 in socks, 0)
+        self.assertEquals(socks[s2], zmq.POLLOUT)
+
+        # Make sure that s2 goes immediately into state 0 after send.
+        s2.send('msg1'.encode())
+        socks = dict(poller.poll())
+        self.assertEquals(s2 in socks, 0)
+
+        # Make sure that s1 goes into POLLIN state after a time.sleep().
+        time.sleep(0.5)
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s1], zmq.POLLIN)
+
+        # Make sure that s1 goes into POLLOUT after recv.
+        s1.recv()
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s1], zmq.POLLOUT)
+
+        # Make sure s1 goes into state 0 after send.
+        s1.send('msg2'.encode())
+        socks = dict(poller.poll())
+        self.assertEquals(s1 in socks, 0)
+
+        # Wait and then see that s2 is in POLLIN.
+        time.sleep(0.5)
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s2], zmq.POLLIN)
+
+        # Make sure that s2 is in POLLOUT after recv.
+        s2.recv()
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s2], zmq.POLLOUT)
+
+        poller.unregister(s1)
+        poller.unregister(s2)
+
+        # Wait for everything to finish.
+        wait()
+
+    def test_pubsub(self):
+        s1, s2 = self.create_bound_pair(zmq.PUB, zmq.SUB)
+        s2.setsockopt(zmq.SUBSCRIBE, ''.encode())
+
+        # Sleep to allow sockets to connect.
+        wait()
+
+        poller = zmq.Poller()
+        poller.register(s1, zmq.POLLIN|zmq.POLLOUT)
+        poller.register(s2, zmq.POLLIN|zmq.POLLOUT)
+
+        # Now make sure that both are send ready.
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s1], zmq.POLLOUT)
+        self.assertEquals(s2 in socks, 0)
+        # Make sure that s1 stays in POLLOUT after a send.
+        s1.send('msg1'.encode())
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s1], zmq.POLLOUT)
+
+        # Make sure that s2 is POLLIN after waiting.
+        wait()
+        socks = dict(poller.poll())
+        self.assertEquals(socks[s2], zmq.POLLIN)
+
+        # Make sure that s2 goes into 0 after recv.
+        s2.recv()
+        socks = dict(poller.poll())
+        self.assertEquals(s2 in socks, 0)
+
+        poller.unregister(s1)
+        poller.unregister(s2)
+
+        # Wait for everything to finish.
+        wait()
+
+class TestSelect(PollZMQTestCase):
+
+    # This test is failing due to this issue:
+    # http://github.com/sustrik/zeromq2/issues#issue/26
+    def test_pair(self):
+        s1, s2 = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
+
+        # Sleep to allow sockets to connect.
+        wait()
+
+        rlist, wlist, xlist = zmq.select([s1, s2], [s1, s2], [s1, s2])
+        self.assert_(s1 in wlist)
+        self.assert_(s2 in wlist)
+        self.assert_(s1 not in rlist)
+        self.assert_(s2 not in rlist)
+

File zmq/tests/test_pubsub.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 unittest import TestCase
+
+import zmq
+from zmq.tests import BaseZMQTestCase
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+class TestPubSub(BaseZMQTestCase):
+
+    pass
+
+    # We are disabling this test while an issue is being resolved.
+    # def test_basic(self):
+    #     s1, s2 = self.create_bound_pair(zmq.PUB, zmq.SUB)
+    #     s2.setsockopt(zmq.SUBSCRIBE,'')
+    #     import time; time.sleep(0.5)
+    #     msg1 = 'message'
+    #     s1.send(msg1)
+    #     msg2 = s2.recv()  # This is blocking!
+    #     self.assertEquals(msg1, msg2)
+
+    def test_topic(self):
+        s1, s2 = self.create_bound_pair(zmq.PUB, zmq.SUB)
+        s2.setsockopt(zmq.SUBSCRIBE, 'x'.encode())
+        import time; time.sleep(0.1)
+        msg1 = 'message'.encode()
+        s1.send(msg1)
+        self.assertRaisesErrno(zmq.EAGAIN, s2.recv, zmq.NOBLOCK)
+        msg1 = 'xmessage'.encode()
+        s1.send(msg1)
+        msg2 = s2.recv()
+        self.assertEquals(msg1, msg2)
+

File zmq/tests/test_reqrep.py

+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 unittest import TestCase
+
+import zmq
+from zmq.tests import BaseZMQTestCase
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+class TestReqRep(BaseZMQTestCase):
+
+    def test_basic(self):
+        s1, s2 = self.create_bound_pair(zmq.REQ, zmq.REP)
+
+        msg1 = 'message 1'.encode()
+        msg2 = self.ping_pong(s1, s2, msg1)
+        self.assertEquals(msg1, msg2)
+
+    def test_multiple(self):
+        s1, s2 = self.create_bound_pair(zmq.REQ, zmq.REP)
+
+        for i in range(10):
+            msg1 = i*' '.encode()
+            msg2 = self.ping_pong(s1, s2, msg1)
+            self.assertEquals(msg1, msg2)
+
+    def test_bad_send_recv(self):
+        s1, s2 = self.create_bound_pair(zmq.REQ, zmq.REP)
+        for copy in (True,False):
+            self.assertRaisesErrno(zmq.EFSM, s1.recv, copy=copy)
+            self.assertRaisesErrno(zmq.EFSM, s2.send, 'asdf'.encode(), copy=copy)
+
+        # I have to have this or we die on an Abort trap.
+        msg1 = 'asdf'.encode()
+        msg2 = self.ping_pong(s1, s2, msg1)
+        self.assertEquals(msg1, msg2)
+
+    def test_json(self):
+        s1, s2 = self.create_bound_pair(zmq.REQ, zmq.REP)
+        o = dict(a=10,b=list(range(10)))
+        o2 = self.ping_pong_json(s1, s2, o)
+
+    def test_pyobj(self):
+        s1, s2 = self.create_bound_pair(zmq.REQ, zmq.REP)
+        o = dict(a=10,b=range(10))
+        o2 = self.ping_pong_pyobj(s1, s2, o)
+
+    def test_large_msg(self):
+        s1, s2 = self.create_bound_pair(zmq.REQ, zmq.REP)
+        msg1 = 10000*'X'.encode()
+
+        for i in range(10):
+            msg2 = self.ping_pong(s1, s2, msg1)
+            self.assertEquals(msg1, msg2)
+

File zmq/tests/test_socket.py

+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+#
+#    Copyright (c) 2010 Brian E. Granger
+#
+#    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 sys
+import time
+
+import zmq
+from zmq.tests import BaseZMQTestCase
+from zmq.utils.strtypes import bytes, unicode
+try:
+    from queue import Queue
+except:
+    from Queue import Queue
+
+#-----------------------------------------------------------------------------
+# Tests
+#-----------------------------------------------------------------------------
+
+class TestSocket(BaseZMQTestCase):
+
+    def test_create(self):
+        ctx = zmq.Context()
+        s = ctx.socket(zmq.PUB)
+        # Superluminal protocol not yet implemented
+        self.assertRaisesErrno(zmq.EPROTONOSUPPORT, s.bind, 'ftl://')
+        self.assertRaisesErrno(zmq.EPROTONOSUPPORT, s.connect, 'ftl://')
+        s.close()
+        del ctx
+    
+    def test_unicode_sockopts(self):
+        """test setting/getting sockopts with unicode strings"""
+        topic = "tést"
+        if str is not unicode:
+            topic = topic.decode('utf8')
+        p,s = self.create_bound_pair(zmq.PUB, zmq.SUB)
+        self.assertEquals(s.send_unicode, s.send_unicode)
+        self.assertEquals(p.recv_unicode, p.recv_unicode)
+        self.assertRaises(TypeError, s.setsockopt, zmq.SUBSCRIBE, topic)
+        self.assertRaises(TypeError, s.setsockopt, zmq.IDENTITY, topic)
+        self.assertRaises(TypeError, s.setsockopt, zmq.AFFINITY, topic)
+        s.setsockopt_unicode(zmq.SUBSCRIBE, topic)
+        s.setsockopt_unicode(zmq.IDENTITY, topic, 'utf16')
+        self.assertRaises(TypeError, s.getsockopt_unicode, zmq.AFFINITY)
+        self.assertRaises(TypeError, s.getsockopt_unicode, zmq.SUBSCRIBE)
+        st = s.getsockopt(zmq.IDENTITY)
+        self.assertEquals(st.decode('utf16'), s.getsockopt_unicode(zmq.IDENTITY, 'utf16'))
+        time.sleep(0.1) # wait for connection/subscription
+        p.send_unicode(topic,zmq.SNDMORE)
+        p.send_unicode(topic*2, encoding='latin-1')
+        self.assertEquals(topic, s.recv_unicode())
+        self.assertEquals(topic*2, s.recv_unicode(encoding='latin-1'))
+    
+    def test_send_unicode(self):
+        "test sending unicode objects"