OLD | NEW |
(Empty) | |
| 1 diff --git a/buildutils/config.py b/buildutils/config.py |
| 2 index 66f61e3..de2cd6e 100644 |
| 3 --- a/buildutils/config.py |
| 4 +++ b/buildutils/config.py |
| 5 @@ -87,6 +87,11 @@ def get_cfg_args(): |
| 6 cfg = cfg2dict(cfg) |
| 7 |
| 8 g = cfg.setdefault('global', {}) |
| 9 + if "NACL_BUILD_TREE" in os.environ: |
| 10 + NACL_TREE = os.environ["NACL_BUILD_TREE"] |
| 11 + cfg["global"]["zmq_prefix"] = NACL_TREE |
| 12 + cfg["global"]["have_sys_un_h"] = "False" |
| 13 + |
| 14 # boolean keys: |
| 15 for key in ['libzmq_extension', |
| 16 'bundle_libzmq_dylib', |
| 17 diff --git a/setup.cfg b/setup.cfg |
| 18 new file mode 100644 |
| 19 index 0000000..15686fc |
| 20 --- /dev/null |
| 21 +++ b/setup.cfg |
| 22 @@ -0,0 +1,3 @@ |
| 23 +[bdist_egg] |
| 24 +plat-name = pnacl |
| 25 + |
| 26 diff --git a/setup.py b/setup.py |
| 27 index 5348c61..a204e23 100755 |
| 28 --- a/setup.py |
| 29 +++ b/setup.py |
| 30 @@ -270,6 +270,10 @@ class Configure(build_ext): |
| 31 # include internal directories |
| 32 settings.setdefault('include_dirs', []) |
| 33 settings['include_dirs'] += [pjoin('zmq', sub) for sub in ('utils','cor
e','devices')] |
| 34 + if "NACL_BUILD_TREE" in os.environ: |
| 35 + settings['include_dirs'].append(pjoin( |
| 36 + os.environ["NACL_BUILD_TREE"], |
| 37 + "include", "glibc-compat")) |
| 38 |
| 39 for ext in self.distribution.ext_modules: |
| 40 if ext.name == 'zmq.libzmq': |
| 41 @@ -826,29 +830,29 @@ def dotc(subdir, name): |
| 42 |
| 43 libzmq = pxd('core', 'libzmq') |
| 44 buffers = pxd('utils', 'buffers') |
| 45 -message = pxd('core', 'message') |
| 46 -context = pxd('core', 'context') |
| 47 -socket = pxd('core', 'socket') |
| 48 +message = pxd('core', '_zmessage') |
| 49 +context = pxd('core', '_zcontext') |
| 50 +socket = pxd('core', '_zsocket') |
| 51 checkrc = pxd('core', 'checkrc') |
| 52 -monqueue = pxd('devices', 'monitoredqueue') |
| 53 +monqueue = pxd('devices', '_zmonitoredqueue') |
| 54 |
| 55 submodules = dict( |
| 56 - core = {'constants': [libzmq], |
| 57 - 'error':[libzmq, checkrc], |
| 58 - '_poll':[libzmq, socket, context, checkrc], |
| 59 - 'stopwatch':[libzmq, pxd('core','stopwatch'), checkrc], |
| 60 - 'context':[context, libzmq, checkrc], |
| 61 - 'message':[libzmq, buffers, message, checkrc], |
| 62 - 'socket':[context, message, socket, libzmq, buffers, checkrc], |
| 63 - '_device':[libzmq, socket, context, checkrc], |
| 64 - '_version':[libzmq], |
| 65 + core = {'_zconstants': [libzmq], |
| 66 + '_zerror':[libzmq, checkrc], |
| 67 + '__zpoll':[libzmq, socket, context, checkrc], |
| 68 + '_zstopwatch':[libzmq, pxd('core','_zstopwatch'), checkrc], |
| 69 + '_zcontext':[context, libzmq, checkrc], |
| 70 + '_zmessage':[libzmq, buffers, message, checkrc], |
| 71 + '_zsocket':[context, message, socket, libzmq, buffers, checkrc], |
| 72 + '__zdevice':[libzmq, socket, context, checkrc], |
| 73 + '__zversion':[libzmq], |
| 74 }, |
| 75 devices = { |
| 76 - 'monitoredqueue':[buffers, libzmq, monqueue, socket, context, check
rc], |
| 77 + '_zmonitoredqueue':[buffers, libzmq, monqueue, socket, context, che
ckrc], |
| 78 }, |
| 79 utils = { |
| 80 - 'initthreads':[libzmq], |
| 81 - 'rebuffer':[buffers], |
| 82 + '_zinitthreads':[libzmq], |
| 83 + '_zrebuffer':[buffers], |
| 84 }, |
| 85 ) |
| 86 |
| 87 #----------------------------------------------------------------------------- |
| 88 # Main setup |
| 89 #----------------------------------------------------------------------------- |
| 90 diff --git a/zmq/__init__.py b/zmq/__init__.py |
| 91 index 19cb4a9..c55ac5c 100644 |
| 92 --- a/zmq/__init__.py |
| 93 +++ b/zmq/__init__.py |
| 94 @@ -39,7 +39,7 @@ if bundled: |
| 95 |
| 96 if 'PyPy' not in sys.version: |
| 97 try: |
| 98 - from zmq.utils import initthreads # initialize threads |
| 99 + from zmq.utils import _zinitthreads as initthreads # initialize threads |
| 100 except ImportError as e: |
| 101 raise ImportError("%s\nAre you trying to `import zmq` from the pyzmq so
urce dir?" % e) |
| 102 else: |
| 103 diff --git a/zmq/core/__init__.py b/zmq/core/__init__.py |
| 104 index 862f1d5..275e47a 100644 |
| 105 --- a/zmq/core/__init__.py |
| 106 +++ b/zmq/core/__init__.py |
| 107 @@ -23,21 +23,21 @@ |
| 108 # Imports |
| 109 #----------------------------------------------------------------------------- |
| 110 |
| 111 -from zmq.core import (constants, error, message, context, |
| 112 - socket, stopwatch, _poll, _version, _device ) |
| 113 +from zmq.core import (_zconstants, _zerror, _zmessage, _zcontext, |
| 114 + _zsocket, _zstopwatch, __zpoll, __zversion, __zdevice ) |
| 115 |
| 116 __all__ = [] |
| 117 -for submod in (constants, error, message, context, |
| 118 - socket, stopwatch, _poll, _version, _device): |
| 119 +for submod in (_zconstants, _zerror, _zmessage, _zcontext, |
| 120 + _zsocket, _zstopwatch, __zpoll, __zversion, __zdevice): |
| 121 __all__.extend(submod.__all__) |
| 122 |
| 123 -from zmq.core.constants import * |
| 124 -from zmq.core.error import * |
| 125 -from zmq.core.message import * |
| 126 -from zmq.core.context import * |
| 127 -from zmq.core.socket import * |
| 128 -from zmq.core._poll import * |
| 129 -from zmq.core.stopwatch import * |
| 130 -from zmq.core._device import * |
| 131 -from zmq.core._version import * |
| 132 +from zmq.core._zconstants import * |
| 133 +from zmq.core._zerror import * |
| 134 +from zmq.core._zmessage import * |
| 135 +from zmq.core._zcontext import * |
| 136 +from zmq.core._zsocket import * |
| 137 +from zmq.core.__zpoll import * |
| 138 +from zmq.core._zstopwatch import * |
| 139 +from zmq.core.__zdevice import * |
| 140 +from zmq.core.__zversion import * |
| 141 |
| 142 diff --git a/zmq/core/__zdevice.pyx b/zmq/core/__zdevice.pyx |
| 143 new file mode 100644 |
| 144 index 0000000..99bcc27 |
| 145 --- /dev/null |
| 146 +++ b/zmq/core/__zdevice.pyx |
| 147 @@ -0,0 +1,86 @@ |
| 148 +"""Python binding for 0MQ device function.""" |
| 149 + |
| 150 +# |
| 151 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 152 +# |
| 153 +# This file is part of pyzmq. |
| 154 +# |
| 155 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 156 +# the terms of the Lesser GNU General Public License as published by |
| 157 +# the Free Software Foundation; either version 3 of the License, or |
| 158 +# (at your option) any later version. |
| 159 +# |
| 160 +# pyzmq is distributed in the hope that it will be useful, |
| 161 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 162 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 163 +# Lesser GNU General Public License for more details. |
| 164 +# |
| 165 +# You should have received a copy of the Lesser GNU General Public License |
| 166 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 167 +# |
| 168 + |
| 169 +#----------------------------------------------------------------------------- |
| 170 +# Imports |
| 171 +#----------------------------------------------------------------------------- |
| 172 + |
| 173 +from libzmq cimport zmq_device, zmq_proxy, ZMQ_VERSION_MAJOR |
| 174 +from zmq.core._zsocket cimport Socket as cSocket |
| 175 +from zmq.core.checkrc cimport _check_rc |
| 176 + |
| 177 +#----------------------------------------------------------------------------- |
| 178 +# Basic device API |
| 179 +#----------------------------------------------------------------------------- |
| 180 + |
| 181 +def device(int device_type, cSocket frontend, cSocket backend=None): |
| 182 + """device(device_type, frontend, backend) |
| 183 + |
| 184 + Start a zeromq device. |
| 185 + |
| 186 + WARNING: zmq.device is deprecated as of libzmq-3.2, |
| 187 + in favor of zmq.proxy. |
| 188 + |
| 189 + Parameters |
| 190 + ---------- |
| 191 + device_type : (QUEUE, FORWARDER, STREAMER) |
| 192 + The type of device to start. |
| 193 + frontend : Socket |
| 194 + The Socket instance for the incoming traffic. |
| 195 + backend : Socket |
| 196 + The Socket instance for the outbound traffic. |
| 197 + """ |
| 198 + if ZMQ_VERSION_MAJOR >= 3: |
| 199 + return proxy(frontend, backend) |
| 200 + |
| 201 + cdef int rc = 0 |
| 202 + with nogil: |
| 203 + rc = zmq_device(device_type, frontend.handle, backend.handle) |
| 204 + _check_rc(rc) |
| 205 + return rc |
| 206 + |
| 207 +def proxy(cSocket frontend, cSocket backend, cSocket capture=None): |
| 208 + """proxy(frontend, backend, capture) |
| 209 + |
| 210 + Start a zeromq proxy (replacement for device). |
| 211 + |
| 212 + Parameters |
| 213 + ---------- |
| 214 + frontend : Socket |
| 215 + The Socket instance for the incoming traffic. |
| 216 + backend : Socket |
| 217 + The Socket instance for the outbound traffic. |
| 218 + capture : Socket |
| 219 + The Socket instance for capturing traffic. |
| 220 + """ |
| 221 + cdef int rc = 0 |
| 222 + cdef void* capture_handle |
| 223 + if isinstance(capture, cSocket): |
| 224 + capture_handle = capture.handle |
| 225 + else: |
| 226 + capture_handle = NULL |
| 227 + with nogil: |
| 228 + rc = zmq_proxy(frontend.handle, backend.handle, capture_handle) |
| 229 + _check_rc(rc) |
| 230 + return rc |
| 231 + |
| 232 +__all__ = ['device', 'proxy'] |
| 233 + |
| 234 diff --git a/zmq/core/__zpoll.pyx b/zmq/core/__zpoll.pyx |
| 235 new file mode 100644 |
| 236 index 0000000..799b20b |
| 237 --- /dev/null |
| 238 +++ b/zmq/core/__zpoll.pyx |
| 239 @@ -0,0 +1,136 @@ |
| 240 +"""0MQ polling related functions and classes.""" |
| 241 + |
| 242 +# |
| 243 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 244 +# |
| 245 +# This file is part of pyzmq. |
| 246 +# |
| 247 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 248 +# the terms of the Lesser GNU General Public License as published by |
| 249 +# the Free Software Foundation; either version 3 of the License, or |
| 250 +# (at your option) any later version. |
| 251 +# |
| 252 +# pyzmq is distributed in the hope that it will be useful, |
| 253 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 254 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 255 +# Lesser GNU General Public License for more details. |
| 256 +# |
| 257 +# You should have received a copy of the Lesser GNU General Public License |
| 258 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 259 +# |
| 260 + |
| 261 +#----------------------------------------------------------------------------- |
| 262 +# Imports |
| 263 +#----------------------------------------------------------------------------- |
| 264 + |
| 265 +from libc.stdlib cimport free, malloc |
| 266 + |
| 267 +from libzmq cimport zmq_pollitem_t, ZMQ_VERSION_MAJOR |
| 268 +from libzmq cimport zmq_poll as zmq_poll_c |
| 269 +from _zsocket cimport Socket |
| 270 + |
| 271 +import sys |
| 272 + |
| 273 +from zmq.core.checkrc cimport _check_rc |
| 274 + |
| 275 +#----------------------------------------------------------------------------- |
| 276 +# Polling related methods |
| 277 +#----------------------------------------------------------------------------- |
| 278 + |
| 279 +# version-independent typecheck for int/long |
| 280 +if sys.version_info[0] >= 3: |
| 281 + int_t = int |
| 282 +else: |
| 283 + int_t = (int,long) |
| 284 + |
| 285 +def zmq_poll(sockets, long timeout=-1): |
| 286 + """zmq_poll(sockets, timeout=-1) |
| 287 + |
| 288 + Poll a set of 0MQ sockets, native file descs. or sockets. |
| 289 + |
| 290 + Parameters |
| 291 + ---------- |
| 292 + sockets : list of tuples of (socket, flags) |
| 293 + Each element of this list is a two-tuple containing a socket |
| 294 + and a flags. The socket may be a 0MQ socket or any object with |
| 295 + a ``fileno()`` method. The flags can be zmq.POLLIN (for detecting |
| 296 + for incoming messages), zmq.POLLOUT (for detecting that send is OK) |
| 297 + or zmq.POLLIN|zmq.POLLOUT for detecting both. |
| 298 + timeout : int |
| 299 + The number of milliseconds to poll for. Negative means no timeout. |
| 300 + """ |
| 301 + cdef int rc, i |
| 302 + cdef zmq_pollitem_t *pollitems = NULL |
| 303 + cdef int nsockets = <int>len(sockets) |
| 304 + cdef Socket current_socket |
| 305 + |
| 306 + if nsockets == 0: |
| 307 + return [] |
| 308 + |
| 309 + pollitems = <zmq_pollitem_t *>malloc(nsockets*sizeof(zmq_pollitem_t)) |
| 310 + if pollitems == NULL: |
| 311 + raise MemoryError("Could not allocate poll items") |
| 312 + |
| 313 + if ZMQ_VERSION_MAJOR < 3: |
| 314 + # timeout is us in 2.x, ms in 3.x |
| 315 + # expected input is ms (matches 3.x) |
| 316 + timeout = 1000*timeout |
| 317 + |
| 318 + for i in range(nsockets): |
| 319 + s = sockets[i][0] |
| 320 + events = sockets[i][1] |
| 321 + if isinstance(s, Socket): |
| 322 + current_socket = s |
| 323 + pollitems[i].socket = current_socket.handle |
| 324 + pollitems[i].events = events |
| 325 + pollitems[i].revents = 0 |
| 326 + elif isinstance(s, int_t): |
| 327 + pollitems[i].socket = NULL |
| 328 + pollitems[i].fd = s |
| 329 + pollitems[i].events = events |
| 330 + pollitems[i].revents = 0 |
| 331 + elif hasattr(s, 'fileno'): |
| 332 + try: |
| 333 + fileno = int(s.fileno()) |
| 334 + except: |
| 335 + free(pollitems) |
| 336 + raise ValueError('fileno() must return an valid integer fd') |
| 337 + else: |
| 338 + pollitems[i].socket = NULL |
| 339 + pollitems[i].fd = fileno |
| 340 + pollitems[i].events = events |
| 341 + pollitems[i].revents = 0 |
| 342 + else: |
| 343 + free(pollitems) |
| 344 + raise TypeError( |
| 345 + "Socket must be a 0MQ socket, an integer fd or have " |
| 346 + "a fileno() method: %r" % s |
| 347 + ) |
| 348 + |
| 349 + |
| 350 + with nogil: |
| 351 + rc = zmq_poll_c(pollitems, nsockets, timeout) |
| 352 + |
| 353 + if rc < 0: |
| 354 + free(pollitems) |
| 355 + _check_rc(rc) |
| 356 + |
| 357 + results = [] |
| 358 + for i in range(nsockets): |
| 359 + s = sockets[i][0] |
| 360 + # Return the fd for sockets, for compat. with select.poll. |
| 361 + if hasattr(s, 'fileno'): |
| 362 + s = s.fileno() |
| 363 + revents = pollitems[i].revents |
| 364 + # Only return sockets with non-zero status for compat. with select.poll
. |
| 365 + if revents > 0: |
| 366 + results.append((s, revents)) |
| 367 + |
| 368 + free(pollitems) |
| 369 + return results |
| 370 + |
| 371 +#----------------------------------------------------------------------------- |
| 372 +# Symbols to export |
| 373 +#----------------------------------------------------------------------------- |
| 374 + |
| 375 +__all__ = [ 'zmq_poll' ] |
| 376 diff --git a/zmq/core/__zversion.pyx b/zmq/core/__zversion.pyx |
| 377 new file mode 100644 |
| 378 index 0000000..02cf6fc |
| 379 --- /dev/null |
| 380 +++ b/zmq/core/__zversion.pyx |
| 381 @@ -0,0 +1,43 @@ |
| 382 +"""PyZMQ and 0MQ version functions.""" |
| 383 + |
| 384 +# |
| 385 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 386 +# |
| 387 +# This file is part of pyzmq. |
| 388 +# |
| 389 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 390 +# the terms of the Lesser GNU General Public License as published by |
| 391 +# the Free Software Foundation; either version 3 of the License, or |
| 392 +# (at your option) any later version. |
| 393 +# |
| 394 +# pyzmq is distributed in the hope that it will be useful, |
| 395 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 396 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 397 +# Lesser GNU General Public License for more details. |
| 398 +# |
| 399 +# You should have received a copy of the Lesser GNU General Public License |
| 400 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 401 +# |
| 402 + |
| 403 +#----------------------------------------------------------------------------- |
| 404 +# Imports |
| 405 +#----------------------------------------------------------------------------- |
| 406 + |
| 407 +from libzmq cimport _zmq_version |
| 408 + |
| 409 +#----------------------------------------------------------------------------- |
| 410 +# Code |
| 411 +#----------------------------------------------------------------------------- |
| 412 + |
| 413 +def zmq_version_info(): |
| 414 + """zmq_version_info() |
| 415 + |
| 416 + Return the version of ZeroMQ itself as a 3-tuple of ints. |
| 417 + """ |
| 418 + cdef int major, minor, patch |
| 419 + _zmq_version(&major, &minor, &patch) |
| 420 + return (major, minor, patch) |
| 421 + |
| 422 + |
| 423 +__all__ = ['zmq_version_info'] |
| 424 + |
| 425 diff --git a/zmq/core/_device.pyx b/zmq/core/_device.pyx |
| 426 deleted file mode 100644 |
| 427 index 5471e73..0000000 |
| 428 --- a/zmq/core/_device.pyx |
| 429 +++ /dev/null |
| 430 @@ -1,86 +0,0 @@ |
| 431 -"""Python binding for 0MQ device function.""" |
| 432 - |
| 433 -# |
| 434 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 435 -# |
| 436 -# This file is part of pyzmq. |
| 437 -# |
| 438 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 439 -# the terms of the Lesser GNU General Public License as published by |
| 440 -# the Free Software Foundation; either version 3 of the License, or |
| 441 -# (at your option) any later version. |
| 442 -# |
| 443 -# pyzmq is distributed in the hope that it will be useful, |
| 444 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 445 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 446 -# Lesser GNU General Public License for more details. |
| 447 -# |
| 448 -# You should have received a copy of the Lesser GNU General Public License |
| 449 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 450 -# |
| 451 - |
| 452 -#----------------------------------------------------------------------------- |
| 453 -# Imports |
| 454 -#----------------------------------------------------------------------------- |
| 455 - |
| 456 -from libzmq cimport zmq_device, zmq_proxy, ZMQ_VERSION_MAJOR |
| 457 -from zmq.core.socket cimport Socket as cSocket |
| 458 -from zmq.core.checkrc cimport _check_rc |
| 459 - |
| 460 -#----------------------------------------------------------------------------- |
| 461 -# Basic device API |
| 462 -#----------------------------------------------------------------------------- |
| 463 - |
| 464 -def device(int device_type, cSocket frontend, cSocket backend=None): |
| 465 - """device(device_type, frontend, backend) |
| 466 - |
| 467 - Start a zeromq device. |
| 468 - |
| 469 - WARNING: zmq.device is deprecated as of libzmq-3.2, |
| 470 - in favor of zmq.proxy. |
| 471 - |
| 472 - Parameters |
| 473 - ---------- |
| 474 - device_type : (QUEUE, FORWARDER, STREAMER) |
| 475 - The type of device to start. |
| 476 - frontend : Socket |
| 477 - The Socket instance for the incoming traffic. |
| 478 - backend : Socket |
| 479 - The Socket instance for the outbound traffic. |
| 480 - """ |
| 481 - if ZMQ_VERSION_MAJOR >= 3: |
| 482 - return proxy(frontend, backend) |
| 483 - |
| 484 - cdef int rc = 0 |
| 485 - with nogil: |
| 486 - rc = zmq_device(device_type, frontend.handle, backend.handle) |
| 487 - _check_rc(rc) |
| 488 - return rc |
| 489 - |
| 490 -def proxy(cSocket frontend, cSocket backend, cSocket capture=None): |
| 491 - """proxy(frontend, backend, capture) |
| 492 - |
| 493 - Start a zeromq proxy (replacement for device). |
| 494 - |
| 495 - Parameters |
| 496 - ---------- |
| 497 - frontend : Socket |
| 498 - The Socket instance for the incoming traffic. |
| 499 - backend : Socket |
| 500 - The Socket instance for the outbound traffic. |
| 501 - capture : Socket |
| 502 - The Socket instance for capturing traffic. |
| 503 - """ |
| 504 - cdef int rc = 0 |
| 505 - cdef void* capture_handle |
| 506 - if isinstance(capture, cSocket): |
| 507 - capture_handle = capture.handle |
| 508 - else: |
| 509 - capture_handle = NULL |
| 510 - with nogil: |
| 511 - rc = zmq_proxy(frontend.handle, backend.handle, capture_handle) |
| 512 - _check_rc(rc) |
| 513 - return rc |
| 514 - |
| 515 -__all__ = ['device', 'proxy'] |
| 516 - |
| 517 diff --git a/zmq/core/_poll.pyx b/zmq/core/_poll.pyx |
| 518 deleted file mode 100644 |
| 519 index 9db19e1..0000000 |
| 520 --- a/zmq/core/_poll.pyx |
| 521 +++ /dev/null |
| 522 @@ -1,136 +0,0 @@ |
| 523 -"""0MQ polling related functions and classes.""" |
| 524 - |
| 525 -# |
| 526 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 527 -# |
| 528 -# This file is part of pyzmq. |
| 529 -# |
| 530 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 531 -# the terms of the Lesser GNU General Public License as published by |
| 532 -# the Free Software Foundation; either version 3 of the License, or |
| 533 -# (at your option) any later version. |
| 534 -# |
| 535 -# pyzmq is distributed in the hope that it will be useful, |
| 536 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 537 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 538 -# Lesser GNU General Public License for more details. |
| 539 -# |
| 540 -# You should have received a copy of the Lesser GNU General Public License |
| 541 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 542 -# |
| 543 - |
| 544 -#----------------------------------------------------------------------------- |
| 545 -# Imports |
| 546 -#----------------------------------------------------------------------------- |
| 547 - |
| 548 -from libc.stdlib cimport free, malloc |
| 549 - |
| 550 -from libzmq cimport zmq_pollitem_t, ZMQ_VERSION_MAJOR |
| 551 -from libzmq cimport zmq_poll as zmq_poll_c |
| 552 -from socket cimport Socket |
| 553 - |
| 554 -import sys |
| 555 - |
| 556 -from zmq.core.checkrc cimport _check_rc |
| 557 - |
| 558 -#----------------------------------------------------------------------------- |
| 559 -# Polling related methods |
| 560 -#----------------------------------------------------------------------------- |
| 561 - |
| 562 -# version-independent typecheck for int/long |
| 563 -if sys.version_info[0] >= 3: |
| 564 - int_t = int |
| 565 -else: |
| 566 - int_t = (int,long) |
| 567 - |
| 568 -def zmq_poll(sockets, long timeout=-1): |
| 569 - """zmq_poll(sockets, timeout=-1) |
| 570 - |
| 571 - Poll a set of 0MQ sockets, native file descs. or sockets. |
| 572 - |
| 573 - Parameters |
| 574 - ---------- |
| 575 - sockets : list of tuples of (socket, flags) |
| 576 - Each element of this list is a two-tuple containing a socket |
| 577 - and a flags. The socket may be a 0MQ socket or any object with |
| 578 - a ``fileno()`` method. The flags can be zmq.POLLIN (for detecting |
| 579 - for incoming messages), zmq.POLLOUT (for detecting that send is OK) |
| 580 - or zmq.POLLIN|zmq.POLLOUT for detecting both. |
| 581 - timeout : int |
| 582 - The number of milliseconds to poll for. Negative means no timeout. |
| 583 - """ |
| 584 - cdef int rc, i |
| 585 - cdef zmq_pollitem_t *pollitems = NULL |
| 586 - cdef int nsockets = <int>len(sockets) |
| 587 - cdef Socket current_socket |
| 588 - |
| 589 - if nsockets == 0: |
| 590 - return [] |
| 591 - |
| 592 - pollitems = <zmq_pollitem_t *>malloc(nsockets*sizeof(zmq_pollitem_t)) |
| 593 - if pollitems == NULL: |
| 594 - raise MemoryError("Could not allocate poll items") |
| 595 - |
| 596 - if ZMQ_VERSION_MAJOR < 3: |
| 597 - # timeout is us in 2.x, ms in 3.x |
| 598 - # expected input is ms (matches 3.x) |
| 599 - timeout = 1000*timeout |
| 600 - |
| 601 - for i in range(nsockets): |
| 602 - s = sockets[i][0] |
| 603 - events = sockets[i][1] |
| 604 - if isinstance(s, Socket): |
| 605 - current_socket = s |
| 606 - pollitems[i].socket = current_socket.handle |
| 607 - pollitems[i].events = events |
| 608 - pollitems[i].revents = 0 |
| 609 - elif isinstance(s, int_t): |
| 610 - pollitems[i].socket = NULL |
| 611 - pollitems[i].fd = s |
| 612 - pollitems[i].events = events |
| 613 - pollitems[i].revents = 0 |
| 614 - elif hasattr(s, 'fileno'): |
| 615 - try: |
| 616 - fileno = int(s.fileno()) |
| 617 - except: |
| 618 - free(pollitems) |
| 619 - raise ValueError('fileno() must return an valid integer fd') |
| 620 - else: |
| 621 - pollitems[i].socket = NULL |
| 622 - pollitems[i].fd = fileno |
| 623 - pollitems[i].events = events |
| 624 - pollitems[i].revents = 0 |
| 625 - else: |
| 626 - free(pollitems) |
| 627 - raise TypeError( |
| 628 - "Socket must be a 0MQ socket, an integer fd or have " |
| 629 - "a fileno() method: %r" % s |
| 630 - ) |
| 631 - |
| 632 - |
| 633 - with nogil: |
| 634 - rc = zmq_poll_c(pollitems, nsockets, timeout) |
| 635 - |
| 636 - if rc < 0: |
| 637 - free(pollitems) |
| 638 - _check_rc(rc) |
| 639 - |
| 640 - results = [] |
| 641 - for i in range(nsockets): |
| 642 - s = sockets[i][0] |
| 643 - # Return the fd for sockets, for compat. with select.poll. |
| 644 - if hasattr(s, 'fileno'): |
| 645 - s = s.fileno() |
| 646 - revents = pollitems[i].revents |
| 647 - # Only return sockets with non-zero status for compat. with select.poll
. |
| 648 - if revents > 0: |
| 649 - results.append((s, revents)) |
| 650 - |
| 651 - free(pollitems) |
| 652 - return results |
| 653 - |
| 654 -#----------------------------------------------------------------------------- |
| 655 -# Symbols to export |
| 656 -#----------------------------------------------------------------------------- |
| 657 - |
| 658 -__all__ = [ 'zmq_poll' ] |
| 659 diff --git a/zmq/core/_version.pyx b/zmq/core/_version.pyx |
| 660 deleted file mode 100644 |
| 661 index 02cf6fc..0000000 |
| 662 --- a/zmq/core/_version.pyx |
| 663 +++ /dev/null |
| 664 @@ -1,43 +0,0 @@ |
| 665 -"""PyZMQ and 0MQ version functions.""" |
| 666 - |
| 667 -# |
| 668 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 669 -# |
| 670 -# This file is part of pyzmq. |
| 671 -# |
| 672 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 673 -# the terms of the Lesser GNU General Public License as published by |
| 674 -# the Free Software Foundation; either version 3 of the License, or |
| 675 -# (at your option) any later version. |
| 676 -# |
| 677 -# pyzmq is distributed in the hope that it will be useful, |
| 678 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 679 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 680 -# Lesser GNU General Public License for more details. |
| 681 -# |
| 682 -# You should have received a copy of the Lesser GNU General Public License |
| 683 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 684 -# |
| 685 - |
| 686 -#----------------------------------------------------------------------------- |
| 687 -# Imports |
| 688 -#----------------------------------------------------------------------------- |
| 689 - |
| 690 -from libzmq cimport _zmq_version |
| 691 - |
| 692 -#----------------------------------------------------------------------------- |
| 693 -# Code |
| 694 -#----------------------------------------------------------------------------- |
| 695 - |
| 696 -def zmq_version_info(): |
| 697 - """zmq_version_info() |
| 698 - |
| 699 - Return the version of ZeroMQ itself as a 3-tuple of ints. |
| 700 - """ |
| 701 - cdef int major, minor, patch |
| 702 - _zmq_version(&major, &minor, &patch) |
| 703 - return (major, minor, patch) |
| 704 - |
| 705 - |
| 706 -__all__ = ['zmq_version_info'] |
| 707 - |
| 708 diff --git a/zmq/core/_zconstants.pyx b/zmq/core/_zconstants.pyx |
| 709 new file mode 100644 |
| 710 index 0000000..fa2695d |
| 711 --- /dev/null |
| 712 +++ b/zmq/core/_zconstants.pyx |
| 713 @@ -0,0 +1,190 @@ |
| 714 +"""0MQ Constants.""" |
| 715 + |
| 716 +# |
| 717 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 718 +# |
| 719 +# This file is part of pyzmq. |
| 720 +# |
| 721 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 722 +# the terms of the Lesser GNU General Public License as published by |
| 723 +# the Free Software Foundation; either version 3 of the License, or |
| 724 +# (at your option) any later version. |
| 725 +# |
| 726 +# pyzmq is distributed in the hope that it will be useful, |
| 727 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 728 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 729 +# Lesser GNU General Public License for more details. |
| 730 +# |
| 731 +# You should have received a copy of the Lesser GNU General Public License |
| 732 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 733 +# |
| 734 + |
| 735 +#----------------------------------------------------------------------------- |
| 736 +# Imports |
| 737 +#----------------------------------------------------------------------------- |
| 738 + |
| 739 +from libzmq cimport * |
| 740 + |
| 741 +#----------------------------------------------------------------------------- |
| 742 +# Python module level constants |
| 743 +#----------------------------------------------------------------------------- |
| 744 + |
| 745 +_optionals = [] |
| 746 + |
| 747 +if ZMQ_VERSION < 30000: |
| 748 + # backport DONTWAIT as alias to NOBLOCK |
| 749 + NOBLOCK = ZMQ_NOBLOCK |
| 750 + DONTWAIT = ZMQ_NOBLOCK |
| 751 +else: |
| 752 + # keep NOBLOCK as alias for new DONTWAIT |
| 753 + NOBLOCK = ZMQ_DONTWAIT |
| 754 + DONTWAIT = ZMQ_DONTWAIT |
| 755 + |
| 756 +VERSION = ZMQ_VERSION |
| 757 + |
| 758 +# socket types |
| 759 +PAIR = ZMQ_PAIR |
| 760 +PUB = ZMQ_PUB |
| 761 +SUB = ZMQ_SUB |
| 762 +REQ = ZMQ_REQ |
| 763 +REP = ZMQ_REP |
| 764 +DEALER = ZMQ_DEALER |
| 765 +ROUTER = ZMQ_ROUTER |
| 766 +PULL = ZMQ_PULL |
| 767 +PUSH = ZMQ_PUSH |
| 768 +XPUB = ZMQ_XPUB |
| 769 +XSUB = ZMQ_XSUB |
| 770 + |
| 771 +# keep deprecated aliases |
| 772 +XREQ = DEALER |
| 773 +XREP = ROUTER |
| 774 +UPSTREAM = PULL |
| 775 +DOWNSTREAM = PUSH |
| 776 + |
| 777 + |
| 778 +# socket options |
| 779 +AFFINITY = ZMQ_AFFINITY |
| 780 +IDENTITY = ZMQ_IDENTITY |
| 781 +SUBSCRIBE = ZMQ_SUBSCRIBE |
| 782 +UNSUBSCRIBE = ZMQ_UNSUBSCRIBE |
| 783 +RATE = ZMQ_RATE |
| 784 +RECOVERY_IVL = ZMQ_RECOVERY_IVL |
| 785 +RECONNECT_IVL_MAX = ZMQ_RECONNECT_IVL_MAX |
| 786 +SNDBUF = ZMQ_SNDBUF |
| 787 +RCVBUF = ZMQ_RCVBUF |
| 788 +RCVMORE = ZMQ_RCVMORE |
| 789 +SNDMORE = ZMQ_SNDMORE |
| 790 +POLLIN = ZMQ_POLLIN |
| 791 +POLLOUT = ZMQ_POLLOUT |
| 792 +POLLERR = ZMQ_POLLERR |
| 793 + |
| 794 +STREAMER = ZMQ_STREAMER |
| 795 +FORWARDER = ZMQ_FORWARDER |
| 796 +QUEUE = ZMQ_QUEUE |
| 797 + |
| 798 +# sockopts new in 2.2.0 |
| 799 +SNDTIMEO = ZMQ_SNDTIMEO |
| 800 +RCVTIMEO = ZMQ_RCVTIMEO |
| 801 + |
| 802 +# sockopts removed in 3.0.0 |
| 803 +HWM = ZMQ_HWM |
| 804 +SWAP = ZMQ_SWAP |
| 805 +MCAST_LOOP = ZMQ_MCAST_LOOP |
| 806 +RECOVERY_IVL_MSEC = ZMQ_RECOVERY_IVL_MSEC |
| 807 + |
| 808 +# new in 3.x |
| 809 +IO_THREADS = ZMQ_IO_THREADS |
| 810 +MAX_SOCKETS = ZMQ_MAX_SOCKETS |
| 811 + |
| 812 +MORE = ZMQ_MORE |
| 813 + |
| 814 +MAXMSGSIZE = ZMQ_MAXMSGSIZE |
| 815 +SNDHWM = ZMQ_SNDHWM |
| 816 +RCVHWM = ZMQ_RCVHWM |
| 817 +MULTICAST_HOPS = ZMQ_MULTICAST_HOPS |
| 818 +IPV4ONLY = ZMQ_IPV4ONLY |
| 819 +LAST_ENDPOINT = ZMQ_LAST_ENDPOINT |
| 820 + |
| 821 +ROUTER_MANDATORY = ZMQ_ROUTER_MANDATORY |
| 822 +# aliases |
| 823 +ROUTER_BEHAVIOR = ROUTER_MANDATORY |
| 824 +FAIL_UNROUTABLE = ROUTER_MANDATORY |
| 825 + |
| 826 +TCP_KEEPALIVE = ZMQ_TCP_KEEPALIVE |
| 827 +TCP_KEEPALIVE_CNT = ZMQ_TCP_KEEPALIVE_CNT |
| 828 +TCP_KEEPALIVE_IDLE = ZMQ_TCP_KEEPALIVE_IDLE |
| 829 +TCP_KEEPALIVE_INTVL = ZMQ_TCP_KEEPALIVE_INTVL |
| 830 +TCP_ACCEPT_FILTER = ZMQ_TCP_ACCEPT_FILTER |
| 831 +DELAY_ATTACH_ON_CONNECT = ZMQ_DELAY_ATTACH_ON_CONNECT |
| 832 +XPUB_VERBOSE = ZMQ_XPUB_VERBOSE |
| 833 +ROUTER_RAW = ZMQ_ROUTER_RAW |
| 834 + |
| 835 +EVENT_CONNECTED = ZMQ_EVENT_CONNECTED |
| 836 +EVENT_CONNECT_DELAYED = ZMQ_EVENT_CONNECT_DELAYED |
| 837 +EVENT_CONNECT_RETRIED = ZMQ_EVENT_CONNECT_RETRIED |
| 838 +EVENT_LISTENING = ZMQ_EVENT_LISTENING |
| 839 +EVENT_BIND_FAILED = ZMQ_EVENT_BIND_FAILED |
| 840 +EVENT_ACCEPTED = ZMQ_EVENT_ACCEPTED |
| 841 +EVENT_ACCEPT_FAILED = ZMQ_EVENT_ACCEPT_FAILED |
| 842 +EVENT_CLOSED = ZMQ_EVENT_CLOSED |
| 843 +EVENT_CLOSE_FAILED = ZMQ_EVENT_CLOSE_FAILED |
| 844 +EVENT_DISCONNECTED = ZMQ_EVENT_DISCONNECTED |
| 845 + |
| 846 +FD = ZMQ_FD |
| 847 +EVENTS = ZMQ_EVENTS |
| 848 +TYPE = ZMQ_TYPE |
| 849 +LINGER = ZMQ_LINGER |
| 850 +RECONNECT_IVL = ZMQ_RECONNECT_IVL |
| 851 +BACKLOG = ZMQ_BACKLOG |
| 852 + |
| 853 +# As new constants are added in future versions, add a new block here |
| 854 +# like the two above, checking agains the relevant value for ZMQ_VERSION. |
| 855 +# The constants will need to be added to libzmq.pxd and utils/zmq_compat.h |
| 856 +# as well. |
| 857 + |
| 858 +#----------------------------------------------------------------------------- |
| 859 +# Error handling |
| 860 +#----------------------------------------------------------------------------- |
| 861 + |
| 862 +# Often used standard errnos |
| 863 +from errno import ( |
| 864 + EAGAIN, |
| 865 + EINVAL, |
| 866 + EFAULT, |
| 867 + ENOMEM, |
| 868 + ENODEV |
| 869 +) |
| 870 + |
| 871 +# For Windows compatability |
| 872 +ENOTSUP = ZMQ_ENOTSUP |
| 873 +EPROTONOSUPPORT = ZMQ_EPROTONOSUPPORT |
| 874 +ENOBUFS = ZMQ_ENOBUFS |
| 875 +ENETDOWN = ZMQ_ENETDOWN |
| 876 +EADDRINUSE = ZMQ_EADDRINUSE |
| 877 +EADDRNOTAVAIL = ZMQ_EADDRNOTAVAIL |
| 878 +ECONNREFUSED = ZMQ_ECONNREFUSED |
| 879 +EINPROGRESS = ZMQ_EINPROGRESS |
| 880 +ENOTSOCK = ZMQ_ENOTSOCK |
| 881 + |
| 882 +# new errnos in zmq3 |
| 883 +EMSGSIZE = ZMQ_EMSGSIZE |
| 884 +EAFNOSUPPORT = ZMQ_EAFNOSUPPORT |
| 885 +ENETUNREACH = ZMQ_ENETUNREACH |
| 886 +ECONNABORTED = ZMQ_ECONNABORTED |
| 887 +ECONNRESET = ZMQ_ECONNRESET |
| 888 +ENOTCONN = ZMQ_ENOTCONN |
| 889 +ETIMEDOUT = ZMQ_ETIMEDOUT |
| 890 +EHOSTUNREACH = ZMQ_EHOSTUNREACH |
| 891 +ENETRESET = ZMQ_ENETRESET |
| 892 + |
| 893 +# 0MQ Native |
| 894 +EFSM = ZMQ_EFSM |
| 895 +ENOCOMPATPROTO = ZMQ_ENOCOMPATPROTO |
| 896 +ETERM = ZMQ_ETERM |
| 897 +EMTHREAD = ZMQ_EMTHREAD |
| 898 + |
| 899 +#----------------------------------------------------------------------------- |
| 900 +# Symbols to export |
| 901 +#----------------------------------------------------------------------------- |
| 902 +_names = list(locals().keys()) |
| 903 +__all__ = [ key for key in _names if not key.startswith('_') ] |
| 904 diff --git a/zmq/core/_zcontext.pxd b/zmq/core/_zcontext.pxd |
| 905 new file mode 100644 |
| 906 index 0000000..e399de5 |
| 907 --- /dev/null |
| 908 +++ b/zmq/core/_zcontext.pxd |
| 909 @@ -0,0 +1,40 @@ |
| 910 +"""0MQ Context class declaration.""" |
| 911 + |
| 912 +# |
| 913 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 914 +# |
| 915 +# This file is part of pyzmq. |
| 916 +# |
| 917 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 918 +# the terms of the Lesser GNU General Public License as published by |
| 919 +# the Free Software Foundation; either version 3 of the License, or |
| 920 +# (at your option) any later version. |
| 921 +# |
| 922 +# pyzmq is distributed in the hope that it will be useful, |
| 923 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 924 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 925 +# Lesser GNU General Public License for more details. |
| 926 +# |
| 927 +# You should have received a copy of the Lesser GNU General Public License |
| 928 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 929 +# |
| 930 + |
| 931 +#----------------------------------------------------------------------------- |
| 932 +# Code |
| 933 +#----------------------------------------------------------------------------- |
| 934 + |
| 935 +cdef class Context: |
| 936 + """Manage the lifecycle of a 0MQ context.""" |
| 937 + |
| 938 + cdef object __weakref__ # enable weakref |
| 939 + cdef void *handle # The C handle for the underlying zmq object. |
| 940 + cdef void **_sockets # A C-array containg socket handles |
| 941 + cdef size_t _n_sockets # the number of sockets |
| 942 + cdef size_t _max_sockets # the size of the _sockets array |
| 943 + cdef int _pid # the pid of the process which created me (for
fork safety) |
| 944 + |
| 945 + cdef public object closed # bool property for a closed context. |
| 946 + # helpers for events on _sockets in Socket.__cinit__()/close() |
| 947 + cdef inline void _add_socket(self, void* handle) |
| 948 + cdef inline void _remove_socket(self, void* handle) |
| 949 + |
| 950 diff --git a/zmq/core/_zcontext.pyx b/zmq/core/_zcontext.pyx |
| 951 new file mode 100644 |
| 952 index 0000000..0917c66 |
| 953 --- /dev/null |
| 954 +++ b/zmq/core/_zcontext.pyx |
| 955 @@ -0,0 +1,254 @@ |
| 956 +"""0MQ Context class.""" |
| 957 + |
| 958 +# |
| 959 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 960 +# |
| 961 +# This file is part of pyzmq. |
| 962 +# |
| 963 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 964 +# the terms of the Lesser GNU General Public License as published by |
| 965 +# the Free Software Foundation; either version 3 of the License, or |
| 966 +# (at your option) any later version. |
| 967 +# |
| 968 +# pyzmq is distributed in the hope that it will be useful, |
| 969 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 970 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 971 +# Lesser GNU General Public License for more details. |
| 972 +# |
| 973 +# You should have received a copy of the Lesser GNU General Public License |
| 974 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 975 +# |
| 976 + |
| 977 +#----------------------------------------------------------------------------- |
| 978 +# Imports |
| 979 +#----------------------------------------------------------------------------- |
| 980 + |
| 981 +from libc.stdlib cimport free, malloc, realloc |
| 982 + |
| 983 +from libzmq cimport * |
| 984 + |
| 985 +cdef extern from "getpid_compat.h": |
| 986 + int getpid() |
| 987 + |
| 988 +from zmq.error import ZMQError |
| 989 +from zmq.core.checkrc cimport _check_rc |
| 990 + |
| 991 +#----------------------------------------------------------------------------- |
| 992 +# Code |
| 993 +#----------------------------------------------------------------------------- |
| 994 + |
| 995 +_instance = None |
| 996 + |
| 997 +cdef class Context: |
| 998 + """Context(io_threads=1) |
| 999 + |
| 1000 + Manage the lifecycle of a 0MQ context. |
| 1001 + |
| 1002 + Parameters |
| 1003 + ---------- |
| 1004 + io_threads : int |
| 1005 + The number of IO threads. |
| 1006 + """ |
| 1007 + |
| 1008 + def __cinit__(self, int io_threads = 1, **kwargs): |
| 1009 + self.handle = NULL |
| 1010 + self._sockets = NULL |
| 1011 + |
| 1012 + if ZMQ_VERSION_MAJOR >= 3: |
| 1013 + self.handle = zmq_ctx_new() |
| 1014 + else: |
| 1015 + self.handle = zmq_init(io_threads) |
| 1016 + |
| 1017 + if self.handle == NULL: |
| 1018 + raise ZMQError() |
| 1019 + |
| 1020 + cdef int rc = 0 |
| 1021 + if ZMQ_VERSION_MAJOR >= 3: |
| 1022 + rc = zmq_ctx_set(self.handle, ZMQ_IO_THREADS, io_threads) |
| 1023 + _check_rc(rc) |
| 1024 + |
| 1025 + self.closed = False |
| 1026 + self._n_sockets = 0 |
| 1027 + self._max_sockets = 32 |
| 1028 + |
| 1029 + self._sockets = <void **>malloc(self._max_sockets*sizeof(void *)) |
| 1030 + if self._sockets == NULL: |
| 1031 + raise MemoryError("Could not allocate _sockets array") |
| 1032 + |
| 1033 + self._pid = getpid() |
| 1034 + |
| 1035 + def __init__(self, io_threads=1): |
| 1036 + # no-op |
| 1037 + pass |
| 1038 + |
| 1039 + |
| 1040 + def __del__(self): |
| 1041 + """deleting a Context should terminate it, without trying non-threadsaf
e destroy""" |
| 1042 + self.term() |
| 1043 + |
| 1044 + def __dealloc__(self): |
| 1045 + """don't touch members in dealloc, just cleanup allocations""" |
| 1046 + cdef int rc |
| 1047 + if self._sockets != NULL: |
| 1048 + free(self._sockets) |
| 1049 + self._sockets = NULL |
| 1050 + self._n_sockets = 0 |
| 1051 + self.term() |
| 1052 + |
| 1053 + cdef inline void _add_socket(self, void* handle): |
| 1054 + """Add a socket handle to be closed when Context terminates. |
| 1055 + |
| 1056 + This is to be called in the Socket constructor. |
| 1057 + """ |
| 1058 + # print self._n_sockets, self._max_sockets |
| 1059 + if self._n_sockets >= self._max_sockets: |
| 1060 + self._max_sockets *= 2 |
| 1061 + self._sockets = <void **>realloc(self._sockets, self._max_sockets*s
izeof(void *)) |
| 1062 + if self._sockets == NULL: |
| 1063 + raise MemoryError("Could not reallocate _sockets array") |
| 1064 + |
| 1065 + self._sockets[self._n_sockets] = handle |
| 1066 + self._n_sockets += 1 |
| 1067 + # print self._n_sockets, self._max_sockets |
| 1068 + |
| 1069 + cdef inline void _remove_socket(self, void* handle): |
| 1070 + """Remove a socket from the collected handles. |
| 1071 + |
| 1072 + This should be called by Socket.close, to prevent trying to |
| 1073 + close a socket a second time. |
| 1074 + """ |
| 1075 + cdef bint found = False |
| 1076 + |
| 1077 + for idx in range(self._n_sockets): |
| 1078 + if self._sockets[idx] == handle: |
| 1079 + found=True |
| 1080 + break |
| 1081 + |
| 1082 + if found: |
| 1083 + self._n_sockets -= 1 |
| 1084 + if self._n_sockets: |
| 1085 + # move last handle to closed socket's index |
| 1086 + self._sockets[idx] = self._sockets[self._n_sockets] |
| 1087 + |
| 1088 + @property |
| 1089 + def _handle(self): |
| 1090 + return <Py_ssize_t> self.handle |
| 1091 + |
| 1092 + def term(self): |
| 1093 + """ctx.term() |
| 1094 + |
| 1095 + Close or terminate the context. |
| 1096 + |
| 1097 + This can be called to close the context by hand. If this is not called, |
| 1098 + the context will automatically be closed when it is garbage collected. |
| 1099 + """ |
| 1100 + cdef int rc |
| 1101 + cdef int i=-1 |
| 1102 + |
| 1103 + if self.handle != NULL and not self.closed and getpid() == self._pid: |
| 1104 + with nogil: |
| 1105 + rc = zmq_ctx_destroy(self.handle) |
| 1106 + _check_rc(rc) |
| 1107 + self.handle = NULL |
| 1108 + self.closed = True |
| 1109 + |
| 1110 + def set(self, int option, optval): |
| 1111 + """ctx.set(option, optval) |
| 1112 + |
| 1113 + Set context options. |
| 1114 + |
| 1115 + See the 0MQ API documentation for zmq_ctx_set |
| 1116 + for details on specific options. |
| 1117 + |
| 1118 + New in libzmq-3.2 |
| 1119 + |
| 1120 + Parameters |
| 1121 + ---------- |
| 1122 + option : int |
| 1123 + The option to set. Available values will depend on your |
| 1124 + version of libzmq. Examples include:: |
| 1125 + |
| 1126 + zmq.IO_THREADS, zmq.MAX_SOCKETS |
| 1127 + |
| 1128 + optval : int |
| 1129 + The value of the option to set. |
| 1130 + """ |
| 1131 + cdef int optval_int_c |
| 1132 + cdef int rc |
| 1133 + cdef char* optval_c |
| 1134 + |
| 1135 + if self.closed: |
| 1136 + raise RuntimeError("Context has been destroyed") |
| 1137 + |
| 1138 + if not isinstance(optval, int): |
| 1139 + raise TypeError('expected int, got: %r' % optval) |
| 1140 + optval_int_c = optval |
| 1141 + rc = zmq_ctx_set(self.handle, option, optval_int_c) |
| 1142 + _check_rc(rc) |
| 1143 + |
| 1144 + def get(self, int option): |
| 1145 + """ctx.get(option) |
| 1146 + |
| 1147 + Get the value of a context option. |
| 1148 + |
| 1149 + See the 0MQ API documentation for zmq_ctx_get |
| 1150 + for details on specific options. |
| 1151 + |
| 1152 + New in libzmq-3.2 |
| 1153 + |
| 1154 + Parameters |
| 1155 + ---------- |
| 1156 + option : int |
| 1157 + The option to get. Available values will depend on your |
| 1158 + version of libzmq. Examples include:: |
| 1159 + |
| 1160 + zmq.IO_THREADS, zmq.MAX_SOCKETS |
| 1161 + |
| 1162 + Returns |
| 1163 + ------- |
| 1164 + optval : int |
| 1165 + The value of the option as an integer. |
| 1166 + """ |
| 1167 + cdef int optval_int_c |
| 1168 + cdef size_t sz |
| 1169 + cdef int rc |
| 1170 + |
| 1171 + if self.closed: |
| 1172 + raise RuntimeError("Context has been destroyed") |
| 1173 + |
| 1174 + rc = zmq_ctx_get(self.handle, option) |
| 1175 + _check_rc(rc) |
| 1176 + |
| 1177 + return rc |
| 1178 + |
| 1179 + def destroy(self, linger=None): |
| 1180 + """ctx.destroy(linger=None) |
| 1181 + |
| 1182 + Close all sockets associated with this context, and then terminate |
| 1183 + the context. If linger is specified, |
| 1184 + the LINGER sockopt of the sockets will be set prior to closing. |
| 1185 + |
| 1186 + WARNING: |
| 1187 + |
| 1188 + destroy involves calling zmq_close(), which is *NOT* threadsafe. |
| 1189 + If there are active sockets in other threads, this must not be called. |
| 1190 + """ |
| 1191 + |
| 1192 + cdef int linger_c |
| 1193 + cdef bint setlinger=False |
| 1194 + |
| 1195 + if linger is not None: |
| 1196 + linger_c = linger |
| 1197 + setlinger=True |
| 1198 + if self.handle != NULL and not self.closed and self._n_sockets: |
| 1199 + while self._n_sockets: |
| 1200 + if setlinger: |
| 1201 + zmq_setsockopt(self._sockets[0], ZMQ_LINGER, &linger_c, siz
eof(int)) |
| 1202 + rc = zmq_close(self._sockets[0]) |
| 1203 + if rc < 0 and zmq_errno() != ZMQ_ENOTSOCK: |
| 1204 + raise ZMQError() |
| 1205 + self._n_sockets -= 1 |
| 1206 + self._sockets[0] = self._sockets[self._n_sockets] |
| 1207 + self.term() |
| 1208 + |
| 1209 +__all__ = ['Context'] |
| 1210 diff --git a/zmq/core/_zerror.pyx b/zmq/core/_zerror.pyx |
| 1211 new file mode 100644 |
| 1212 index 0000000..85e785f |
| 1213 --- /dev/null |
| 1214 +++ b/zmq/core/_zerror.pyx |
| 1215 @@ -0,0 +1,56 @@ |
| 1216 +"""0MQ Error classes and functions.""" |
| 1217 + |
| 1218 +# |
| 1219 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 1220 +# |
| 1221 +# This file is part of pyzmq. |
| 1222 +# |
| 1223 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 1224 +# the terms of the Lesser GNU General Public License as published by |
| 1225 +# the Free Software Foundation; either version 3 of the License, or |
| 1226 +# (at your option) any later version. |
| 1227 +# |
| 1228 +# pyzmq is distributed in the hope that it will be useful, |
| 1229 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1230 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1231 +# Lesser GNU General Public License for more details. |
| 1232 +# |
| 1233 +# You should have received a copy of the Lesser GNU General Public License |
| 1234 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1235 +# |
| 1236 + |
| 1237 +#----------------------------------------------------------------------------- |
| 1238 +# Imports |
| 1239 +#----------------------------------------------------------------------------- |
| 1240 + |
| 1241 +# allow const char* |
| 1242 +cdef extern from *: |
| 1243 + ctypedef char* const_char_ptr "const char*" |
| 1244 + |
| 1245 +from libzmq cimport zmq_strerror, zmq_errno as zmq_errno_c |
| 1246 + |
| 1247 +from zmq.utils.strtypes import bytes |
| 1248 + |
| 1249 +def strerror(int errno): |
| 1250 + """strerror(errno) |
| 1251 + |
| 1252 + Return the error string given the error number. |
| 1253 + """ |
| 1254 + cdef const_char_ptr str_e |
| 1255 + # char * will be a bytes object: |
| 1256 + str_e = zmq_strerror(errno) |
| 1257 + if str is bytes: |
| 1258 + # Python 2: str is bytes, so we already have the right type |
| 1259 + return str_e |
| 1260 + else: |
| 1261 + # Python 3: decode bytes to unicode str |
| 1262 + return str_e.decode() |
| 1263 + |
| 1264 +def zmq_errno(): |
| 1265 + """zmq_errno() |
| 1266 + |
| 1267 + Return the integer errno of the most recent zmq error. |
| 1268 + """ |
| 1269 + return zmq_errno_c() |
| 1270 + |
| 1271 +__all__ = ['strerror', 'zmq_errno'] |
| 1272 diff --git a/zmq/core/_zmessage.pxd b/zmq/core/_zmessage.pxd |
| 1273 new file mode 100644 |
| 1274 index 0000000..a86a8e0 |
| 1275 --- /dev/null |
| 1276 +++ b/zmq/core/_zmessage.pxd |
| 1277 @@ -0,0 +1,66 @@ |
| 1278 +"""0MQ Message related class declarations.""" |
| 1279 + |
| 1280 +# |
| 1281 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 1282 +# |
| 1283 +# This file is part of pyzmq. |
| 1284 +# |
| 1285 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 1286 +# the terms of the Lesser GNU General Public License as published by |
| 1287 +# the Free Software Foundation; either version 3 of the License, or |
| 1288 +# (at your option) any later version. |
| 1289 +# |
| 1290 +# pyzmq is distributed in the hope that it will be useful, |
| 1291 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1292 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1293 +# Lesser GNU General Public License for more details. |
| 1294 +# |
| 1295 +# You should have received a copy of the Lesser GNU General Public License |
| 1296 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1297 +# |
| 1298 + |
| 1299 +#----------------------------------------------------------------------------- |
| 1300 +# Imports |
| 1301 +#----------------------------------------------------------------------------- |
| 1302 + |
| 1303 +from cpython cimport PyBytes_FromStringAndSize |
| 1304 + |
| 1305 +from libzmq cimport zmq_msg_t, zmq_msg_data, zmq_msg_size |
| 1306 + |
| 1307 +#----------------------------------------------------------------------------- |
| 1308 +# Code |
| 1309 +#----------------------------------------------------------------------------- |
| 1310 + |
| 1311 +cdef class MessageTracker(object): |
| 1312 + """A class for tracking if 0MQ is done using one or more messages.""" |
| 1313 + |
| 1314 + cdef set events # Message Event objects to track. |
| 1315 + cdef set peers # Other Message or MessageTracker objects. |
| 1316 + |
| 1317 + |
| 1318 +cdef class Frame: |
| 1319 + """A Message Frame class for non-copy send/recvs.""" |
| 1320 + |
| 1321 + cdef zmq_msg_t zmq_msg |
| 1322 + cdef object _data # The actual message data as a Python object. |
| 1323 + cdef object _buffer # A Python Buffer/View of the message contents |
| 1324 + cdef object _bytes # A bytes/str copy of the message. |
| 1325 + cdef bint _failed_init # Flag to handle failed zmq_msg_init |
| 1326 + cdef public object tracker_event # Event for use with zmq_free_fn. |
| 1327 + cdef public object tracker # MessageTracker object. |
| 1328 + cdef public bint more # whether RCVMORE was set |
| 1329 + |
| 1330 + cdef Frame fast_copy(self) # Create shallow copy of Message object. |
| 1331 + cdef object _getbuffer(self) # Construct self._buffer. |
| 1332 + |
| 1333 + |
| 1334 +cdef inline object copy_zmq_msg_bytes(zmq_msg_t *zmq_msg): |
| 1335 + """ Copy the data from a zmq_msg_t """ |
| 1336 + cdef char *data_c = NULL |
| 1337 + cdef Py_ssize_t data_len_c |
| 1338 + with nogil: |
| 1339 + data_c = <char *>zmq_msg_data(zmq_msg) |
| 1340 + data_len_c = zmq_msg_size(zmq_msg) |
| 1341 + return PyBytes_FromStringAndSize(data_c, data_len_c) |
| 1342 + |
| 1343 + |
| 1344 diff --git a/zmq/core/_zmessage.pyx b/zmq/core/_zmessage.pyx |
| 1345 new file mode 100644 |
| 1346 index 0000000..1d358ab |
| 1347 --- /dev/null |
| 1348 +++ b/zmq/core/_zmessage.pyx |
| 1349 @@ -0,0 +1,297 @@ |
| 1350 +"""0MQ Message related classes.""" |
| 1351 + |
| 1352 +# |
| 1353 +# Copyright (c) 2013 Brian E. Granger & Min Ragan-Kelley |
| 1354 +# |
| 1355 +# This file is part of pyzmq. |
| 1356 +# |
| 1357 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 1358 +# the terms of the Lesser GNU General Public License as published by |
| 1359 +# the Free Software Foundation; either version 3 of the License, or |
| 1360 +# (at your option) any later version. |
| 1361 +# |
| 1362 +# pyzmq is distributed in the hope that it will be useful, |
| 1363 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1364 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1365 +# Lesser GNU General Public License for more details. |
| 1366 +# |
| 1367 +# You should have received a copy of the Lesser GNU General Public License |
| 1368 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1369 +# |
| 1370 + |
| 1371 +#----------------------------------------------------------------------------- |
| 1372 +# Imports |
| 1373 +#----------------------------------------------------------------------------- |
| 1374 + |
| 1375 +# get version-independent aliases: |
| 1376 +cdef extern from "pyversion_compat.h": |
| 1377 + pass |
| 1378 + |
| 1379 +from cpython cimport Py_DECREF, Py_INCREF |
| 1380 + |
| 1381 +from buffers cimport asbuffer_r, viewfromobject_r |
| 1382 + |
| 1383 +cdef extern from "Python.h": |
| 1384 + ctypedef int Py_ssize_t |
| 1385 + |
| 1386 +from libzmq cimport * |
| 1387 + |
| 1388 +import time |
| 1389 + |
| 1390 +try: |
| 1391 + # below 3.3 |
| 1392 + from threading import _Event as Event |
| 1393 +except (ImportError, AttributeError): |
| 1394 + # python throws ImportError, cython throws AttributeError |
| 1395 + from threading import Event |
| 1396 + |
| 1397 +import zmq |
| 1398 +from zmq.core.checkrc cimport _check_rc |
| 1399 +from zmq.utils.strtypes import bytes,unicode,basestring |
| 1400 + |
| 1401 +#----------------------------------------------------------------------------- |
| 1402 +# Code |
| 1403 +#----------------------------------------------------------------------------- |
| 1404 + |
| 1405 + |
| 1406 +cdef void free_python_msg(void *data, void *hint) with gil: |
| 1407 + """A function for DECREF'ing Python based messages.""" |
| 1408 + if hint != NULL: |
| 1409 + tracker_event = (<tuple>hint)[1] |
| 1410 + Py_DECREF(<object>hint) |
| 1411 + if isinstance(tracker_event, Event): |
| 1412 + # don't assert before DECREF: |
| 1413 + # assert tracker_queue.empty(), "somebody else wrote to my Queue!" |
| 1414 + tracker_event.set() |
| 1415 + tracker_event = None |
| 1416 + |
| 1417 + |
| 1418 +cdef class Frame: |
| 1419 + """Frame(data=None, track=False) |
| 1420 + |
| 1421 + A zmq message Frame class for non-copy send/recvs. |
| 1422 + |
| 1423 + This class is only needed if you want to do non-copying send and recvs. |
| 1424 + When you pass a string to this class, like ``Frame(s)``, the |
| 1425 + ref-count of `s` is increased by two: once because the Frame saves `s` as |
| 1426 + an instance attribute and another because a ZMQ message is created that |
| 1427 + points to the buffer of `s`. This second ref-count increase makes sure |
| 1428 + that `s` lives until all messages that use it have been sent. Once 0MQ |
| 1429 + sends all the messages and it doesn't need the buffer of s, 0MQ will call |
| 1430 + ``Py_DECREF(s)``. |
| 1431 + |
| 1432 + Parameters |
| 1433 + ---------- |
| 1434 + |
| 1435 + data : object, optional |
| 1436 + any object that provides the buffer interface will be used to |
| 1437 + construct the 0MQ message data. |
| 1438 + track : bool [default: False] |
| 1439 + whether a MessageTracker_ should be created to track this object. |
| 1440 + Tracking a message has a cost at creation, because it creates a threads
afe |
| 1441 + Event object. |
| 1442 + |
| 1443 + """ |
| 1444 + |
| 1445 + def __cinit__(self, object data=None, track=False, **kwargs): |
| 1446 + cdef int rc |
| 1447 + cdef char *data_c = NULL |
| 1448 + cdef Py_ssize_t data_len_c=0 |
| 1449 + cdef object hint |
| 1450 + |
| 1451 + # init more as False |
| 1452 + self.more = False |
| 1453 + |
| 1454 + # Save the data object in case the user wants the the data as a str. |
| 1455 + self._data = data |
| 1456 + self._failed_init = True # bool switch for dealloc |
| 1457 + self._buffer = None # buffer view of data |
| 1458 + self._bytes = None # bytes copy of data |
| 1459 + |
| 1460 + # Event and MessageTracker for monitoring when zmq is done with data: |
| 1461 + if track: |
| 1462 + evt = Event() |
| 1463 + self.tracker_event = evt |
| 1464 + self.tracker = zmq.MessageTracker(evt) |
| 1465 + else: |
| 1466 + self.tracker_event = None |
| 1467 + self.tracker = None |
| 1468 + |
| 1469 + if isinstance(data, unicode): |
| 1470 + raise TypeError("Unicode objects not allowed. Only: str/bytes, buff
er interfaces.") |
| 1471 + |
| 1472 + if data is None: |
| 1473 + with nogil: |
| 1474 + rc = zmq_msg_init(&self.zmq_msg) |
| 1475 + _check_rc(rc) |
| 1476 + self._failed_init = False |
| 1477 + return |
| 1478 + else: |
| 1479 + asbuffer_r(data, <void **>&data_c, &data_len_c) |
| 1480 + # We INCREF the *original* Python object (not self) and pass it |
| 1481 + # as the hint below. This allows other copies of this Frame |
| 1482 + # object to take over the ref counting of data properly. |
| 1483 + hint = (data, self.tracker_event) |
| 1484 + Py_INCREF(hint) |
| 1485 + with nogil: |
| 1486 + rc = zmq_msg_init_data( |
| 1487 + &self.zmq_msg, <void *>data_c, data_len_c, |
| 1488 + <zmq_free_fn *>free_python_msg, <void *>hint |
| 1489 + ) |
| 1490 + if rc != 0: |
| 1491 + Py_DECREF(hint) |
| 1492 + _check_rc(rc) |
| 1493 + self._failed_init = False |
| 1494 + |
| 1495 + def __init__(self, object data=None, track=False): |
| 1496 + """Enforce signature""" |
| 1497 + pass |
| 1498 + |
| 1499 + def __dealloc__(self): |
| 1500 + cdef int rc |
| 1501 + if self._failed_init: |
| 1502 + return |
| 1503 + # This simply decreases the 0MQ ref-count of zmq_msg. |
| 1504 + with nogil: |
| 1505 + rc = zmq_msg_close(&self.zmq_msg) |
| 1506 + _check_rc(rc) |
| 1507 + |
| 1508 + # buffer interface code adapted from petsc4py by Lisandro Dalcin, a BSD pro
ject |
| 1509 + |
| 1510 + def __getbuffer__(self, Py_buffer* buffer, int flags): |
| 1511 + # new-style (memoryview) buffer interface |
| 1512 + with nogil: |
| 1513 + buffer.buf = zmq_msg_data(&self.zmq_msg) |
| 1514 + buffer.len = zmq_msg_size(&self.zmq_msg) |
| 1515 + |
| 1516 + buffer.obj = self |
| 1517 + buffer.readonly = 1 |
| 1518 + buffer.format = "B" |
| 1519 + buffer.ndim = 0 |
| 1520 + buffer.shape = NULL |
| 1521 + buffer.strides = NULL |
| 1522 + buffer.suboffsets = NULL |
| 1523 + buffer.itemsize = 1 |
| 1524 + buffer.internal = NULL |
| 1525 + |
| 1526 + def __getsegcount__(self, Py_ssize_t *lenp): |
| 1527 + # required for getreadbuffer |
| 1528 + if lenp != NULL: |
| 1529 + with nogil: |
| 1530 + lenp[0] = zmq_msg_size(&self.zmq_msg) |
| 1531 + return 1 |
| 1532 + |
| 1533 + def __getreadbuffer__(self, Py_ssize_t idx, void **p): |
| 1534 + # old-style (buffer) interface |
| 1535 + cdef char *data_c = NULL |
| 1536 + cdef Py_ssize_t data_len_c |
| 1537 + if idx != 0: |
| 1538 + raise SystemError("accessing non-existent buffer segment") |
| 1539 + # read-only, because we don't want to allow |
| 1540 + # editing of the message in-place |
| 1541 + with nogil: |
| 1542 + data_c = <char *>zmq_msg_data(&self.zmq_msg) |
| 1543 + data_len_c = zmq_msg_size(&self.zmq_msg) |
| 1544 + if p != NULL: |
| 1545 + p[0] = <void*>data_c |
| 1546 + return data_len_c |
| 1547 + |
| 1548 + # end buffer interface |
| 1549 + |
| 1550 + def __copy__(self): |
| 1551 + """Create a shallow copy of the message. |
| 1552 + |
| 1553 + This does not copy the contents of the Frame, just the pointer. |
| 1554 + This will increment the 0MQ ref count of the message, but not |
| 1555 + the ref count of the Python object. That is only done once when |
| 1556 + the Python is first turned into a 0MQ message. |
| 1557 + """ |
| 1558 + return self.fast_copy() |
| 1559 + |
| 1560 + cdef Frame fast_copy(self): |
| 1561 + """Fast, cdef'd version of shallow copy of the Frame.""" |
| 1562 + cdef Frame new_msg |
| 1563 + new_msg = Frame() |
| 1564 + # This does not copy the contents, but just increases the ref-count |
| 1565 + # of the zmq_msg by one. |
| 1566 + with nogil: |
| 1567 + zmq_msg_copy(&new_msg.zmq_msg, &self.zmq_msg) |
| 1568 + # Copy the ref to data so the copy won't create a copy when str is |
| 1569 + # called. |
| 1570 + if self._data is not None: |
| 1571 + new_msg._data = self._data |
| 1572 + if self._buffer is not None: |
| 1573 + new_msg._buffer = self._buffer |
| 1574 + if self._bytes is not None: |
| 1575 + new_msg._bytes = self._bytes |
| 1576 + |
| 1577 + # Frame copies share the tracker and tracker_event |
| 1578 + new_msg.tracker_event = self.tracker_event |
| 1579 + new_msg.tracker = self.tracker |
| 1580 + |
| 1581 + return new_msg |
| 1582 + |
| 1583 + def __len__(self): |
| 1584 + """Return the length of the message in bytes.""" |
| 1585 + cdef size_t sz |
| 1586 + with nogil: |
| 1587 + sz = zmq_msg_size(&self.zmq_msg) |
| 1588 + return sz |
| 1589 + # return <int>zmq_msg_size(&self.zmq_msg) |
| 1590 + |
| 1591 + def __str__(self): |
| 1592 + """Return the str form of the message.""" |
| 1593 + if isinstance(self._data, bytes): |
| 1594 + b = self._data |
| 1595 + else: |
| 1596 + b = self.bytes |
| 1597 + if str is unicode: |
| 1598 + return b.decode() |
| 1599 + else: |
| 1600 + return b |
| 1601 + |
| 1602 + cdef inline object _getbuffer(self): |
| 1603 + """Create a Python buffer/view of the message data. |
| 1604 + |
| 1605 + This will be called only once, the first time the `buffer` property |
| 1606 + is accessed. Subsequent calls use a cached copy. |
| 1607 + """ |
| 1608 + if self._data is None: |
| 1609 + return viewfromobject_r(self) |
| 1610 + else: |
| 1611 + return viewfromobject_r(self._data) |
| 1612 + |
| 1613 + @property |
| 1614 + def buffer(self): |
| 1615 + """Get a read-only buffer view of the message contents.""" |
| 1616 + if self._buffer is None: |
| 1617 + self._buffer = self._getbuffer() |
| 1618 + return self._buffer |
| 1619 + |
| 1620 + @property |
| 1621 + def bytes(self): |
| 1622 + """Get the message content as a Python str/bytes object. |
| 1623 + |
| 1624 + The first time this property is accessed, a copy of the message |
| 1625 + contents is made. From then on that same copy of the message is |
| 1626 + returned. |
| 1627 + """ |
| 1628 + if self._bytes is None: |
| 1629 + self._bytes = copy_zmq_msg_bytes(&self.zmq_msg) |
| 1630 + return self._bytes |
| 1631 + |
| 1632 + def set(self, int option, int value): |
| 1633 + """Set a message property""" |
| 1634 + cdef int rc = zmq_msg_set(&self.zmq_msg, option, value) |
| 1635 + _check_rc(rc) |
| 1636 + |
| 1637 + def get(self, int option): |
| 1638 + """Get a message property""" |
| 1639 + cdef int rc = zmq_msg_get(&self.zmq_msg, option) |
| 1640 + _check_rc(rc) |
| 1641 + return rc |
| 1642 + |
| 1643 +# legacy Message name |
| 1644 +Message = Frame |
| 1645 + |
| 1646 +__all__ = ['Frame', 'Message'] |
| 1647 diff --git a/zmq/core/_zsocket.pxd b/zmq/core/_zsocket.pxd |
| 1648 new file mode 100644 |
| 1649 index 0000000..68f96c8 |
| 1650 --- /dev/null |
| 1651 +++ b/zmq/core/_zsocket.pxd |
| 1652 @@ -0,0 +1,48 @@ |
| 1653 +"""0MQ Socket class declaration.""" |
| 1654 + |
| 1655 +# |
| 1656 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 1657 +# |
| 1658 +# This file is part of pyzmq. |
| 1659 +# |
| 1660 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 1661 +# the terms of the Lesser GNU General Public License as published by |
| 1662 +# the Free Software Foundation; either version 3 of the License, or |
| 1663 +# (at your option) any later version. |
| 1664 +# |
| 1665 +# pyzmq is distributed in the hope that it will be useful, |
| 1666 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1667 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1668 +# Lesser GNU General Public License for more details. |
| 1669 +# |
| 1670 +# You should have received a copy of the Lesser GNU General Public License |
| 1671 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1672 +# |
| 1673 + |
| 1674 +#----------------------------------------------------------------------------- |
| 1675 +# Imports |
| 1676 +#----------------------------------------------------------------------------- |
| 1677 + |
| 1678 +from _zcontext cimport Context |
| 1679 + |
| 1680 +#----------------------------------------------------------------------------- |
| 1681 +# Code |
| 1682 +#----------------------------------------------------------------------------- |
| 1683 + |
| 1684 + |
| 1685 +cdef class Socket: |
| 1686 + """A 0MQ socket.""" |
| 1687 + |
| 1688 + cdef object __weakref__ # enable weakref |
| 1689 + cdef void *handle # The C handle for the underlying zmq object. |
| 1690 + cdef public int socket_type # The 0MQ socket type - REQ,REP, etc. |
| 1691 + # Hold on to a reference to the context to make sure it is not garbage |
| 1692 + # collected until the socket it done with it. |
| 1693 + cdef public Context context # The zmq Context object that owns this. |
| 1694 + cdef public bint _closed # bool property for a closed socket. |
| 1695 + cdef int _pid # the pid of the process which created me (for
fork safety) |
| 1696 + |
| 1697 + # cpdef methods for direct-cython access: |
| 1698 + cpdef object send(self, object data, int flags=*, copy=*, track=*) |
| 1699 + cpdef object recv(self, int flags=*, copy=*, track=*) |
| 1700 + |
| 1701 diff --git a/zmq/core/_zsocket.pyx b/zmq/core/_zsocket.pyx |
| 1702 new file mode 100644 |
| 1703 index 0000000..a5e507d |
| 1704 --- /dev/null |
| 1705 +++ b/zmq/core/_zsocket.pyx |
| 1706 @@ -0,0 +1,628 @@ |
| 1707 +"""0MQ Socket class.""" |
| 1708 + |
| 1709 +# |
| 1710 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 1711 +# |
| 1712 +# This file is part of pyzmq. |
| 1713 +# |
| 1714 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 1715 +# the terms of the Lesser GNU General Public License as published by |
| 1716 +# the Free Software Foundation; either version 3 of the License, or |
| 1717 +# (at your option) any later version. |
| 1718 +# |
| 1719 +# pyzmq is distributed in the hope that it will be useful, |
| 1720 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1721 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1722 +# Lesser GNU General Public License for more details. |
| 1723 +# |
| 1724 +# You should have received a copy of the Lesser GNU General Public License |
| 1725 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1726 +# |
| 1727 + |
| 1728 +#----------------------------------------------------------------------------- |
| 1729 +# Cython Imports |
| 1730 +#----------------------------------------------------------------------------- |
| 1731 + |
| 1732 +# get version-independent aliases: |
| 1733 +cdef extern from "pyversion_compat.h": |
| 1734 + pass |
| 1735 + |
| 1736 +from libc.errno cimport ENAMETOOLONG |
| 1737 +from libc.string cimport memcpy |
| 1738 + |
| 1739 +from cpython cimport PyBytes_FromStringAndSize |
| 1740 +from cpython cimport PyBytes_AsString, PyBytes_Size |
| 1741 +from cpython cimport Py_DECREF, Py_INCREF |
| 1742 + |
| 1743 +from buffers cimport asbuffer_r, viewfromobject_r |
| 1744 + |
| 1745 +from libzmq cimport * |
| 1746 +from _zmessage cimport Frame, copy_zmq_msg_bytes |
| 1747 + |
| 1748 +from _zcontext cimport Context |
| 1749 + |
| 1750 +cdef extern from "Python.h": |
| 1751 + ctypedef int Py_ssize_t |
| 1752 + |
| 1753 +cdef extern from "ipcmaxlen.h": |
| 1754 + int get_ipc_path_max_len() |
| 1755 + |
| 1756 +cdef extern from "getpid_compat.h": |
| 1757 + int getpid() |
| 1758 + |
| 1759 + |
| 1760 +#----------------------------------------------------------------------------- |
| 1761 +# Python Imports |
| 1762 +#----------------------------------------------------------------------------- |
| 1763 + |
| 1764 +import copy as copy_mod |
| 1765 +import time |
| 1766 +import sys |
| 1767 +import random |
| 1768 +import struct |
| 1769 +import codecs |
| 1770 + |
| 1771 +from zmq.utils import jsonapi |
| 1772 + |
| 1773 +try: |
| 1774 + import cPickle |
| 1775 + pickle = cPickle |
| 1776 +except: |
| 1777 + cPickle = None |
| 1778 + import pickle |
| 1779 + |
| 1780 +import zmq |
| 1781 +from zmq.core import _zconstants as constants |
| 1782 +from zmq.core._zconstants import * |
| 1783 +from zmq.core.checkrc cimport _check_rc |
| 1784 +from zmq.error import ZMQError, ZMQBindError |
| 1785 +from zmq.utils.strtypes import bytes,unicode,basestring |
| 1786 + |
| 1787 +#----------------------------------------------------------------------------- |
| 1788 +# Code |
| 1789 +#----------------------------------------------------------------------------- |
| 1790 + |
| 1791 +IPC_PATH_MAX_LEN = get_ipc_path_max_len() |
| 1792 + |
| 1793 +# inline some small socket submethods: |
| 1794 +# true methods frequently cannot be inlined, acc. Cython docs |
| 1795 + |
| 1796 +cdef inline _check_closed(Socket s, bint raise_notsup): |
| 1797 + cdef int rc |
| 1798 + cdef int errno |
| 1799 + cdef int stype |
| 1800 + cdef size_t sz=sizeof(int) |
| 1801 + if s._closed: |
| 1802 + if raise_notsup: |
| 1803 + raise ZMQError(ENOTSUP) |
| 1804 + else: |
| 1805 + return True |
| 1806 + else: |
| 1807 + rc = zmq_getsockopt(s.handle, ZMQ_TYPE, <void *>&stype, &sz) |
| 1808 + if rc < 0 and zmq_errno() == ENOTSOCK: |
| 1809 + s._closed = True |
| 1810 + if raise_notsup: |
| 1811 + raise ZMQError(ENOTSUP) |
| 1812 + else: |
| 1813 + return True |
| 1814 + else: |
| 1815 + _check_rc(rc) |
| 1816 + return False |
| 1817 + |
| 1818 +cdef inline Frame _recv_frame(void *handle, int flags=0, track=False): |
| 1819 + """Receive a message in a non-copying manner and return a Frame.""" |
| 1820 + cdef int rc |
| 1821 + cdef Frame msg |
| 1822 + msg = Frame(track=track) |
| 1823 + |
| 1824 + with nogil: |
| 1825 + rc = zmq_msg_recv(&msg.zmq_msg, handle, flags) |
| 1826 + |
| 1827 + _check_rc(rc) |
| 1828 + return msg |
| 1829 + |
| 1830 +cdef inline object _recv_copy(void *handle, int flags=0): |
| 1831 + """Receive a message and return a copy""" |
| 1832 + cdef zmq_msg_t zmq_msg |
| 1833 + with nogil: |
| 1834 + zmq_msg_init (&zmq_msg) |
| 1835 + rc = zmq_msg_recv(&zmq_msg, handle, flags) |
| 1836 + _check_rc(rc) |
| 1837 + msg_bytes = copy_zmq_msg_bytes(&zmq_msg) |
| 1838 + with nogil: |
| 1839 + zmq_msg_close(&zmq_msg) |
| 1840 + return msg_bytes |
| 1841 + |
| 1842 +cdef inline object _send_frame(void *handle, Frame msg, int flags=0): |
| 1843 + """Send a Frame on this socket in a non-copy manner.""" |
| 1844 + cdef int rc |
| 1845 + cdef Frame msg_copy |
| 1846 + |
| 1847 + # Always copy so the original message isn't garbage collected. |
| 1848 + # This doesn't do a real copy, just a reference. |
| 1849 + msg_copy = msg.fast_copy() |
| 1850 + |
| 1851 + with nogil: |
| 1852 + rc = zmq_msg_send(&msg_copy.zmq_msg, handle, flags) |
| 1853 + |
| 1854 + _check_rc(rc) |
| 1855 + return msg.tracker |
| 1856 + |
| 1857 + |
| 1858 +cdef inline object _send_copy(void *handle, object msg, int flags=0): |
| 1859 + """Send a message on this socket by copying its content.""" |
| 1860 + cdef int rc, rc2 |
| 1861 + cdef zmq_msg_t data |
| 1862 + cdef char *msg_c |
| 1863 + cdef Py_ssize_t msg_c_len=0 |
| 1864 + |
| 1865 + # copy to c array: |
| 1866 + asbuffer_r(msg, <void **>&msg_c, &msg_c_len) |
| 1867 + |
| 1868 + # Copy the msg before sending. This avoids any complications with |
| 1869 + # the GIL, etc. |
| 1870 + # If zmq_msg_init_* fails we must not call zmq_msg_close (Bus Error) |
| 1871 + with nogil: |
| 1872 + rc = zmq_msg_init_size(&data, msg_c_len) |
| 1873 + |
| 1874 + _check_rc(rc) |
| 1875 + |
| 1876 + with nogil: |
| 1877 + memcpy(zmq_msg_data(&data), msg_c, zmq_msg_size(&data)) |
| 1878 + rc = zmq_msg_send(&data, handle, flags) |
| 1879 + rc2 = zmq_msg_close(&data) |
| 1880 + _check_rc(rc) |
| 1881 + _check_rc(rc2) |
| 1882 + |
| 1883 + |
| 1884 +cdef class Socket: |
| 1885 + """Socket(context, socket_type) |
| 1886 + |
| 1887 + A 0MQ socket. |
| 1888 + |
| 1889 + These objects will generally be constructed via the socket() method of a Co
ntext object. |
| 1890 + |
| 1891 + Note: 0MQ Sockets are *not* threadsafe. **DO NOT** share them across thread
s. |
| 1892 + |
| 1893 + Parameters |
| 1894 + ---------- |
| 1895 + context : Context |
| 1896 + The 0MQ Context this Socket belongs to. |
| 1897 + socket_type : int |
| 1898 + The socket type, which can be any of the 0MQ socket types: |
| 1899 + REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB. |
| 1900 + |
| 1901 + See Also |
| 1902 + -------- |
| 1903 + .Context.socket : method for creating a socket bound to a Context. |
| 1904 + """ |
| 1905 + |
| 1906 + def __cinit__(self, Context context, int socket_type, *args, **kwrags): |
| 1907 + cdef Py_ssize_t c_handle |
| 1908 + c_handle = context._handle |
| 1909 + |
| 1910 + self.handle = NULL |
| 1911 + self.context = context |
| 1912 + self.socket_type = socket_type |
| 1913 + with nogil: |
| 1914 + self.handle = zmq_socket(<void *>c_handle, socket_type) |
| 1915 + if self.handle == NULL: |
| 1916 + raise ZMQError() |
| 1917 + self._closed = False |
| 1918 + self._pid = getpid() |
| 1919 + context._add_socket(self.handle) |
| 1920 + |
| 1921 + def __dealloc__(self): |
| 1922 + """close *and* remove from context's list |
| 1923 + |
| 1924 + But be careful that context might not exist if called during gc |
| 1925 + """ |
| 1926 + if self.handle != NULL and getpid() == self._pid: |
| 1927 + rc = zmq_close(self.handle) |
| 1928 + if rc != 0 and zmq_errno() != ENOTSOCK: |
| 1929 + # ignore ENOTSOCK (closed by Context) |
| 1930 + _check_rc(rc) |
| 1931 + # during gc, self.context might be NULL |
| 1932 + if self.context: |
| 1933 + self.context._remove_socket(self.handle) |
| 1934 + |
| 1935 + def __init__(self, context, socket_type): |
| 1936 + pass |
| 1937 + |
| 1938 + @property |
| 1939 + def closed(self): |
| 1940 + return _check_closed(self, False) |
| 1941 + |
| 1942 + def close(self, linger=None): |
| 1943 + """s.close(linger=None) |
| 1944 + |
| 1945 + Close the socket. |
| 1946 + |
| 1947 + If linger is specified, LINGER sockopt will be set prior to closing. |
| 1948 + |
| 1949 + This can be called to close the socket by hand. If this is not |
| 1950 + called, the socket will automatically be closed when it is |
| 1951 + garbage collected. |
| 1952 + """ |
| 1953 + cdef int rc=0 |
| 1954 + cdef int linger_c |
| 1955 + cdef bint setlinger=False |
| 1956 + |
| 1957 + if linger is not None: |
| 1958 + linger_c = linger |
| 1959 + setlinger=True |
| 1960 + |
| 1961 + if self.handle != NULL and not self._closed and getpid() == self._pid: |
| 1962 + if setlinger: |
| 1963 + zmq_setsockopt(self.handle, ZMQ_LINGER, &linger_c, sizeof(int)) |
| 1964 + rc = zmq_close(self.handle) |
| 1965 + if rc != 0 and zmq_errno() != ENOTSOCK: |
| 1966 + # ignore ENOTSOCK (closed by Context) |
| 1967 + _check_rc(rc) |
| 1968 + self._closed = True |
| 1969 + # during gc, self.context might be NULL |
| 1970 + if self.context: |
| 1971 + self.context._remove_socket(self.handle) |
| 1972 + self.handle = NULL |
| 1973 + |
| 1974 + def set(self, int option, optval): |
| 1975 + """s.set(option, optval) |
| 1976 + |
| 1977 + Set socket options. |
| 1978 + |
| 1979 + See the 0MQ API documentation for details on specific options. |
| 1980 + |
| 1981 + Parameters |
| 1982 + ---------- |
| 1983 + option : int |
| 1984 + The option to set. Available values will depend on your |
| 1985 + version of libzmq. Examples include:: |
| 1986 + |
| 1987 + zmq.SUBSCRIBE, UNSUBSCRIBE, IDENTITY, HWM, LINGER, FD |
| 1988 + |
| 1989 + optval : int or bytes |
| 1990 + The value of the option to set. |
| 1991 + """ |
| 1992 + cdef int64_t optval_int64_c |
| 1993 + cdef int optval_int_c |
| 1994 + cdef int rc |
| 1995 + cdef char* optval_c |
| 1996 + cdef Py_ssize_t sz |
| 1997 + |
| 1998 + _check_closed(self, True) |
| 1999 + if isinstance(optval, unicode): |
| 2000 + raise TypeError("unicode not allowed, use setsockopt_string") |
| 2001 + |
| 2002 + if option in zmq.constants.bytes_sockopts: |
| 2003 + if not isinstance(optval, bytes): |
| 2004 + raise TypeError('expected bytes, got: %r' % optval) |
| 2005 + optval_c = PyBytes_AsString(optval) |
| 2006 + sz = PyBytes_Size(optval) |
| 2007 + with nogil: |
| 2008 + rc = zmq_setsockopt( |
| 2009 + self.handle, option, |
| 2010 + optval_c, sz |
| 2011 + ) |
| 2012 + elif option in zmq.constants.int64_sockopts: |
| 2013 + if not isinstance(optval, int): |
| 2014 + raise TypeError('expected int, got: %r' % optval) |
| 2015 + optval_int64_c = optval |
| 2016 + with nogil: |
| 2017 + rc = zmq_setsockopt( |
| 2018 + self.handle, option, |
| 2019 + &optval_int64_c, sizeof(int64_t) |
| 2020 + ) |
| 2021 + else: |
| 2022 + # default is to assume int, which is what most new sockopts will be |
| 2023 + # this lets pyzmq work with newer libzmq which may add constants |
| 2024 + # pyzmq has not yet added, rather than artificially raising. Invali
d |
| 2025 + # sockopts will still raise just the same, but it will be libzmq do
ing |
| 2026 + # the raising. |
| 2027 + if not isinstance(optval, int): |
| 2028 + raise TypeError('expected int, got: %r' % optval) |
| 2029 + optval_int_c = optval |
| 2030 + with nogil: |
| 2031 + rc = zmq_setsockopt( |
| 2032 + self.handle, option, |
| 2033 + &optval_int_c, sizeof(int) |
| 2034 + ) |
| 2035 + |
| 2036 + _check_rc(rc) |
| 2037 + |
| 2038 + def get(self, int option): |
| 2039 + """s.get(option) |
| 2040 + |
| 2041 + Get the value of a socket option. |
| 2042 + |
| 2043 + See the 0MQ API documentation for details on specific options. |
| 2044 + |
| 2045 + Parameters |
| 2046 + ---------- |
| 2047 + option : int |
| 2048 + The option to get. Available values will depend on your |
| 2049 + version of libzmq. Examples include:: |
| 2050 + |
| 2051 + zmq.IDENTITY, HWM, LINGER, FD, EVENTS |
| 2052 + |
| 2053 + Returns |
| 2054 + ------- |
| 2055 + optval : int or bytes |
| 2056 + The value of the option as a bytestring or int. |
| 2057 + """ |
| 2058 + cdef int64_t optval_int64_c |
| 2059 + cdef int optval_int_c |
| 2060 + cdef fd_t optval_fd_c |
| 2061 + cdef char identity_str_c [255] |
| 2062 + cdef size_t sz |
| 2063 + cdef int rc |
| 2064 + |
| 2065 + _check_closed(self, True) |
| 2066 + |
| 2067 + if option in zmq.constants.bytes_sockopts: |
| 2068 + sz = 255 |
| 2069 + with nogil: |
| 2070 + rc = zmq_getsockopt(self.handle, option, <void *>identity_str_c
, &sz) |
| 2071 + _check_rc(rc) |
| 2072 + result = PyBytes_FromStringAndSize(<char *>identity_str_c, sz) |
| 2073 + elif option in zmq.constants.int64_sockopts: |
| 2074 + sz = sizeof(int64_t) |
| 2075 + with nogil: |
| 2076 + rc = zmq_getsockopt(self.handle, option, <void *>&optval_int64_
c, &sz) |
| 2077 + _check_rc(rc) |
| 2078 + result = optval_int64_c |
| 2079 + elif option == ZMQ_FD: |
| 2080 + sz = sizeof(fd_t) |
| 2081 + with nogil: |
| 2082 + rc = zmq_getsockopt(self.handle, option, <void *>&optval_fd_c,
&sz) |
| 2083 + _check_rc(rc) |
| 2084 + result = optval_fd_c |
| 2085 + else: |
| 2086 + # default is to assume int, which is what most new sockopts will be |
| 2087 + # this lets pyzmq work with newer libzmq which may add constants |
| 2088 + # pyzmq has not yet added, rather than artificially raising. Invali
d |
| 2089 + # sockopts will still raise just the same, but it will be libzmq do
ing |
| 2090 + # the raising. |
| 2091 + sz = sizeof(int) |
| 2092 + with nogil: |
| 2093 + rc = zmq_getsockopt(self.handle, option, <void *>&optval_int_c,
&sz) |
| 2094 + _check_rc(rc) |
| 2095 + result = optval_int_c |
| 2096 + |
| 2097 + return result |
| 2098 + |
| 2099 + def bind(self, addr): |
| 2100 + """s.bind(addr) |
| 2101 + |
| 2102 + Bind the socket to an address. |
| 2103 + |
| 2104 + This causes the socket to listen on a network port. Sockets on the |
| 2105 + other side of this connection will use ``Socket.connect(addr)`` to |
| 2106 + connect to this socket. |
| 2107 + |
| 2108 + Parameters |
| 2109 + ---------- |
| 2110 + addr : str |
| 2111 + The address string. This has the form 'protocol://interface:port', |
| 2112 + for example 'tcp://127.0.0.1:5555'. Protocols supported include |
| 2113 + tcp, udp, pgm, epgm, inproc and ipc. If the address is unicode, it
is |
| 2114 + encoded to utf-8 first. |
| 2115 + """ |
| 2116 + cdef int rc |
| 2117 + cdef char* c_addr |
| 2118 + |
| 2119 + _check_closed(self, True) |
| 2120 + if isinstance(addr, unicode): |
| 2121 + addr = addr.encode('utf-8') |
| 2122 + if not isinstance(addr, bytes): |
| 2123 + raise TypeError('expected str, got: %r' % addr) |
| 2124 + c_addr = addr |
| 2125 + rc = zmq_bind(self.handle, c_addr) |
| 2126 + if rc != 0: |
| 2127 + if IPC_PATH_MAX_LEN and zmq_errno() == ENAMETOOLONG: |
| 2128 + # py3compat: addr is bytes, but msg wants str |
| 2129 + if str is unicode: |
| 2130 + addr = addr.decode('utf-8', 'replace') |
| 2131 + path = addr.split('://', 1)[-1] |
| 2132 + msg = ('ipc path "{0}" is longer than {1} ' |
| 2133 + 'characters (sizeof(sockaddr_un.sun_path)). ' |
| 2134 + 'zmq.IPC_PATH_MAX_LEN constant can be used ' |
| 2135 + 'to check addr length (if it is defined).' |
| 2136 + .format(path, IPC_PATH_MAX_LEN)) |
| 2137 + raise ZMQError(msg=msg) |
| 2138 + _check_rc(rc) |
| 2139 + |
| 2140 + def connect(self, addr): |
| 2141 + """s.connect(addr) |
| 2142 + |
| 2143 + Connect to a remote 0MQ socket. |
| 2144 + |
| 2145 + Parameters |
| 2146 + ---------- |
| 2147 + addr : str |
| 2148 + The address string. This has the form 'protocol://interface:port', |
| 2149 + for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| 2150 + tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| 2151 + encoded to utf-8 first. |
| 2152 + """ |
| 2153 + cdef int rc |
| 2154 + cdef char* c_addr |
| 2155 + |
| 2156 + _check_closed(self, True) |
| 2157 + if isinstance(addr, unicode): |
| 2158 + addr = addr.encode('utf-8') |
| 2159 + if not isinstance(addr, bytes): |
| 2160 + raise TypeError('expected str, got: %r' % addr) |
| 2161 + c_addr = addr |
| 2162 + |
| 2163 + rc = zmq_connect(self.handle, c_addr) |
| 2164 + if rc != 0: |
| 2165 + raise ZMQError() |
| 2166 + |
| 2167 + def unbind(self, addr): |
| 2168 + """s.unbind(addr) |
| 2169 + |
| 2170 + Unbind from an address (undoes a call to bind). |
| 2171 + |
| 2172 + This feature requires libzmq-3 |
| 2173 + |
| 2174 + Parameters |
| 2175 + ---------- |
| 2176 + addr : str |
| 2177 + The address string. This has the form 'protocol://interface:port', |
| 2178 + for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| 2179 + tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| 2180 + encoded to utf-8 first. |
| 2181 + """ |
| 2182 + cdef int rc |
| 2183 + cdef char* c_addr |
| 2184 + |
| 2185 + if ZMQ_VERSION_MAJOR < 3: |
| 2186 + raise NotImplementedError("unbind requires libzmq >= 3.0, have %s"
% zmq.zmq_version()) |
| 2187 + |
| 2188 + |
| 2189 + _check_closed(self, True) |
| 2190 + if isinstance(addr, unicode): |
| 2191 + addr = addr.encode('utf-8') |
| 2192 + if not isinstance(addr, bytes): |
| 2193 + raise TypeError('expected str, got: %r' % addr) |
| 2194 + c_addr = addr |
| 2195 + |
| 2196 + rc = zmq_unbind(self.handle, c_addr) |
| 2197 + if rc != 0: |
| 2198 + raise ZMQError() |
| 2199 + |
| 2200 + def disconnect(self, addr): |
| 2201 + """s.disconnect(addr) |
| 2202 + |
| 2203 + Disconnect from a remote 0MQ socket (undoes a call to connect). |
| 2204 + |
| 2205 + This feature requires libzmq-3 |
| 2206 + |
| 2207 + Parameters |
| 2208 + ---------- |
| 2209 + addr : str |
| 2210 + The address string. This has the form 'protocol://interface:port', |
| 2211 + for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| 2212 + tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| 2213 + encoded to utf-8 first. |
| 2214 + """ |
| 2215 + cdef int rc |
| 2216 + cdef char* c_addr |
| 2217 + |
| 2218 + if ZMQ_VERSION_MAJOR < 3: |
| 2219 + raise NotImplementedError("disconnect requires libzmq >= 3.0, have
%s" % zmq.zmq_version()) |
| 2220 + |
| 2221 + _check_closed(self, True) |
| 2222 + if isinstance(addr, unicode): |
| 2223 + addr = addr.encode('utf-8') |
| 2224 + if not isinstance(addr, bytes): |
| 2225 + raise TypeError('expected str, got: %r' % addr) |
| 2226 + c_addr = addr |
| 2227 + |
| 2228 + rc = zmq_disconnect(self.handle, c_addr) |
| 2229 + if rc != 0: |
| 2230 + raise ZMQError() |
| 2231 + |
| 2232 + #------------------------------------------------------------------------- |
| 2233 + # Sending and receiving messages |
| 2234 + #------------------------------------------------------------------------- |
| 2235 + |
| 2236 + cpdef object send(self, object data, int flags=0, copy=True, track=False): |
| 2237 + """s.send(data, flags=0, copy=True, track=False) |
| 2238 + |
| 2239 + Send a message on this socket. |
| 2240 + |
| 2241 + This queues the message to be sent by the IO thread at a later time. |
| 2242 + |
| 2243 + Parameters |
| 2244 + ---------- |
| 2245 + data : object, str, Frame |
| 2246 + The content of the message. |
| 2247 + flags : int |
| 2248 + Any supported flag: NOBLOCK, SNDMORE. |
| 2249 + copy : bool |
| 2250 + Should the message be sent in a copying or non-copying manner. |
| 2251 + track : bool |
| 2252 + Should the message be tracked for notification that ZMQ has |
| 2253 + finished with it? (ignored if copy=True) |
| 2254 + |
| 2255 + Returns |
| 2256 + ------- |
| 2257 + None : if `copy` or not track |
| 2258 + None if message was sent, raises an exception otherwise. |
| 2259 + MessageTracker : if track and not copy |
| 2260 + a MessageTracker object, whose `pending` property will |
| 2261 + be True until the send is completed. |
| 2262 + |
| 2263 + Raises |
| 2264 + ------ |
| 2265 + TypeError |
| 2266 + If a unicode object is passed |
| 2267 + ValueError |
| 2268 + If `track=True`, but an untracked Frame is passed. |
| 2269 + ZMQError |
| 2270 + If the send does not succeed for any reason. |
| 2271 + |
| 2272 + """ |
| 2273 + _check_closed(self, True) |
| 2274 + |
| 2275 + if isinstance(data, unicode): |
| 2276 + raise TypeError("unicode not allowed, use send_unicode") |
| 2277 + |
| 2278 + if copy: |
| 2279 + # msg.bytes never returns the input data object |
| 2280 + # it is always a copy, but always the same copy |
| 2281 + if isinstance(data, Frame): |
| 2282 + data = data.buffer |
| 2283 + return _send_copy(self.handle, data, flags) |
| 2284 + else: |
| 2285 + if isinstance(data, Frame): |
| 2286 + if track and not data.tracker: |
| 2287 + raise ValueError('Not a tracked message') |
| 2288 + msg = data |
| 2289 + else: |
| 2290 + msg = Frame(data, track=track) |
| 2291 + return _send_frame(self.handle, msg, flags) |
| 2292 + |
| 2293 + cpdef object recv(self, int flags=0, copy=True, track=False): |
| 2294 + """s.recv(flags=0, copy=True, track=False) |
| 2295 + |
| 2296 + Receive a message. |
| 2297 + |
| 2298 + Parameters |
| 2299 + ---------- |
| 2300 + flags : int |
| 2301 + Any supported flag: NOBLOCK. If NOBLOCK is set, this method |
| 2302 + will raise a ZMQError with EAGAIN if a message is not ready. |
| 2303 + If NOBLOCK is not set, then this method will block until a |
| 2304 + message arrives. |
| 2305 + copy : bool |
| 2306 + Should the message be received in a copying or non-copying manner? |
| 2307 + If False a Frame object is returned, if True a string copy of |
| 2308 + message is returned. |
| 2309 + track : bool |
| 2310 + Should the message be tracked for notification that ZMQ has |
| 2311 + finished with it? (ignored if copy=True) |
| 2312 + |
| 2313 + Returns |
| 2314 + ------- |
| 2315 + msg : bytes, Frame |
| 2316 + The received message frame. If `copy` is False, then it will be a
Frame, |
| 2317 + otherwise it will be bytes. |
| 2318 + |
| 2319 + Raises |
| 2320 + ------ |
| 2321 + ZMQError |
| 2322 + for any of the reasons zmq_msg_recv might fail. |
| 2323 + """ |
| 2324 + _check_closed(self, True) |
| 2325 + |
| 2326 + if copy: |
| 2327 + return _recv_copy(self.handle, flags) |
| 2328 + else: |
| 2329 + frame = _recv_frame(self.handle, flags, track) |
| 2330 + frame.more = self.getsockopt(zmq.RCVMORE) |
| 2331 + return frame |
| 2332 + |
| 2333 + |
| 2334 +__all__ = ['Socket', 'IPC_PATH_MAX_LEN'] |
| 2335 diff --git a/zmq/core/_zstopwatch.pxd b/zmq/core/_zstopwatch.pxd |
| 2336 new file mode 100644 |
| 2337 index 0000000..5d56166 |
| 2338 --- /dev/null |
| 2339 +++ b/zmq/core/_zstopwatch.pxd |
| 2340 @@ -0,0 +1,31 @@ |
| 2341 +"""0MQ Stopwatch class declaration.""" |
| 2342 + |
| 2343 +# |
| 2344 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 2345 +# |
| 2346 +# This file is part of pyzmq. |
| 2347 +# |
| 2348 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 2349 +# the terms of the Lesser GNU General Public License as published by |
| 2350 +# the Free Software Foundation; either version 3 of the License, or |
| 2351 +# (at your option) any later version. |
| 2352 +# |
| 2353 +# pyzmq is distributed in the hope that it will be useful, |
| 2354 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2355 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2356 +# Lesser GNU General Public License for more details. |
| 2357 +# |
| 2358 +# You should have received a copy of the Lesser GNU General Public License |
| 2359 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 2360 +# |
| 2361 + |
| 2362 +#----------------------------------------------------------------------------- |
| 2363 +# Code |
| 2364 +#----------------------------------------------------------------------------- |
| 2365 + |
| 2366 + |
| 2367 +cdef class Stopwatch: |
| 2368 + """A simple stopwatch based on zmq_stopwatch_start/stop.""" |
| 2369 + |
| 2370 + cdef void *watch # The C handle for the underlying zmq object |
| 2371 + |
| 2372 diff --git a/zmq/core/_zstopwatch.pyx b/zmq/core/_zstopwatch.pyx |
| 2373 new file mode 100644 |
| 2374 index 0000000..6d2fd61 |
| 2375 --- /dev/null |
| 2376 +++ b/zmq/core/_zstopwatch.pyx |
| 2377 @@ -0,0 +1,90 @@ |
| 2378 +"""0MQ Stopwatch class.""" |
| 2379 + |
| 2380 +# |
| 2381 +# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 2382 +# |
| 2383 +# This file is part of pyzmq. |
| 2384 +# |
| 2385 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 2386 +# the terms of the Lesser GNU General Public License as published by |
| 2387 +# the Free Software Foundation; either version 3 of the License, or |
| 2388 +# (at your option) any later version. |
| 2389 +# |
| 2390 +# pyzmq is distributed in the hope that it will be useful, |
| 2391 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2392 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2393 +# Lesser GNU General Public License for more details. |
| 2394 +# |
| 2395 +# You should have received a copy of the Lesser GNU General Public License |
| 2396 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 2397 +# |
| 2398 + |
| 2399 +#----------------------------------------------------------------------------- |
| 2400 +# Imports |
| 2401 +#----------------------------------------------------------------------------- |
| 2402 + |
| 2403 +from libzmq cimport zmq_stopwatch_start, zmq_stopwatch_stop, zmq_sleep |
| 2404 + |
| 2405 +from zmq.error import ZMQError |
| 2406 + |
| 2407 +#----------------------------------------------------------------------------- |
| 2408 +# Code |
| 2409 +#----------------------------------------------------------------------------- |
| 2410 + |
| 2411 +cdef class Stopwatch: |
| 2412 + """Stopwatch() |
| 2413 + |
| 2414 + A simple stopwatch based on zmq_stopwatch_start/stop. |
| 2415 + |
| 2416 + This class should be used for benchmarking and timing 0MQ code. |
| 2417 + """ |
| 2418 + |
| 2419 + def __cinit__(self): |
| 2420 + self.watch = NULL |
| 2421 + |
| 2422 + def __dealloc__(self): |
| 2423 + try: |
| 2424 + self.stop() |
| 2425 + except ZMQError: |
| 2426 + pass |
| 2427 + |
| 2428 + def start(self): |
| 2429 + """s.start() |
| 2430 + |
| 2431 + Start the stopwatch. |
| 2432 + """ |
| 2433 + if self.watch == NULL: |
| 2434 + with nogil: |
| 2435 + self.watch = zmq_stopwatch_start() |
| 2436 + else: |
| 2437 + raise ZMQError('Stopwatch is already runing.') |
| 2438 + |
| 2439 + def stop(self): |
| 2440 + """s.stop() |
| 2441 + |
| 2442 + Stop the stopwatch. |
| 2443 + |
| 2444 + Returns |
| 2445 + ------- |
| 2446 + t : unsigned long int |
| 2447 + the number of microseconds since ``start()`` was called. |
| 2448 + """ |
| 2449 + cdef unsigned long time |
| 2450 + if self.watch == NULL: |
| 2451 + raise ZMQError('Must start the Stopwatch before calling stop.') |
| 2452 + else: |
| 2453 + with nogil: |
| 2454 + time = zmq_stopwatch_stop(self.watch) |
| 2455 + self.watch = NULL |
| 2456 + return time |
| 2457 + |
| 2458 + def sleep(self, int seconds): |
| 2459 + """s.sleep(seconds) |
| 2460 + |
| 2461 + Sleep for an integer number of seconds. |
| 2462 + """ |
| 2463 + with nogil: |
| 2464 + zmq_sleep(seconds) |
| 2465 + |
| 2466 + |
| 2467 +__all__ = ['Stopwatch'] |
| 2468 diff --git a/zmq/core/constants.pyx b/zmq/core/constants.pyx |
| 2469 deleted file mode 100644 |
| 2470 index fa2695d..0000000 |
| 2471 --- a/zmq/core/constants.pyx |
| 2472 +++ /dev/null |
| 2473 @@ -1,190 +0,0 @@ |
| 2474 -"""0MQ Constants.""" |
| 2475 - |
| 2476 -# |
| 2477 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 2478 -# |
| 2479 -# This file is part of pyzmq. |
| 2480 -# |
| 2481 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 2482 -# the terms of the Lesser GNU General Public License as published by |
| 2483 -# the Free Software Foundation; either version 3 of the License, or |
| 2484 -# (at your option) any later version. |
| 2485 -# |
| 2486 -# pyzmq is distributed in the hope that it will be useful, |
| 2487 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2488 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2489 -# Lesser GNU General Public License for more details. |
| 2490 -# |
| 2491 -# You should have received a copy of the Lesser GNU General Public License |
| 2492 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 2493 -# |
| 2494 - |
| 2495 -#----------------------------------------------------------------------------- |
| 2496 -# Imports |
| 2497 -#----------------------------------------------------------------------------- |
| 2498 - |
| 2499 -from libzmq cimport * |
| 2500 - |
| 2501 -#----------------------------------------------------------------------------- |
| 2502 -# Python module level constants |
| 2503 -#----------------------------------------------------------------------------- |
| 2504 - |
| 2505 -_optionals = [] |
| 2506 - |
| 2507 -if ZMQ_VERSION < 30000: |
| 2508 - # backport DONTWAIT as alias to NOBLOCK |
| 2509 - NOBLOCK = ZMQ_NOBLOCK |
| 2510 - DONTWAIT = ZMQ_NOBLOCK |
| 2511 -else: |
| 2512 - # keep NOBLOCK as alias for new DONTWAIT |
| 2513 - NOBLOCK = ZMQ_DONTWAIT |
| 2514 - DONTWAIT = ZMQ_DONTWAIT |
| 2515 - |
| 2516 -VERSION = ZMQ_VERSION |
| 2517 - |
| 2518 -# socket types |
| 2519 -PAIR = ZMQ_PAIR |
| 2520 -PUB = ZMQ_PUB |
| 2521 -SUB = ZMQ_SUB |
| 2522 -REQ = ZMQ_REQ |
| 2523 -REP = ZMQ_REP |
| 2524 -DEALER = ZMQ_DEALER |
| 2525 -ROUTER = ZMQ_ROUTER |
| 2526 -PULL = ZMQ_PULL |
| 2527 -PUSH = ZMQ_PUSH |
| 2528 -XPUB = ZMQ_XPUB |
| 2529 -XSUB = ZMQ_XSUB |
| 2530 - |
| 2531 -# keep deprecated aliases |
| 2532 -XREQ = DEALER |
| 2533 -XREP = ROUTER |
| 2534 -UPSTREAM = PULL |
| 2535 -DOWNSTREAM = PUSH |
| 2536 - |
| 2537 - |
| 2538 -# socket options |
| 2539 -AFFINITY = ZMQ_AFFINITY |
| 2540 -IDENTITY = ZMQ_IDENTITY |
| 2541 -SUBSCRIBE = ZMQ_SUBSCRIBE |
| 2542 -UNSUBSCRIBE = ZMQ_UNSUBSCRIBE |
| 2543 -RATE = ZMQ_RATE |
| 2544 -RECOVERY_IVL = ZMQ_RECOVERY_IVL |
| 2545 -RECONNECT_IVL_MAX = ZMQ_RECONNECT_IVL_MAX |
| 2546 -SNDBUF = ZMQ_SNDBUF |
| 2547 -RCVBUF = ZMQ_RCVBUF |
| 2548 -RCVMORE = ZMQ_RCVMORE |
| 2549 -SNDMORE = ZMQ_SNDMORE |
| 2550 -POLLIN = ZMQ_POLLIN |
| 2551 -POLLOUT = ZMQ_POLLOUT |
| 2552 -POLLERR = ZMQ_POLLERR |
| 2553 - |
| 2554 -STREAMER = ZMQ_STREAMER |
| 2555 -FORWARDER = ZMQ_FORWARDER |
| 2556 -QUEUE = ZMQ_QUEUE |
| 2557 - |
| 2558 -# sockopts new in 2.2.0 |
| 2559 -SNDTIMEO = ZMQ_SNDTIMEO |
| 2560 -RCVTIMEO = ZMQ_RCVTIMEO |
| 2561 - |
| 2562 -# sockopts removed in 3.0.0 |
| 2563 -HWM = ZMQ_HWM |
| 2564 -SWAP = ZMQ_SWAP |
| 2565 -MCAST_LOOP = ZMQ_MCAST_LOOP |
| 2566 -RECOVERY_IVL_MSEC = ZMQ_RECOVERY_IVL_MSEC |
| 2567 - |
| 2568 -# new in 3.x |
| 2569 -IO_THREADS = ZMQ_IO_THREADS |
| 2570 -MAX_SOCKETS = ZMQ_MAX_SOCKETS |
| 2571 - |
| 2572 -MORE = ZMQ_MORE |
| 2573 - |
| 2574 -MAXMSGSIZE = ZMQ_MAXMSGSIZE |
| 2575 -SNDHWM = ZMQ_SNDHWM |
| 2576 -RCVHWM = ZMQ_RCVHWM |
| 2577 -MULTICAST_HOPS = ZMQ_MULTICAST_HOPS |
| 2578 -IPV4ONLY = ZMQ_IPV4ONLY |
| 2579 -LAST_ENDPOINT = ZMQ_LAST_ENDPOINT |
| 2580 - |
| 2581 -ROUTER_MANDATORY = ZMQ_ROUTER_MANDATORY |
| 2582 -# aliases |
| 2583 -ROUTER_BEHAVIOR = ROUTER_MANDATORY |
| 2584 -FAIL_UNROUTABLE = ROUTER_MANDATORY |
| 2585 - |
| 2586 -TCP_KEEPALIVE = ZMQ_TCP_KEEPALIVE |
| 2587 -TCP_KEEPALIVE_CNT = ZMQ_TCP_KEEPALIVE_CNT |
| 2588 -TCP_KEEPALIVE_IDLE = ZMQ_TCP_KEEPALIVE_IDLE |
| 2589 -TCP_KEEPALIVE_INTVL = ZMQ_TCP_KEEPALIVE_INTVL |
| 2590 -TCP_ACCEPT_FILTER = ZMQ_TCP_ACCEPT_FILTER |
| 2591 -DELAY_ATTACH_ON_CONNECT = ZMQ_DELAY_ATTACH_ON_CONNECT |
| 2592 -XPUB_VERBOSE = ZMQ_XPUB_VERBOSE |
| 2593 -ROUTER_RAW = ZMQ_ROUTER_RAW |
| 2594 - |
| 2595 -EVENT_CONNECTED = ZMQ_EVENT_CONNECTED |
| 2596 -EVENT_CONNECT_DELAYED = ZMQ_EVENT_CONNECT_DELAYED |
| 2597 -EVENT_CONNECT_RETRIED = ZMQ_EVENT_CONNECT_RETRIED |
| 2598 -EVENT_LISTENING = ZMQ_EVENT_LISTENING |
| 2599 -EVENT_BIND_FAILED = ZMQ_EVENT_BIND_FAILED |
| 2600 -EVENT_ACCEPTED = ZMQ_EVENT_ACCEPTED |
| 2601 -EVENT_ACCEPT_FAILED = ZMQ_EVENT_ACCEPT_FAILED |
| 2602 -EVENT_CLOSED = ZMQ_EVENT_CLOSED |
| 2603 -EVENT_CLOSE_FAILED = ZMQ_EVENT_CLOSE_FAILED |
| 2604 -EVENT_DISCONNECTED = ZMQ_EVENT_DISCONNECTED |
| 2605 - |
| 2606 -FD = ZMQ_FD |
| 2607 -EVENTS = ZMQ_EVENTS |
| 2608 -TYPE = ZMQ_TYPE |
| 2609 -LINGER = ZMQ_LINGER |
| 2610 -RECONNECT_IVL = ZMQ_RECONNECT_IVL |
| 2611 -BACKLOG = ZMQ_BACKLOG |
| 2612 - |
| 2613 -# As new constants are added in future versions, add a new block here |
| 2614 -# like the two above, checking agains the relevant value for ZMQ_VERSION. |
| 2615 -# The constants will need to be added to libzmq.pxd and utils/zmq_compat.h |
| 2616 -# as well. |
| 2617 - |
| 2618 -#----------------------------------------------------------------------------- |
| 2619 -# Error handling |
| 2620 -#----------------------------------------------------------------------------- |
| 2621 - |
| 2622 -# Often used standard errnos |
| 2623 -from errno import ( |
| 2624 - EAGAIN, |
| 2625 - EINVAL, |
| 2626 - EFAULT, |
| 2627 - ENOMEM, |
| 2628 - ENODEV |
| 2629 -) |
| 2630 - |
| 2631 -# For Windows compatability |
| 2632 -ENOTSUP = ZMQ_ENOTSUP |
| 2633 -EPROTONOSUPPORT = ZMQ_EPROTONOSUPPORT |
| 2634 -ENOBUFS = ZMQ_ENOBUFS |
| 2635 -ENETDOWN = ZMQ_ENETDOWN |
| 2636 -EADDRINUSE = ZMQ_EADDRINUSE |
| 2637 -EADDRNOTAVAIL = ZMQ_EADDRNOTAVAIL |
| 2638 -ECONNREFUSED = ZMQ_ECONNREFUSED |
| 2639 -EINPROGRESS = ZMQ_EINPROGRESS |
| 2640 -ENOTSOCK = ZMQ_ENOTSOCK |
| 2641 - |
| 2642 -# new errnos in zmq3 |
| 2643 -EMSGSIZE = ZMQ_EMSGSIZE |
| 2644 -EAFNOSUPPORT = ZMQ_EAFNOSUPPORT |
| 2645 -ENETUNREACH = ZMQ_ENETUNREACH |
| 2646 -ECONNABORTED = ZMQ_ECONNABORTED |
| 2647 -ECONNRESET = ZMQ_ECONNRESET |
| 2648 -ENOTCONN = ZMQ_ENOTCONN |
| 2649 -ETIMEDOUT = ZMQ_ETIMEDOUT |
| 2650 -EHOSTUNREACH = ZMQ_EHOSTUNREACH |
| 2651 -ENETRESET = ZMQ_ENETRESET |
| 2652 - |
| 2653 -# 0MQ Native |
| 2654 -EFSM = ZMQ_EFSM |
| 2655 -ENOCOMPATPROTO = ZMQ_ENOCOMPATPROTO |
| 2656 -ETERM = ZMQ_ETERM |
| 2657 -EMTHREAD = ZMQ_EMTHREAD |
| 2658 - |
| 2659 -#----------------------------------------------------------------------------- |
| 2660 -# Symbols to export |
| 2661 -#----------------------------------------------------------------------------- |
| 2662 -_names = list(locals().keys()) |
| 2663 -__all__ = [ key for key in _names if not key.startswith('_') ] |
| 2664 diff --git a/zmq/core/context.pxd b/zmq/core/context.pxd |
| 2665 deleted file mode 100644 |
| 2666 index e399de5..0000000 |
| 2667 --- a/zmq/core/context.pxd |
| 2668 +++ /dev/null |
| 2669 @@ -1,40 +0,0 @@ |
| 2670 -"""0MQ Context class declaration.""" |
| 2671 - |
| 2672 -# |
| 2673 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 2674 -# |
| 2675 -# This file is part of pyzmq. |
| 2676 -# |
| 2677 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 2678 -# the terms of the Lesser GNU General Public License as published by |
| 2679 -# the Free Software Foundation; either version 3 of the License, or |
| 2680 -# (at your option) any later version. |
| 2681 -# |
| 2682 -# pyzmq is distributed in the hope that it will be useful, |
| 2683 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2684 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2685 -# Lesser GNU General Public License for more details. |
| 2686 -# |
| 2687 -# You should have received a copy of the Lesser GNU General Public License |
| 2688 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 2689 -# |
| 2690 - |
| 2691 -#----------------------------------------------------------------------------- |
| 2692 -# Code |
| 2693 -#----------------------------------------------------------------------------- |
| 2694 - |
| 2695 -cdef class Context: |
| 2696 - """Manage the lifecycle of a 0MQ context.""" |
| 2697 - |
| 2698 - cdef object __weakref__ # enable weakref |
| 2699 - cdef void *handle # The C handle for the underlying zmq object. |
| 2700 - cdef void **_sockets # A C-array containg socket handles |
| 2701 - cdef size_t _n_sockets # the number of sockets |
| 2702 - cdef size_t _max_sockets # the size of the _sockets array |
| 2703 - cdef int _pid # the pid of the process which created me (for
fork safety) |
| 2704 - |
| 2705 - cdef public object closed # bool property for a closed context. |
| 2706 - # helpers for events on _sockets in Socket.__cinit__()/close() |
| 2707 - cdef inline void _add_socket(self, void* handle) |
| 2708 - cdef inline void _remove_socket(self, void* handle) |
| 2709 - |
| 2710 diff --git a/zmq/core/context.pyx b/zmq/core/context.pyx |
| 2711 deleted file mode 100644 |
| 2712 index 0917c66..0000000 |
| 2713 --- a/zmq/core/context.pyx |
| 2714 +++ /dev/null |
| 2715 @@ -1,254 +0,0 @@ |
| 2716 -"""0MQ Context class.""" |
| 2717 - |
| 2718 -# |
| 2719 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 2720 -# |
| 2721 -# This file is part of pyzmq. |
| 2722 -# |
| 2723 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 2724 -# the terms of the Lesser GNU General Public License as published by |
| 2725 -# the Free Software Foundation; either version 3 of the License, or |
| 2726 -# (at your option) any later version. |
| 2727 -# |
| 2728 -# pyzmq is distributed in the hope that it will be useful, |
| 2729 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2730 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2731 -# Lesser GNU General Public License for more details. |
| 2732 -# |
| 2733 -# You should have received a copy of the Lesser GNU General Public License |
| 2734 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 2735 -# |
| 2736 - |
| 2737 -#----------------------------------------------------------------------------- |
| 2738 -# Imports |
| 2739 -#----------------------------------------------------------------------------- |
| 2740 - |
| 2741 -from libc.stdlib cimport free, malloc, realloc |
| 2742 - |
| 2743 -from libzmq cimport * |
| 2744 - |
| 2745 -cdef extern from "getpid_compat.h": |
| 2746 - int getpid() |
| 2747 - |
| 2748 -from zmq.error import ZMQError |
| 2749 -from zmq.core.checkrc cimport _check_rc |
| 2750 - |
| 2751 -#----------------------------------------------------------------------------- |
| 2752 -# Code |
| 2753 -#----------------------------------------------------------------------------- |
| 2754 - |
| 2755 -_instance = None |
| 2756 - |
| 2757 -cdef class Context: |
| 2758 - """Context(io_threads=1) |
| 2759 - |
| 2760 - Manage the lifecycle of a 0MQ context. |
| 2761 - |
| 2762 - Parameters |
| 2763 - ---------- |
| 2764 - io_threads : int |
| 2765 - The number of IO threads. |
| 2766 - """ |
| 2767 - |
| 2768 - def __cinit__(self, int io_threads = 1, **kwargs): |
| 2769 - self.handle = NULL |
| 2770 - self._sockets = NULL |
| 2771 - |
| 2772 - if ZMQ_VERSION_MAJOR >= 3: |
| 2773 - self.handle = zmq_ctx_new() |
| 2774 - else: |
| 2775 - self.handle = zmq_init(io_threads) |
| 2776 - |
| 2777 - if self.handle == NULL: |
| 2778 - raise ZMQError() |
| 2779 - |
| 2780 - cdef int rc = 0 |
| 2781 - if ZMQ_VERSION_MAJOR >= 3: |
| 2782 - rc = zmq_ctx_set(self.handle, ZMQ_IO_THREADS, io_threads) |
| 2783 - _check_rc(rc) |
| 2784 - |
| 2785 - self.closed = False |
| 2786 - self._n_sockets = 0 |
| 2787 - self._max_sockets = 32 |
| 2788 - |
| 2789 - self._sockets = <void **>malloc(self._max_sockets*sizeof(void *)) |
| 2790 - if self._sockets == NULL: |
| 2791 - raise MemoryError("Could not allocate _sockets array") |
| 2792 - |
| 2793 - self._pid = getpid() |
| 2794 - |
| 2795 - def __init__(self, io_threads=1): |
| 2796 - # no-op |
| 2797 - pass |
| 2798 - |
| 2799 - |
| 2800 - def __del__(self): |
| 2801 - """deleting a Context should terminate it, without trying non-threadsaf
e destroy""" |
| 2802 - self.term() |
| 2803 - |
| 2804 - def __dealloc__(self): |
| 2805 - """don't touch members in dealloc, just cleanup allocations""" |
| 2806 - cdef int rc |
| 2807 - if self._sockets != NULL: |
| 2808 - free(self._sockets) |
| 2809 - self._sockets = NULL |
| 2810 - self._n_sockets = 0 |
| 2811 - self.term() |
| 2812 - |
| 2813 - cdef inline void _add_socket(self, void* handle): |
| 2814 - """Add a socket handle to be closed when Context terminates. |
| 2815 - |
| 2816 - This is to be called in the Socket constructor. |
| 2817 - """ |
| 2818 - # print self._n_sockets, self._max_sockets |
| 2819 - if self._n_sockets >= self._max_sockets: |
| 2820 - self._max_sockets *= 2 |
| 2821 - self._sockets = <void **>realloc(self._sockets, self._max_sockets*s
izeof(void *)) |
| 2822 - if self._sockets == NULL: |
| 2823 - raise MemoryError("Could not reallocate _sockets array") |
| 2824 - |
| 2825 - self._sockets[self._n_sockets] = handle |
| 2826 - self._n_sockets += 1 |
| 2827 - # print self._n_sockets, self._max_sockets |
| 2828 - |
| 2829 - cdef inline void _remove_socket(self, void* handle): |
| 2830 - """Remove a socket from the collected handles. |
| 2831 - |
| 2832 - This should be called by Socket.close, to prevent trying to |
| 2833 - close a socket a second time. |
| 2834 - """ |
| 2835 - cdef bint found = False |
| 2836 - |
| 2837 - for idx in range(self._n_sockets): |
| 2838 - if self._sockets[idx] == handle: |
| 2839 - found=True |
| 2840 - break |
| 2841 - |
| 2842 - if found: |
| 2843 - self._n_sockets -= 1 |
| 2844 - if self._n_sockets: |
| 2845 - # move last handle to closed socket's index |
| 2846 - self._sockets[idx] = self._sockets[self._n_sockets] |
| 2847 - |
| 2848 - @property |
| 2849 - def _handle(self): |
| 2850 - return <Py_ssize_t> self.handle |
| 2851 - |
| 2852 - def term(self): |
| 2853 - """ctx.term() |
| 2854 - |
| 2855 - Close or terminate the context. |
| 2856 - |
| 2857 - This can be called to close the context by hand. If this is not called, |
| 2858 - the context will automatically be closed when it is garbage collected. |
| 2859 - """ |
| 2860 - cdef int rc |
| 2861 - cdef int i=-1 |
| 2862 - |
| 2863 - if self.handle != NULL and not self.closed and getpid() == self._pid: |
| 2864 - with nogil: |
| 2865 - rc = zmq_ctx_destroy(self.handle) |
| 2866 - _check_rc(rc) |
| 2867 - self.handle = NULL |
| 2868 - self.closed = True |
| 2869 - |
| 2870 - def set(self, int option, optval): |
| 2871 - """ctx.set(option, optval) |
| 2872 - |
| 2873 - Set context options. |
| 2874 - |
| 2875 - See the 0MQ API documentation for zmq_ctx_set |
| 2876 - for details on specific options. |
| 2877 - |
| 2878 - New in libzmq-3.2 |
| 2879 - |
| 2880 - Parameters |
| 2881 - ---------- |
| 2882 - option : int |
| 2883 - The option to set. Available values will depend on your |
| 2884 - version of libzmq. Examples include:: |
| 2885 - |
| 2886 - zmq.IO_THREADS, zmq.MAX_SOCKETS |
| 2887 - |
| 2888 - optval : int |
| 2889 - The value of the option to set. |
| 2890 - """ |
| 2891 - cdef int optval_int_c |
| 2892 - cdef int rc |
| 2893 - cdef char* optval_c |
| 2894 - |
| 2895 - if self.closed: |
| 2896 - raise RuntimeError("Context has been destroyed") |
| 2897 - |
| 2898 - if not isinstance(optval, int): |
| 2899 - raise TypeError('expected int, got: %r' % optval) |
| 2900 - optval_int_c = optval |
| 2901 - rc = zmq_ctx_set(self.handle, option, optval_int_c) |
| 2902 - _check_rc(rc) |
| 2903 - |
| 2904 - def get(self, int option): |
| 2905 - """ctx.get(option) |
| 2906 - |
| 2907 - Get the value of a context option. |
| 2908 - |
| 2909 - See the 0MQ API documentation for zmq_ctx_get |
| 2910 - for details on specific options. |
| 2911 - |
| 2912 - New in libzmq-3.2 |
| 2913 - |
| 2914 - Parameters |
| 2915 - ---------- |
| 2916 - option : int |
| 2917 - The option to get. Available values will depend on your |
| 2918 - version of libzmq. Examples include:: |
| 2919 - |
| 2920 - zmq.IO_THREADS, zmq.MAX_SOCKETS |
| 2921 - |
| 2922 - Returns |
| 2923 - ------- |
| 2924 - optval : int |
| 2925 - The value of the option as an integer. |
| 2926 - """ |
| 2927 - cdef int optval_int_c |
| 2928 - cdef size_t sz |
| 2929 - cdef int rc |
| 2930 - |
| 2931 - if self.closed: |
| 2932 - raise RuntimeError("Context has been destroyed") |
| 2933 - |
| 2934 - rc = zmq_ctx_get(self.handle, option) |
| 2935 - _check_rc(rc) |
| 2936 - |
| 2937 - return rc |
| 2938 - |
| 2939 - def destroy(self, linger=None): |
| 2940 - """ctx.destroy(linger=None) |
| 2941 - |
| 2942 - Close all sockets associated with this context, and then terminate |
| 2943 - the context. If linger is specified, |
| 2944 - the LINGER sockopt of the sockets will be set prior to closing. |
| 2945 - |
| 2946 - WARNING: |
| 2947 - |
| 2948 - destroy involves calling zmq_close(), which is *NOT* threadsafe. |
| 2949 - If there are active sockets in other threads, this must not be called. |
| 2950 - """ |
| 2951 - |
| 2952 - cdef int linger_c |
| 2953 - cdef bint setlinger=False |
| 2954 - |
| 2955 - if linger is not None: |
| 2956 - linger_c = linger |
| 2957 - setlinger=True |
| 2958 - if self.handle != NULL and not self.closed and self._n_sockets: |
| 2959 - while self._n_sockets: |
| 2960 - if setlinger: |
| 2961 - zmq_setsockopt(self._sockets[0], ZMQ_LINGER, &linger_c, siz
eof(int)) |
| 2962 - rc = zmq_close(self._sockets[0]) |
| 2963 - if rc < 0 and zmq_errno() != ZMQ_ENOTSOCK: |
| 2964 - raise ZMQError() |
| 2965 - self._n_sockets -= 1 |
| 2966 - self._sockets[0] = self._sockets[self._n_sockets] |
| 2967 - self.term() |
| 2968 - |
| 2969 -__all__ = ['Context'] |
| 2970 diff --git a/zmq/core/error.pyx b/zmq/core/error.pyx |
| 2971 deleted file mode 100644 |
| 2972 index 85e785f..0000000 |
| 2973 --- a/zmq/core/error.pyx |
| 2974 +++ /dev/null |
| 2975 @@ -1,56 +0,0 @@ |
| 2976 -"""0MQ Error classes and functions.""" |
| 2977 - |
| 2978 -# |
| 2979 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 2980 -# |
| 2981 -# This file is part of pyzmq. |
| 2982 -# |
| 2983 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 2984 -# the terms of the Lesser GNU General Public License as published by |
| 2985 -# the Free Software Foundation; either version 3 of the License, or |
| 2986 -# (at your option) any later version. |
| 2987 -# |
| 2988 -# pyzmq is distributed in the hope that it will be useful, |
| 2989 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2990 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2991 -# Lesser GNU General Public License for more details. |
| 2992 -# |
| 2993 -# You should have received a copy of the Lesser GNU General Public License |
| 2994 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 2995 -# |
| 2996 - |
| 2997 -#----------------------------------------------------------------------------- |
| 2998 -# Imports |
| 2999 -#----------------------------------------------------------------------------- |
| 3000 - |
| 3001 -# allow const char* |
| 3002 -cdef extern from *: |
| 3003 - ctypedef char* const_char_ptr "const char*" |
| 3004 - |
| 3005 -from libzmq cimport zmq_strerror, zmq_errno as zmq_errno_c |
| 3006 - |
| 3007 -from zmq.utils.strtypes import bytes |
| 3008 - |
| 3009 -def strerror(int errno): |
| 3010 - """strerror(errno) |
| 3011 - |
| 3012 - Return the error string given the error number. |
| 3013 - """ |
| 3014 - cdef const_char_ptr str_e |
| 3015 - # char * will be a bytes object: |
| 3016 - str_e = zmq_strerror(errno) |
| 3017 - if str is bytes: |
| 3018 - # Python 2: str is bytes, so we already have the right type |
| 3019 - return str_e |
| 3020 - else: |
| 3021 - # Python 3: decode bytes to unicode str |
| 3022 - return str_e.decode() |
| 3023 - |
| 3024 -def zmq_errno(): |
| 3025 - """zmq_errno() |
| 3026 - |
| 3027 - Return the integer errno of the most recent zmq error. |
| 3028 - """ |
| 3029 - return zmq_errno_c() |
| 3030 - |
| 3031 -__all__ = ['strerror', 'zmq_errno'] |
| 3032 diff --git a/zmq/core/message.pxd b/zmq/core/message.pxd |
| 3033 deleted file mode 100644 |
| 3034 index a86a8e0..0000000 |
| 3035 --- a/zmq/core/message.pxd |
| 3036 +++ /dev/null |
| 3037 @@ -1,66 +0,0 @@ |
| 3038 -"""0MQ Message related class declarations.""" |
| 3039 - |
| 3040 -# |
| 3041 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 3042 -# |
| 3043 -# This file is part of pyzmq. |
| 3044 -# |
| 3045 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 3046 -# the terms of the Lesser GNU General Public License as published by |
| 3047 -# the Free Software Foundation; either version 3 of the License, or |
| 3048 -# (at your option) any later version. |
| 3049 -# |
| 3050 -# pyzmq is distributed in the hope that it will be useful, |
| 3051 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 3052 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 3053 -# Lesser GNU General Public License for more details. |
| 3054 -# |
| 3055 -# You should have received a copy of the Lesser GNU General Public License |
| 3056 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 3057 -# |
| 3058 - |
| 3059 -#----------------------------------------------------------------------------- |
| 3060 -# Imports |
| 3061 -#----------------------------------------------------------------------------- |
| 3062 - |
| 3063 -from cpython cimport PyBytes_FromStringAndSize |
| 3064 - |
| 3065 -from libzmq cimport zmq_msg_t, zmq_msg_data, zmq_msg_size |
| 3066 - |
| 3067 -#----------------------------------------------------------------------------- |
| 3068 -# Code |
| 3069 -#----------------------------------------------------------------------------- |
| 3070 - |
| 3071 -cdef class MessageTracker(object): |
| 3072 - """A class for tracking if 0MQ is done using one or more messages.""" |
| 3073 - |
| 3074 - cdef set events # Message Event objects to track. |
| 3075 - cdef set peers # Other Message or MessageTracker objects. |
| 3076 - |
| 3077 - |
| 3078 -cdef class Frame: |
| 3079 - """A Message Frame class for non-copy send/recvs.""" |
| 3080 - |
| 3081 - cdef zmq_msg_t zmq_msg |
| 3082 - cdef object _data # The actual message data as a Python object. |
| 3083 - cdef object _buffer # A Python Buffer/View of the message contents |
| 3084 - cdef object _bytes # A bytes/str copy of the message. |
| 3085 - cdef bint _failed_init # Flag to handle failed zmq_msg_init |
| 3086 - cdef public object tracker_event # Event for use with zmq_free_fn. |
| 3087 - cdef public object tracker # MessageTracker object. |
| 3088 - cdef public bint more # whether RCVMORE was set |
| 3089 - |
| 3090 - cdef Frame fast_copy(self) # Create shallow copy of Message object. |
| 3091 - cdef object _getbuffer(self) # Construct self._buffer. |
| 3092 - |
| 3093 - |
| 3094 -cdef inline object copy_zmq_msg_bytes(zmq_msg_t *zmq_msg): |
| 3095 - """ Copy the data from a zmq_msg_t """ |
| 3096 - cdef char *data_c = NULL |
| 3097 - cdef Py_ssize_t data_len_c |
| 3098 - with nogil: |
| 3099 - data_c = <char *>zmq_msg_data(zmq_msg) |
| 3100 - data_len_c = zmq_msg_size(zmq_msg) |
| 3101 - return PyBytes_FromStringAndSize(data_c, data_len_c) |
| 3102 - |
| 3103 - |
| 3104 diff --git a/zmq/core/message.pyx b/zmq/core/message.pyx |
| 3105 deleted file mode 100644 |
| 3106 index 1d358ab..0000000 |
| 3107 --- a/zmq/core/message.pyx |
| 3108 +++ /dev/null |
| 3109 @@ -1,297 +0,0 @@ |
| 3110 -"""0MQ Message related classes.""" |
| 3111 - |
| 3112 -# |
| 3113 -# Copyright (c) 2013 Brian E. Granger & Min Ragan-Kelley |
| 3114 -# |
| 3115 -# This file is part of pyzmq. |
| 3116 -# |
| 3117 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 3118 -# the terms of the Lesser GNU General Public License as published by |
| 3119 -# the Free Software Foundation; either version 3 of the License, or |
| 3120 -# (at your option) any later version. |
| 3121 -# |
| 3122 -# pyzmq is distributed in the hope that it will be useful, |
| 3123 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 3124 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 3125 -# Lesser GNU General Public License for more details. |
| 3126 -# |
| 3127 -# You should have received a copy of the Lesser GNU General Public License |
| 3128 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 3129 -# |
| 3130 - |
| 3131 -#----------------------------------------------------------------------------- |
| 3132 -# Imports |
| 3133 -#----------------------------------------------------------------------------- |
| 3134 - |
| 3135 -# get version-independent aliases: |
| 3136 -cdef extern from "pyversion_compat.h": |
| 3137 - pass |
| 3138 - |
| 3139 -from cpython cimport Py_DECREF, Py_INCREF |
| 3140 - |
| 3141 -from buffers cimport asbuffer_r, viewfromobject_r |
| 3142 - |
| 3143 -cdef extern from "Python.h": |
| 3144 - ctypedef int Py_ssize_t |
| 3145 - |
| 3146 -from libzmq cimport * |
| 3147 - |
| 3148 -import time |
| 3149 - |
| 3150 -try: |
| 3151 - # below 3.3 |
| 3152 - from threading import _Event as Event |
| 3153 -except (ImportError, AttributeError): |
| 3154 - # python throws ImportError, cython throws AttributeError |
| 3155 - from threading import Event |
| 3156 - |
| 3157 -import zmq |
| 3158 -from zmq.core.checkrc cimport _check_rc |
| 3159 -from zmq.utils.strtypes import bytes,unicode,basestring |
| 3160 - |
| 3161 -#----------------------------------------------------------------------------- |
| 3162 -# Code |
| 3163 -#----------------------------------------------------------------------------- |
| 3164 - |
| 3165 - |
| 3166 -cdef void free_python_msg(void *data, void *hint) with gil: |
| 3167 - """A function for DECREF'ing Python based messages.""" |
| 3168 - if hint != NULL: |
| 3169 - tracker_event = (<tuple>hint)[1] |
| 3170 - Py_DECREF(<object>hint) |
| 3171 - if isinstance(tracker_event, Event): |
| 3172 - # don't assert before DECREF: |
| 3173 - # assert tracker_queue.empty(), "somebody else wrote to my Queue!" |
| 3174 - tracker_event.set() |
| 3175 - tracker_event = None |
| 3176 - |
| 3177 - |
| 3178 -cdef class Frame: |
| 3179 - """Frame(data=None, track=False) |
| 3180 - |
| 3181 - A zmq message Frame class for non-copy send/recvs. |
| 3182 - |
| 3183 - This class is only needed if you want to do non-copying send and recvs. |
| 3184 - When you pass a string to this class, like ``Frame(s)``, the |
| 3185 - ref-count of `s` is increased by two: once because the Frame saves `s` as |
| 3186 - an instance attribute and another because a ZMQ message is created that |
| 3187 - points to the buffer of `s`. This second ref-count increase makes sure |
| 3188 - that `s` lives until all messages that use it have been sent. Once 0MQ |
| 3189 - sends all the messages and it doesn't need the buffer of s, 0MQ will call |
| 3190 - ``Py_DECREF(s)``. |
| 3191 - |
| 3192 - Parameters |
| 3193 - ---------- |
| 3194 - |
| 3195 - data : object, optional |
| 3196 - any object that provides the buffer interface will be used to |
| 3197 - construct the 0MQ message data. |
| 3198 - track : bool [default: False] |
| 3199 - whether a MessageTracker_ should be created to track this object. |
| 3200 - Tracking a message has a cost at creation, because it creates a threads
afe |
| 3201 - Event object. |
| 3202 - |
| 3203 - """ |
| 3204 - |
| 3205 - def __cinit__(self, object data=None, track=False, **kwargs): |
| 3206 - cdef int rc |
| 3207 - cdef char *data_c = NULL |
| 3208 - cdef Py_ssize_t data_len_c=0 |
| 3209 - cdef object hint |
| 3210 - |
| 3211 - # init more as False |
| 3212 - self.more = False |
| 3213 - |
| 3214 - # Save the data object in case the user wants the the data as a str. |
| 3215 - self._data = data |
| 3216 - self._failed_init = True # bool switch for dealloc |
| 3217 - self._buffer = None # buffer view of data |
| 3218 - self._bytes = None # bytes copy of data |
| 3219 - |
| 3220 - # Event and MessageTracker for monitoring when zmq is done with data: |
| 3221 - if track: |
| 3222 - evt = Event() |
| 3223 - self.tracker_event = evt |
| 3224 - self.tracker = zmq.MessageTracker(evt) |
| 3225 - else: |
| 3226 - self.tracker_event = None |
| 3227 - self.tracker = None |
| 3228 - |
| 3229 - if isinstance(data, unicode): |
| 3230 - raise TypeError("Unicode objects not allowed. Only: str/bytes, buff
er interfaces.") |
| 3231 - |
| 3232 - if data is None: |
| 3233 - with nogil: |
| 3234 - rc = zmq_msg_init(&self.zmq_msg) |
| 3235 - _check_rc(rc) |
| 3236 - self._failed_init = False |
| 3237 - return |
| 3238 - else: |
| 3239 - asbuffer_r(data, <void **>&data_c, &data_len_c) |
| 3240 - # We INCREF the *original* Python object (not self) and pass it |
| 3241 - # as the hint below. This allows other copies of this Frame |
| 3242 - # object to take over the ref counting of data properly. |
| 3243 - hint = (data, self.tracker_event) |
| 3244 - Py_INCREF(hint) |
| 3245 - with nogil: |
| 3246 - rc = zmq_msg_init_data( |
| 3247 - &self.zmq_msg, <void *>data_c, data_len_c, |
| 3248 - <zmq_free_fn *>free_python_msg, <void *>hint |
| 3249 - ) |
| 3250 - if rc != 0: |
| 3251 - Py_DECREF(hint) |
| 3252 - _check_rc(rc) |
| 3253 - self._failed_init = False |
| 3254 - |
| 3255 - def __init__(self, object data=None, track=False): |
| 3256 - """Enforce signature""" |
| 3257 - pass |
| 3258 - |
| 3259 - def __dealloc__(self): |
| 3260 - cdef int rc |
| 3261 - if self._failed_init: |
| 3262 - return |
| 3263 - # This simply decreases the 0MQ ref-count of zmq_msg. |
| 3264 - with nogil: |
| 3265 - rc = zmq_msg_close(&self.zmq_msg) |
| 3266 - _check_rc(rc) |
| 3267 - |
| 3268 - # buffer interface code adapted from petsc4py by Lisandro Dalcin, a BSD pro
ject |
| 3269 - |
| 3270 - def __getbuffer__(self, Py_buffer* buffer, int flags): |
| 3271 - # new-style (memoryview) buffer interface |
| 3272 - with nogil: |
| 3273 - buffer.buf = zmq_msg_data(&self.zmq_msg) |
| 3274 - buffer.len = zmq_msg_size(&self.zmq_msg) |
| 3275 - |
| 3276 - buffer.obj = self |
| 3277 - buffer.readonly = 1 |
| 3278 - buffer.format = "B" |
| 3279 - buffer.ndim = 0 |
| 3280 - buffer.shape = NULL |
| 3281 - buffer.strides = NULL |
| 3282 - buffer.suboffsets = NULL |
| 3283 - buffer.itemsize = 1 |
| 3284 - buffer.internal = NULL |
| 3285 - |
| 3286 - def __getsegcount__(self, Py_ssize_t *lenp): |
| 3287 - # required for getreadbuffer |
| 3288 - if lenp != NULL: |
| 3289 - with nogil: |
| 3290 - lenp[0] = zmq_msg_size(&self.zmq_msg) |
| 3291 - return 1 |
| 3292 - |
| 3293 - def __getreadbuffer__(self, Py_ssize_t idx, void **p): |
| 3294 - # old-style (buffer) interface |
| 3295 - cdef char *data_c = NULL |
| 3296 - cdef Py_ssize_t data_len_c |
| 3297 - if idx != 0: |
| 3298 - raise SystemError("accessing non-existent buffer segment") |
| 3299 - # read-only, because we don't want to allow |
| 3300 - # editing of the message in-place |
| 3301 - with nogil: |
| 3302 - data_c = <char *>zmq_msg_data(&self.zmq_msg) |
| 3303 - data_len_c = zmq_msg_size(&self.zmq_msg) |
| 3304 - if p != NULL: |
| 3305 - p[0] = <void*>data_c |
| 3306 - return data_len_c |
| 3307 - |
| 3308 - # end buffer interface |
| 3309 - |
| 3310 - def __copy__(self): |
| 3311 - """Create a shallow copy of the message. |
| 3312 - |
| 3313 - This does not copy the contents of the Frame, just the pointer. |
| 3314 - This will increment the 0MQ ref count of the message, but not |
| 3315 - the ref count of the Python object. That is only done once when |
| 3316 - the Python is first turned into a 0MQ message. |
| 3317 - """ |
| 3318 - return self.fast_copy() |
| 3319 - |
| 3320 - cdef Frame fast_copy(self): |
| 3321 - """Fast, cdef'd version of shallow copy of the Frame.""" |
| 3322 - cdef Frame new_msg |
| 3323 - new_msg = Frame() |
| 3324 - # This does not copy the contents, but just increases the ref-count |
| 3325 - # of the zmq_msg by one. |
| 3326 - with nogil: |
| 3327 - zmq_msg_copy(&new_msg.zmq_msg, &self.zmq_msg) |
| 3328 - # Copy the ref to data so the copy won't create a copy when str is |
| 3329 - # called. |
| 3330 - if self._data is not None: |
| 3331 - new_msg._data = self._data |
| 3332 - if self._buffer is not None: |
| 3333 - new_msg._buffer = self._buffer |
| 3334 - if self._bytes is not None: |
| 3335 - new_msg._bytes = self._bytes |
| 3336 - |
| 3337 - # Frame copies share the tracker and tracker_event |
| 3338 - new_msg.tracker_event = self.tracker_event |
| 3339 - new_msg.tracker = self.tracker |
| 3340 - |
| 3341 - return new_msg |
| 3342 - |
| 3343 - def __len__(self): |
| 3344 - """Return the length of the message in bytes.""" |
| 3345 - cdef size_t sz |
| 3346 - with nogil: |
| 3347 - sz = zmq_msg_size(&self.zmq_msg) |
| 3348 - return sz |
| 3349 - # return <int>zmq_msg_size(&self.zmq_msg) |
| 3350 - |
| 3351 - def __str__(self): |
| 3352 - """Return the str form of the message.""" |
| 3353 - if isinstance(self._data, bytes): |
| 3354 - b = self._data |
| 3355 - else: |
| 3356 - b = self.bytes |
| 3357 - if str is unicode: |
| 3358 - return b.decode() |
| 3359 - else: |
| 3360 - return b |
| 3361 - |
| 3362 - cdef inline object _getbuffer(self): |
| 3363 - """Create a Python buffer/view of the message data. |
| 3364 - |
| 3365 - This will be called only once, the first time the `buffer` property |
| 3366 - is accessed. Subsequent calls use a cached copy. |
| 3367 - """ |
| 3368 - if self._data is None: |
| 3369 - return viewfromobject_r(self) |
| 3370 - else: |
| 3371 - return viewfromobject_r(self._data) |
| 3372 - |
| 3373 - @property |
| 3374 - def buffer(self): |
| 3375 - """Get a read-only buffer view of the message contents.""" |
| 3376 - if self._buffer is None: |
| 3377 - self._buffer = self._getbuffer() |
| 3378 - return self._buffer |
| 3379 - |
| 3380 - @property |
| 3381 - def bytes(self): |
| 3382 - """Get the message content as a Python str/bytes object. |
| 3383 - |
| 3384 - The first time this property is accessed, a copy of the message |
| 3385 - contents is made. From then on that same copy of the message is |
| 3386 - returned. |
| 3387 - """ |
| 3388 - if self._bytes is None: |
| 3389 - self._bytes = copy_zmq_msg_bytes(&self.zmq_msg) |
| 3390 - return self._bytes |
| 3391 - |
| 3392 - def set(self, int option, int value): |
| 3393 - """Set a message property""" |
| 3394 - cdef int rc = zmq_msg_set(&self.zmq_msg, option, value) |
| 3395 - _check_rc(rc) |
| 3396 - |
| 3397 - def get(self, int option): |
| 3398 - """Get a message property""" |
| 3399 - cdef int rc = zmq_msg_get(&self.zmq_msg, option) |
| 3400 - _check_rc(rc) |
| 3401 - return rc |
| 3402 - |
| 3403 -# legacy Message name |
| 3404 -Message = Frame |
| 3405 - |
| 3406 -__all__ = ['Frame', 'Message'] |
| 3407 diff --git a/zmq/core/socket.pxd b/zmq/core/socket.pxd |
| 3408 deleted file mode 100644 |
| 3409 index 92253eb..0000000 |
| 3410 --- a/zmq/core/socket.pxd |
| 3411 +++ /dev/null |
| 3412 @@ -1,48 +0,0 @@ |
| 3413 -"""0MQ Socket class declaration.""" |
| 3414 - |
| 3415 -# |
| 3416 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 3417 -# |
| 3418 -# This file is part of pyzmq. |
| 3419 -# |
| 3420 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 3421 -# the terms of the Lesser GNU General Public License as published by |
| 3422 -# the Free Software Foundation; either version 3 of the License, or |
| 3423 -# (at your option) any later version. |
| 3424 -# |
| 3425 -# pyzmq is distributed in the hope that it will be useful, |
| 3426 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 3427 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 3428 -# Lesser GNU General Public License for more details. |
| 3429 -# |
| 3430 -# You should have received a copy of the Lesser GNU General Public License |
| 3431 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 3432 -# |
| 3433 - |
| 3434 -#----------------------------------------------------------------------------- |
| 3435 -# Imports |
| 3436 -#----------------------------------------------------------------------------- |
| 3437 - |
| 3438 -from context cimport Context |
| 3439 - |
| 3440 -#----------------------------------------------------------------------------- |
| 3441 -# Code |
| 3442 -#----------------------------------------------------------------------------- |
| 3443 - |
| 3444 - |
| 3445 -cdef class Socket: |
| 3446 - """A 0MQ socket.""" |
| 3447 - |
| 3448 - cdef object __weakref__ # enable weakref |
| 3449 - cdef void *handle # The C handle for the underlying zmq object. |
| 3450 - cdef public int socket_type # The 0MQ socket type - REQ,REP, etc. |
| 3451 - # Hold on to a reference to the context to make sure it is not garbage |
| 3452 - # collected until the socket it done with it. |
| 3453 - cdef public Context context # The zmq Context object that owns this. |
| 3454 - cdef public bint _closed # bool property for a closed socket. |
| 3455 - cdef int _pid # the pid of the process which created me (for
fork safety) |
| 3456 - |
| 3457 - # cpdef methods for direct-cython access: |
| 3458 - cpdef object send(self, object data, int flags=*, copy=*, track=*) |
| 3459 - cpdef object recv(self, int flags=*, copy=*, track=*) |
| 3460 - |
| 3461 diff --git a/zmq/core/socket.pyx b/zmq/core/socket.pyx |
| 3462 deleted file mode 100644 |
| 3463 index 16fbf7f..0000000 |
| 3464 --- a/zmq/core/socket.pyx |
| 3465 +++ /dev/null |
| 3466 @@ -1,628 +0,0 @@ |
| 3467 -"""0MQ Socket class.""" |
| 3468 - |
| 3469 -# |
| 3470 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 3471 -# |
| 3472 -# This file is part of pyzmq. |
| 3473 -# |
| 3474 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 3475 -# the terms of the Lesser GNU General Public License as published by |
| 3476 -# the Free Software Foundation; either version 3 of the License, or |
| 3477 -# (at your option) any later version. |
| 3478 -# |
| 3479 -# pyzmq is distributed in the hope that it will be useful, |
| 3480 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 3481 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 3482 -# Lesser GNU General Public License for more details. |
| 3483 -# |
| 3484 -# You should have received a copy of the Lesser GNU General Public License |
| 3485 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 3486 -# |
| 3487 - |
| 3488 -#----------------------------------------------------------------------------- |
| 3489 -# Cython Imports |
| 3490 -#----------------------------------------------------------------------------- |
| 3491 - |
| 3492 -# get version-independent aliases: |
| 3493 -cdef extern from "pyversion_compat.h": |
| 3494 - pass |
| 3495 - |
| 3496 -from libc.errno cimport ENAMETOOLONG |
| 3497 -from libc.string cimport memcpy |
| 3498 - |
| 3499 -from cpython cimport PyBytes_FromStringAndSize |
| 3500 -from cpython cimport PyBytes_AsString, PyBytes_Size |
| 3501 -from cpython cimport Py_DECREF, Py_INCREF |
| 3502 - |
| 3503 -from buffers cimport asbuffer_r, viewfromobject_r |
| 3504 - |
| 3505 -from libzmq cimport * |
| 3506 -from message cimport Frame, copy_zmq_msg_bytes |
| 3507 - |
| 3508 -from context cimport Context |
| 3509 - |
| 3510 -cdef extern from "Python.h": |
| 3511 - ctypedef int Py_ssize_t |
| 3512 - |
| 3513 -cdef extern from "ipcmaxlen.h": |
| 3514 - int get_ipc_path_max_len() |
| 3515 - |
| 3516 -cdef extern from "getpid_compat.h": |
| 3517 - int getpid() |
| 3518 - |
| 3519 - |
| 3520 -#----------------------------------------------------------------------------- |
| 3521 -# Python Imports |
| 3522 -#----------------------------------------------------------------------------- |
| 3523 - |
| 3524 -import copy as copy_mod |
| 3525 -import time |
| 3526 -import sys |
| 3527 -import random |
| 3528 -import struct |
| 3529 -import codecs |
| 3530 - |
| 3531 -from zmq.utils import jsonapi |
| 3532 - |
| 3533 -try: |
| 3534 - import cPickle |
| 3535 - pickle = cPickle |
| 3536 -except: |
| 3537 - cPickle = None |
| 3538 - import pickle |
| 3539 - |
| 3540 -import zmq |
| 3541 -from zmq.core import constants |
| 3542 -from zmq.core.constants import * |
| 3543 -from zmq.core.checkrc cimport _check_rc |
| 3544 -from zmq.error import ZMQError, ZMQBindError |
| 3545 -from zmq.utils.strtypes import bytes,unicode,basestring |
| 3546 - |
| 3547 -#----------------------------------------------------------------------------- |
| 3548 -# Code |
| 3549 -#----------------------------------------------------------------------------- |
| 3550 - |
| 3551 -IPC_PATH_MAX_LEN = get_ipc_path_max_len() |
| 3552 - |
| 3553 -# inline some small socket submethods: |
| 3554 -# true methods frequently cannot be inlined, acc. Cython docs |
| 3555 - |
| 3556 -cdef inline _check_closed(Socket s, bint raise_notsup): |
| 3557 - cdef int rc |
| 3558 - cdef int errno |
| 3559 - cdef int stype |
| 3560 - cdef size_t sz=sizeof(int) |
| 3561 - if s._closed: |
| 3562 - if raise_notsup: |
| 3563 - raise ZMQError(ENOTSUP) |
| 3564 - else: |
| 3565 - return True |
| 3566 - else: |
| 3567 - rc = zmq_getsockopt(s.handle, ZMQ_TYPE, <void *>&stype, &sz) |
| 3568 - if rc < 0 and zmq_errno() == ENOTSOCK: |
| 3569 - s._closed = True |
| 3570 - if raise_notsup: |
| 3571 - raise ZMQError(ENOTSUP) |
| 3572 - else: |
| 3573 - return True |
| 3574 - else: |
| 3575 - _check_rc(rc) |
| 3576 - return False |
| 3577 - |
| 3578 -cdef inline Frame _recv_frame(void *handle, int flags=0, track=False): |
| 3579 - """Receive a message in a non-copying manner and return a Frame.""" |
| 3580 - cdef int rc |
| 3581 - cdef Frame msg |
| 3582 - msg = Frame(track=track) |
| 3583 - |
| 3584 - with nogil: |
| 3585 - rc = zmq_msg_recv(&msg.zmq_msg, handle, flags) |
| 3586 - |
| 3587 - _check_rc(rc) |
| 3588 - return msg |
| 3589 - |
| 3590 -cdef inline object _recv_copy(void *handle, int flags=0): |
| 3591 - """Receive a message and return a copy""" |
| 3592 - cdef zmq_msg_t zmq_msg |
| 3593 - with nogil: |
| 3594 - zmq_msg_init (&zmq_msg) |
| 3595 - rc = zmq_msg_recv(&zmq_msg, handle, flags) |
| 3596 - _check_rc(rc) |
| 3597 - msg_bytes = copy_zmq_msg_bytes(&zmq_msg) |
| 3598 - with nogil: |
| 3599 - zmq_msg_close(&zmq_msg) |
| 3600 - return msg_bytes |
| 3601 - |
| 3602 -cdef inline object _send_frame(void *handle, Frame msg, int flags=0): |
| 3603 - """Send a Frame on this socket in a non-copy manner.""" |
| 3604 - cdef int rc |
| 3605 - cdef Frame msg_copy |
| 3606 - |
| 3607 - # Always copy so the original message isn't garbage collected. |
| 3608 - # This doesn't do a real copy, just a reference. |
| 3609 - msg_copy = msg.fast_copy() |
| 3610 - |
| 3611 - with nogil: |
| 3612 - rc = zmq_msg_send(&msg_copy.zmq_msg, handle, flags) |
| 3613 - |
| 3614 - _check_rc(rc) |
| 3615 - return msg.tracker |
| 3616 - |
| 3617 - |
| 3618 -cdef inline object _send_copy(void *handle, object msg, int flags=0): |
| 3619 - """Send a message on this socket by copying its content.""" |
| 3620 - cdef int rc, rc2 |
| 3621 - cdef zmq_msg_t data |
| 3622 - cdef char *msg_c |
| 3623 - cdef Py_ssize_t msg_c_len=0 |
| 3624 - |
| 3625 - # copy to c array: |
| 3626 - asbuffer_r(msg, <void **>&msg_c, &msg_c_len) |
| 3627 - |
| 3628 - # Copy the msg before sending. This avoids any complications with |
| 3629 - # the GIL, etc. |
| 3630 - # If zmq_msg_init_* fails we must not call zmq_msg_close (Bus Error) |
| 3631 - with nogil: |
| 3632 - rc = zmq_msg_init_size(&data, msg_c_len) |
| 3633 - |
| 3634 - _check_rc(rc) |
| 3635 - |
| 3636 - with nogil: |
| 3637 - memcpy(zmq_msg_data(&data), msg_c, zmq_msg_size(&data)) |
| 3638 - rc = zmq_msg_send(&data, handle, flags) |
| 3639 - rc2 = zmq_msg_close(&data) |
| 3640 - _check_rc(rc) |
| 3641 - _check_rc(rc2) |
| 3642 - |
| 3643 - |
| 3644 -cdef class Socket: |
| 3645 - """Socket(context, socket_type) |
| 3646 - |
| 3647 - A 0MQ socket. |
| 3648 - |
| 3649 - These objects will generally be constructed via the socket() method of a Co
ntext object. |
| 3650 - |
| 3651 - Note: 0MQ Sockets are *not* threadsafe. **DO NOT** share them across thread
s. |
| 3652 - |
| 3653 - Parameters |
| 3654 - ---------- |
| 3655 - context : Context |
| 3656 - The 0MQ Context this Socket belongs to. |
| 3657 - socket_type : int |
| 3658 - The socket type, which can be any of the 0MQ socket types: |
| 3659 - REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB. |
| 3660 - |
| 3661 - See Also |
| 3662 - -------- |
| 3663 - .Context.socket : method for creating a socket bound to a Context. |
| 3664 - """ |
| 3665 - |
| 3666 - def __cinit__(self, Context context, int socket_type, *args, **kwrags): |
| 3667 - cdef Py_ssize_t c_handle |
| 3668 - c_handle = context._handle |
| 3669 - |
| 3670 - self.handle = NULL |
| 3671 - self.context = context |
| 3672 - self.socket_type = socket_type |
| 3673 - with nogil: |
| 3674 - self.handle = zmq_socket(<void *>c_handle, socket_type) |
| 3675 - if self.handle == NULL: |
| 3676 - raise ZMQError() |
| 3677 - self._closed = False |
| 3678 - self._pid = getpid() |
| 3679 - context._add_socket(self.handle) |
| 3680 - |
| 3681 - def __dealloc__(self): |
| 3682 - """close *and* remove from context's list |
| 3683 - |
| 3684 - But be careful that context might not exist if called during gc |
| 3685 - """ |
| 3686 - if self.handle != NULL and getpid() == self._pid: |
| 3687 - rc = zmq_close(self.handle) |
| 3688 - if rc != 0 and zmq_errno() != ENOTSOCK: |
| 3689 - # ignore ENOTSOCK (closed by Context) |
| 3690 - _check_rc(rc) |
| 3691 - # during gc, self.context might be NULL |
| 3692 - if self.context: |
| 3693 - self.context._remove_socket(self.handle) |
| 3694 - |
| 3695 - def __init__(self, context, socket_type): |
| 3696 - pass |
| 3697 - |
| 3698 - @property |
| 3699 - def closed(self): |
| 3700 - return _check_closed(self, False) |
| 3701 - |
| 3702 - def close(self, linger=None): |
| 3703 - """s.close(linger=None) |
| 3704 - |
| 3705 - Close the socket. |
| 3706 - |
| 3707 - If linger is specified, LINGER sockopt will be set prior to closing. |
| 3708 - |
| 3709 - This can be called to close the socket by hand. If this is not |
| 3710 - called, the socket will automatically be closed when it is |
| 3711 - garbage collected. |
| 3712 - """ |
| 3713 - cdef int rc=0 |
| 3714 - cdef int linger_c |
| 3715 - cdef bint setlinger=False |
| 3716 - |
| 3717 - if linger is not None: |
| 3718 - linger_c = linger |
| 3719 - setlinger=True |
| 3720 - |
| 3721 - if self.handle != NULL and not self._closed and getpid() == self._pid: |
| 3722 - if setlinger: |
| 3723 - zmq_setsockopt(self.handle, ZMQ_LINGER, &linger_c, sizeof(int)) |
| 3724 - rc = zmq_close(self.handle) |
| 3725 - if rc != 0 and zmq_errno() != ENOTSOCK: |
| 3726 - # ignore ENOTSOCK (closed by Context) |
| 3727 - _check_rc(rc) |
| 3728 - self._closed = True |
| 3729 - # during gc, self.context might be NULL |
| 3730 - if self.context: |
| 3731 - self.context._remove_socket(self.handle) |
| 3732 - self.handle = NULL |
| 3733 - |
| 3734 - def set(self, int option, optval): |
| 3735 - """s.set(option, optval) |
| 3736 - |
| 3737 - Set socket options. |
| 3738 - |
| 3739 - See the 0MQ API documentation for details on specific options. |
| 3740 - |
| 3741 - Parameters |
| 3742 - ---------- |
| 3743 - option : int |
| 3744 - The option to set. Available values will depend on your |
| 3745 - version of libzmq. Examples include:: |
| 3746 - |
| 3747 - zmq.SUBSCRIBE, UNSUBSCRIBE, IDENTITY, HWM, LINGER, FD |
| 3748 - |
| 3749 - optval : int or bytes |
| 3750 - The value of the option to set. |
| 3751 - """ |
| 3752 - cdef int64_t optval_int64_c |
| 3753 - cdef int optval_int_c |
| 3754 - cdef int rc |
| 3755 - cdef char* optval_c |
| 3756 - cdef Py_ssize_t sz |
| 3757 - |
| 3758 - _check_closed(self, True) |
| 3759 - if isinstance(optval, unicode): |
| 3760 - raise TypeError("unicode not allowed, use setsockopt_string") |
| 3761 - |
| 3762 - if option in zmq.constants.bytes_sockopts: |
| 3763 - if not isinstance(optval, bytes): |
| 3764 - raise TypeError('expected bytes, got: %r' % optval) |
| 3765 - optval_c = PyBytes_AsString(optval) |
| 3766 - sz = PyBytes_Size(optval) |
| 3767 - with nogil: |
| 3768 - rc = zmq_setsockopt( |
| 3769 - self.handle, option, |
| 3770 - optval_c, sz |
| 3771 - ) |
| 3772 - elif option in zmq.constants.int64_sockopts: |
| 3773 - if not isinstance(optval, int): |
| 3774 - raise TypeError('expected int, got: %r' % optval) |
| 3775 - optval_int64_c = optval |
| 3776 - with nogil: |
| 3777 - rc = zmq_setsockopt( |
| 3778 - self.handle, option, |
| 3779 - &optval_int64_c, sizeof(int64_t) |
| 3780 - ) |
| 3781 - else: |
| 3782 - # default is to assume int, which is what most new sockopts will be |
| 3783 - # this lets pyzmq work with newer libzmq which may add constants |
| 3784 - # pyzmq has not yet added, rather than artificially raising. Invali
d |
| 3785 - # sockopts will still raise just the same, but it will be libzmq do
ing |
| 3786 - # the raising. |
| 3787 - if not isinstance(optval, int): |
| 3788 - raise TypeError('expected int, got: %r' % optval) |
| 3789 - optval_int_c = optval |
| 3790 - with nogil: |
| 3791 - rc = zmq_setsockopt( |
| 3792 - self.handle, option, |
| 3793 - &optval_int_c, sizeof(int) |
| 3794 - ) |
| 3795 - |
| 3796 - _check_rc(rc) |
| 3797 - |
| 3798 - def get(self, int option): |
| 3799 - """s.get(option) |
| 3800 - |
| 3801 - Get the value of a socket option. |
| 3802 - |
| 3803 - See the 0MQ API documentation for details on specific options. |
| 3804 - |
| 3805 - Parameters |
| 3806 - ---------- |
| 3807 - option : int |
| 3808 - The option to get. Available values will depend on your |
| 3809 - version of libzmq. Examples include:: |
| 3810 - |
| 3811 - zmq.IDENTITY, HWM, LINGER, FD, EVENTS |
| 3812 - |
| 3813 - Returns |
| 3814 - ------- |
| 3815 - optval : int or bytes |
| 3816 - The value of the option as a bytestring or int. |
| 3817 - """ |
| 3818 - cdef int64_t optval_int64_c |
| 3819 - cdef int optval_int_c |
| 3820 - cdef fd_t optval_fd_c |
| 3821 - cdef char identity_str_c [255] |
| 3822 - cdef size_t sz |
| 3823 - cdef int rc |
| 3824 - |
| 3825 - _check_closed(self, True) |
| 3826 - |
| 3827 - if option in zmq.constants.bytes_sockopts: |
| 3828 - sz = 255 |
| 3829 - with nogil: |
| 3830 - rc = zmq_getsockopt(self.handle, option, <void *>identity_str_c
, &sz) |
| 3831 - _check_rc(rc) |
| 3832 - result = PyBytes_FromStringAndSize(<char *>identity_str_c, sz) |
| 3833 - elif option in zmq.constants.int64_sockopts: |
| 3834 - sz = sizeof(int64_t) |
| 3835 - with nogil: |
| 3836 - rc = zmq_getsockopt(self.handle, option, <void *>&optval_int64_
c, &sz) |
| 3837 - _check_rc(rc) |
| 3838 - result = optval_int64_c |
| 3839 - elif option == ZMQ_FD: |
| 3840 - sz = sizeof(fd_t) |
| 3841 - with nogil: |
| 3842 - rc = zmq_getsockopt(self.handle, option, <void *>&optval_fd_c,
&sz) |
| 3843 - _check_rc(rc) |
| 3844 - result = optval_fd_c |
| 3845 - else: |
| 3846 - # default is to assume int, which is what most new sockopts will be |
| 3847 - # this lets pyzmq work with newer libzmq which may add constants |
| 3848 - # pyzmq has not yet added, rather than artificially raising. Invali
d |
| 3849 - # sockopts will still raise just the same, but it will be libzmq do
ing |
| 3850 - # the raising. |
| 3851 - sz = sizeof(int) |
| 3852 - with nogil: |
| 3853 - rc = zmq_getsockopt(self.handle, option, <void *>&optval_int_c,
&sz) |
| 3854 - _check_rc(rc) |
| 3855 - result = optval_int_c |
| 3856 - |
| 3857 - return result |
| 3858 - |
| 3859 - def bind(self, addr): |
| 3860 - """s.bind(addr) |
| 3861 - |
| 3862 - Bind the socket to an address. |
| 3863 - |
| 3864 - This causes the socket to listen on a network port. Sockets on the |
| 3865 - other side of this connection will use ``Socket.connect(addr)`` to |
| 3866 - connect to this socket. |
| 3867 - |
| 3868 - Parameters |
| 3869 - ---------- |
| 3870 - addr : str |
| 3871 - The address string. This has the form 'protocol://interface:port', |
| 3872 - for example 'tcp://127.0.0.1:5555'. Protocols supported include |
| 3873 - tcp, udp, pgm, epgm, inproc and ipc. If the address is unicode, it
is |
| 3874 - encoded to utf-8 first. |
| 3875 - """ |
| 3876 - cdef int rc |
| 3877 - cdef char* c_addr |
| 3878 - |
| 3879 - _check_closed(self, True) |
| 3880 - if isinstance(addr, unicode): |
| 3881 - addr = addr.encode('utf-8') |
| 3882 - if not isinstance(addr, bytes): |
| 3883 - raise TypeError('expected str, got: %r' % addr) |
| 3884 - c_addr = addr |
| 3885 - rc = zmq_bind(self.handle, c_addr) |
| 3886 - if rc != 0: |
| 3887 - if IPC_PATH_MAX_LEN and zmq_errno() == ENAMETOOLONG: |
| 3888 - # py3compat: addr is bytes, but msg wants str |
| 3889 - if str is unicode: |
| 3890 - addr = addr.decode('utf-8', 'replace') |
| 3891 - path = addr.split('://', 1)[-1] |
| 3892 - msg = ('ipc path "{0}" is longer than {1} ' |
| 3893 - 'characters (sizeof(sockaddr_un.sun_path)). ' |
| 3894 - 'zmq.IPC_PATH_MAX_LEN constant can be used ' |
| 3895 - 'to check addr length (if it is defined).' |
| 3896 - .format(path, IPC_PATH_MAX_LEN)) |
| 3897 - raise ZMQError(msg=msg) |
| 3898 - _check_rc(rc) |
| 3899 - |
| 3900 - def connect(self, addr): |
| 3901 - """s.connect(addr) |
| 3902 - |
| 3903 - Connect to a remote 0MQ socket. |
| 3904 - |
| 3905 - Parameters |
| 3906 - ---------- |
| 3907 - addr : str |
| 3908 - The address string. This has the form 'protocol://interface:port', |
| 3909 - for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| 3910 - tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| 3911 - encoded to utf-8 first. |
| 3912 - """ |
| 3913 - cdef int rc |
| 3914 - cdef char* c_addr |
| 3915 - |
| 3916 - _check_closed(self, True) |
| 3917 - if isinstance(addr, unicode): |
| 3918 - addr = addr.encode('utf-8') |
| 3919 - if not isinstance(addr, bytes): |
| 3920 - raise TypeError('expected str, got: %r' % addr) |
| 3921 - c_addr = addr |
| 3922 - |
| 3923 - rc = zmq_connect(self.handle, c_addr) |
| 3924 - if rc != 0: |
| 3925 - raise ZMQError() |
| 3926 - |
| 3927 - def unbind(self, addr): |
| 3928 - """s.unbind(addr) |
| 3929 - |
| 3930 - Unbind from an address (undoes a call to bind). |
| 3931 - |
| 3932 - This feature requires libzmq-3 |
| 3933 - |
| 3934 - Parameters |
| 3935 - ---------- |
| 3936 - addr : str |
| 3937 - The address string. This has the form 'protocol://interface:port', |
| 3938 - for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| 3939 - tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| 3940 - encoded to utf-8 first. |
| 3941 - """ |
| 3942 - cdef int rc |
| 3943 - cdef char* c_addr |
| 3944 - |
| 3945 - if ZMQ_VERSION_MAJOR < 3: |
| 3946 - raise NotImplementedError("unbind requires libzmq >= 3.0, have %s"
% zmq.zmq_version()) |
| 3947 - |
| 3948 - |
| 3949 - _check_closed(self, True) |
| 3950 - if isinstance(addr, unicode): |
| 3951 - addr = addr.encode('utf-8') |
| 3952 - if not isinstance(addr, bytes): |
| 3953 - raise TypeError('expected str, got: %r' % addr) |
| 3954 - c_addr = addr |
| 3955 - |
| 3956 - rc = zmq_unbind(self.handle, c_addr) |
| 3957 - if rc != 0: |
| 3958 - raise ZMQError() |
| 3959 - |
| 3960 - def disconnect(self, addr): |
| 3961 - """s.disconnect(addr) |
| 3962 - |
| 3963 - Disconnect from a remote 0MQ socket (undoes a call to connect). |
| 3964 - |
| 3965 - This feature requires libzmq-3 |
| 3966 - |
| 3967 - Parameters |
| 3968 - ---------- |
| 3969 - addr : str |
| 3970 - The address string. This has the form 'protocol://interface:port', |
| 3971 - for example 'tcp://127.0.0.1:5555'. Protocols supported are |
| 3972 - tcp, upd, pgm, inproc and ipc. If the address is unicode, it is |
| 3973 - encoded to utf-8 first. |
| 3974 - """ |
| 3975 - cdef int rc |
| 3976 - cdef char* c_addr |
| 3977 - |
| 3978 - if ZMQ_VERSION_MAJOR < 3: |
| 3979 - raise NotImplementedError("disconnect requires libzmq >= 3.0, have
%s" % zmq.zmq_version()) |
| 3980 - |
| 3981 - _check_closed(self, True) |
| 3982 - if isinstance(addr, unicode): |
| 3983 - addr = addr.encode('utf-8') |
| 3984 - if not isinstance(addr, bytes): |
| 3985 - raise TypeError('expected str, got: %r' % addr) |
| 3986 - c_addr = addr |
| 3987 - |
| 3988 - rc = zmq_disconnect(self.handle, c_addr) |
| 3989 - if rc != 0: |
| 3990 - raise ZMQError() |
| 3991 - |
| 3992 - #------------------------------------------------------------------------- |
| 3993 - # Sending and receiving messages |
| 3994 - #------------------------------------------------------------------------- |
| 3995 - |
| 3996 - cpdef object send(self, object data, int flags=0, copy=True, track=False): |
| 3997 - """s.send(data, flags=0, copy=True, track=False) |
| 3998 - |
| 3999 - Send a message on this socket. |
| 4000 - |
| 4001 - This queues the message to be sent by the IO thread at a later time. |
| 4002 - |
| 4003 - Parameters |
| 4004 - ---------- |
| 4005 - data : object, str, Frame |
| 4006 - The content of the message. |
| 4007 - flags : int |
| 4008 - Any supported flag: NOBLOCK, SNDMORE. |
| 4009 - copy : bool |
| 4010 - Should the message be sent in a copying or non-copying manner. |
| 4011 - track : bool |
| 4012 - Should the message be tracked for notification that ZMQ has |
| 4013 - finished with it? (ignored if copy=True) |
| 4014 - |
| 4015 - Returns |
| 4016 - ------- |
| 4017 - None : if `copy` or not track |
| 4018 - None if message was sent, raises an exception otherwise. |
| 4019 - MessageTracker : if track and not copy |
| 4020 - a MessageTracker object, whose `pending` property will |
| 4021 - be True until the send is completed. |
| 4022 - |
| 4023 - Raises |
| 4024 - ------ |
| 4025 - TypeError |
| 4026 - If a unicode object is passed |
| 4027 - ValueError |
| 4028 - If `track=True`, but an untracked Frame is passed. |
| 4029 - ZMQError |
| 4030 - If the send does not succeed for any reason. |
| 4031 - |
| 4032 - """ |
| 4033 - _check_closed(self, True) |
| 4034 - |
| 4035 - if isinstance(data, unicode): |
| 4036 - raise TypeError("unicode not allowed, use send_unicode") |
| 4037 - |
| 4038 - if copy: |
| 4039 - # msg.bytes never returns the input data object |
| 4040 - # it is always a copy, but always the same copy |
| 4041 - if isinstance(data, Frame): |
| 4042 - data = data.buffer |
| 4043 - return _send_copy(self.handle, data, flags) |
| 4044 - else: |
| 4045 - if isinstance(data, Frame): |
| 4046 - if track and not data.tracker: |
| 4047 - raise ValueError('Not a tracked message') |
| 4048 - msg = data |
| 4049 - else: |
| 4050 - msg = Frame(data, track=track) |
| 4051 - return _send_frame(self.handle, msg, flags) |
| 4052 - |
| 4053 - cpdef object recv(self, int flags=0, copy=True, track=False): |
| 4054 - """s.recv(flags=0, copy=True, track=False) |
| 4055 - |
| 4056 - Receive a message. |
| 4057 - |
| 4058 - Parameters |
| 4059 - ---------- |
| 4060 - flags : int |
| 4061 - Any supported flag: NOBLOCK. If NOBLOCK is set, this method |
| 4062 - will raise a ZMQError with EAGAIN if a message is not ready. |
| 4063 - If NOBLOCK is not set, then this method will block until a |
| 4064 - message arrives. |
| 4065 - copy : bool |
| 4066 - Should the message be received in a copying or non-copying manner? |
| 4067 - If False a Frame object is returned, if True a string copy of |
| 4068 - message is returned. |
| 4069 - track : bool |
| 4070 - Should the message be tracked for notification that ZMQ has |
| 4071 - finished with it? (ignored if copy=True) |
| 4072 - |
| 4073 - Returns |
| 4074 - ------- |
| 4075 - msg : bytes, Frame |
| 4076 - The received message frame. If `copy` is False, then it will be a
Frame, |
| 4077 - otherwise it will be bytes. |
| 4078 - |
| 4079 - Raises |
| 4080 - ------ |
| 4081 - ZMQError |
| 4082 - for any of the reasons zmq_msg_recv might fail. |
| 4083 - """ |
| 4084 - _check_closed(self, True) |
| 4085 - |
| 4086 - if copy: |
| 4087 - return _recv_copy(self.handle, flags) |
| 4088 - else: |
| 4089 - frame = _recv_frame(self.handle, flags, track) |
| 4090 - frame.more = self.getsockopt(zmq.RCVMORE) |
| 4091 - return frame |
| 4092 - |
| 4093 - |
| 4094 -__all__ = ['Socket', 'IPC_PATH_MAX_LEN'] |
| 4095 diff --git a/zmq/core/stopwatch.pxd b/zmq/core/stopwatch.pxd |
| 4096 deleted file mode 100644 |
| 4097 index 5d56166..0000000 |
| 4098 --- a/zmq/core/stopwatch.pxd |
| 4099 +++ /dev/null |
| 4100 @@ -1,31 +0,0 @@ |
| 4101 -"""0MQ Stopwatch class declaration.""" |
| 4102 - |
| 4103 -# |
| 4104 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 4105 -# |
| 4106 -# This file is part of pyzmq. |
| 4107 -# |
| 4108 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 4109 -# the terms of the Lesser GNU General Public License as published by |
| 4110 -# the Free Software Foundation; either version 3 of the License, or |
| 4111 -# (at your option) any later version. |
| 4112 -# |
| 4113 -# pyzmq is distributed in the hope that it will be useful, |
| 4114 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 4115 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 4116 -# Lesser GNU General Public License for more details. |
| 4117 -# |
| 4118 -# You should have received a copy of the Lesser GNU General Public License |
| 4119 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 4120 -# |
| 4121 - |
| 4122 -#----------------------------------------------------------------------------- |
| 4123 -# Code |
| 4124 -#----------------------------------------------------------------------------- |
| 4125 - |
| 4126 - |
| 4127 -cdef class Stopwatch: |
| 4128 - """A simple stopwatch based on zmq_stopwatch_start/stop.""" |
| 4129 - |
| 4130 - cdef void *watch # The C handle for the underlying zmq object |
| 4131 - |
| 4132 diff --git a/zmq/core/stopwatch.pyx b/zmq/core/stopwatch.pyx |
| 4133 deleted file mode 100644 |
| 4134 index 6d2fd61..0000000 |
| 4135 --- a/zmq/core/stopwatch.pyx |
| 4136 +++ /dev/null |
| 4137 @@ -1,90 +0,0 @@ |
| 4138 -"""0MQ Stopwatch class.""" |
| 4139 - |
| 4140 -# |
| 4141 -# Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley |
| 4142 -# |
| 4143 -# This file is part of pyzmq. |
| 4144 -# |
| 4145 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 4146 -# the terms of the Lesser GNU General Public License as published by |
| 4147 -# the Free Software Foundation; either version 3 of the License, or |
| 4148 -# (at your option) any later version. |
| 4149 -# |
| 4150 -# pyzmq is distributed in the hope that it will be useful, |
| 4151 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 4152 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 4153 -# Lesser GNU General Public License for more details. |
| 4154 -# |
| 4155 -# You should have received a copy of the Lesser GNU General Public License |
| 4156 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 4157 -# |
| 4158 - |
| 4159 -#----------------------------------------------------------------------------- |
| 4160 -# Imports |
| 4161 -#----------------------------------------------------------------------------- |
| 4162 - |
| 4163 -from libzmq cimport zmq_stopwatch_start, zmq_stopwatch_stop, zmq_sleep |
| 4164 - |
| 4165 -from zmq.error import ZMQError |
| 4166 - |
| 4167 -#----------------------------------------------------------------------------- |
| 4168 -# Code |
| 4169 -#----------------------------------------------------------------------------- |
| 4170 - |
| 4171 -cdef class Stopwatch: |
| 4172 - """Stopwatch() |
| 4173 - |
| 4174 - A simple stopwatch based on zmq_stopwatch_start/stop. |
| 4175 - |
| 4176 - This class should be used for benchmarking and timing 0MQ code. |
| 4177 - """ |
| 4178 - |
| 4179 - def __cinit__(self): |
| 4180 - self.watch = NULL |
| 4181 - |
| 4182 - def __dealloc__(self): |
| 4183 - try: |
| 4184 - self.stop() |
| 4185 - except ZMQError: |
| 4186 - pass |
| 4187 - |
| 4188 - def start(self): |
| 4189 - """s.start() |
| 4190 - |
| 4191 - Start the stopwatch. |
| 4192 - """ |
| 4193 - if self.watch == NULL: |
| 4194 - with nogil: |
| 4195 - self.watch = zmq_stopwatch_start() |
| 4196 - else: |
| 4197 - raise ZMQError('Stopwatch is already runing.') |
| 4198 - |
| 4199 - def stop(self): |
| 4200 - """s.stop() |
| 4201 - |
| 4202 - Stop the stopwatch. |
| 4203 - |
| 4204 - Returns |
| 4205 - ------- |
| 4206 - t : unsigned long int |
| 4207 - the number of microseconds since ``start()`` was called. |
| 4208 - """ |
| 4209 - cdef unsigned long time |
| 4210 - if self.watch == NULL: |
| 4211 - raise ZMQError('Must start the Stopwatch before calling stop.') |
| 4212 - else: |
| 4213 - with nogil: |
| 4214 - time = zmq_stopwatch_stop(self.watch) |
| 4215 - self.watch = NULL |
| 4216 - return time |
| 4217 - |
| 4218 - def sleep(self, int seconds): |
| 4219 - """s.sleep(seconds) |
| 4220 - |
| 4221 - Sleep for an integer number of seconds. |
| 4222 - """ |
| 4223 - with nogil: |
| 4224 - zmq_sleep(seconds) |
| 4225 - |
| 4226 - |
| 4227 -__all__ = ['Stopwatch'] |
| 4228 diff --git a/zmq/devices/__init__.py b/zmq/devices/__init__.py |
| 4229 index b5c8eb3..dcae13d 100644 |
| 4230 --- a/zmq/devices/__init__.py |
| 4231 +++ b/zmq/devices/__init__.py |
| 4232 @@ -14,11 +14,12 @@ |
| 4233 #----------------------------------------------------------------------------- |
| 4234 |
| 4235 from zmq import device |
| 4236 -from zmq.devices import basedevice, proxydevice, monitoredqueue, monitoredqueue
device |
| 4237 +from zmq.devices import basedevice, proxydevice, monitoredqueuedevice |
| 4238 +from zmq.devices import _zmonitoredqueue as monitoredqueue |
| 4239 |
| 4240 from zmq.devices.basedevice import * |
| 4241 from zmq.devices.proxydevice import * |
| 4242 -from zmq.devices.monitoredqueue import * |
| 4243 +from zmq.devices._zmonitoredqueue import * |
| 4244 from zmq.devices.monitoredqueuedevice import * |
| 4245 |
| 4246 __all__ = ['device'] |
| 4247 diff --git a/zmq/devices/_zmonitoredqueue.pxd b/zmq/devices/_zmonitoredqueue.pxd |
| 4248 new file mode 100644 |
| 4249 index 0000000..e04354a |
| 4250 --- /dev/null |
| 4251 +++ b/zmq/devices/_zmonitoredqueue.pxd |
| 4252 @@ -0,0 +1,166 @@ |
| 4253 +"""MonitoredQueue class declarations. |
| 4254 + |
| 4255 +Authors |
| 4256 +------- |
| 4257 +* MinRK |
| 4258 +* Brian Granger |
| 4259 +""" |
| 4260 + |
| 4261 +# |
| 4262 +# Copyright (c) 2010 Min Ragan-Kelley, Brian Granger |
| 4263 +# |
| 4264 +# This file is part of pyzmq, but is derived and adapted from zmq_queue.cpp |
| 4265 +# originally from libzmq-2.1.6, used under LGPLv3 |
| 4266 +# |
| 4267 +# pyzmq is free software; you can redistribute it and/or modify it under |
| 4268 +# the terms of the Lesser GNU General Public License as published by |
| 4269 +# the Free Software Foundation; either version 3 of the License, or |
| 4270 +# (at your option) any later version. |
| 4271 +# |
| 4272 +# pyzmq is distributed in the hope that it will be useful, |
| 4273 +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 4274 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 4275 +# Lesser GNU General Public License for more details. |
| 4276 +# |
| 4277 +# You should have received a copy of the Lesser GNU General Public License |
| 4278 +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 4279 +# |
| 4280 + |
| 4281 +#----------------------------------------------------------------------------- |
| 4282 +# Imports |
| 4283 +#----------------------------------------------------------------------------- |
| 4284 + |
| 4285 +from libzmq cimport * |
| 4286 + |
| 4287 +#----------------------------------------------------------------------------- |
| 4288 +# MonitoredQueue C functions |
| 4289 +#----------------------------------------------------------------------------- |
| 4290 + |
| 4291 +cdef inline int _relay(void *insocket_, void *outsocket_, void *sidesocket_, |
| 4292 + zmq_msg_t msg, zmq_msg_t side_msg, zmq_msg_t id_msg, |
| 4293 + bint swap_ids) nogil: |
| 4294 + cdef int rc |
| 4295 + cdef int64_t flag_2 |
| 4296 + cdef int flag_3 |
| 4297 + cdef int flags |
| 4298 + cdef bint more |
| 4299 + cdef size_t flagsz |
| 4300 + cdef void * flag_ptr |
| 4301 + |
| 4302 + if ZMQ_VERSION_MAJOR < 3: |
| 4303 + flagsz = sizeof (int64_t) |
| 4304 + flag_ptr = &flag_2 |
| 4305 + else: |
| 4306 + flagsz = sizeof (int) |
| 4307 + flag_ptr = &flag_3 |
| 4308 + |
| 4309 + if swap_ids:# both router, must send second identity first |
| 4310 + # recv two ids into msg, id_msg |
| 4311 + rc = zmq_msg_recv(&msg, insocket_, 0) |
| 4312 + rc = zmq_msg_recv(&id_msg, insocket_, 0) |
| 4313 + |
| 4314 + # send second id (id_msg) first |
| 4315 + #!!!! always send a copy before the original !!!! |
| 4316 + rc = zmq_msg_copy(&side_msg, &id_msg) |
| 4317 + rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| 4318 + rc = zmq_msg_send(&id_msg, sidesocket_, ZMQ_SNDMORE) |
| 4319 + # send first id (msg) second |
| 4320 + rc = zmq_msg_copy(&side_msg, &msg) |
| 4321 + rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| 4322 + rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| 4323 + if rc < 0: |
| 4324 + return rc |
| 4325 + while (True): |
| 4326 + rc = zmq_msg_recv(&msg, insocket_, 0) |
| 4327 + # assert (rc == 0) |
| 4328 + rc = zmq_getsockopt (insocket_, ZMQ_RCVMORE, flag_ptr, &flagsz) |
| 4329 + flags = 0 |
| 4330 + if ZMQ_VERSION_MAJOR < 3: |
| 4331 + if flag_2: |
| 4332 + flags |= ZMQ_SNDMORE |
| 4333 + else: |
| 4334 + if flag_3: |
| 4335 + flags |= ZMQ_SNDMORE |
| 4336 + # LABEL has been removed: |
| 4337 + # rc = zmq_getsockopt (insocket_, ZMQ_RCVLABEL, flag_ptr, &flagsz) |
| 4338 + # if flag_3: |
| 4339 + # flags |= ZMQ_SNDLABEL |
| 4340 + # assert (rc == 0) |
| 4341 + |
| 4342 + rc = zmq_msg_copy(&side_msg, &msg) |
| 4343 + if flags: |
| 4344 + rc = zmq_msg_send(&side_msg, outsocket_, flags) |
| 4345 + # only SNDMORE for side-socket |
| 4346 + rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| 4347 + else: |
| 4348 + rc = zmq_msg_send(&side_msg, outsocket_, 0) |
| 4349 + rc = zmq_msg_send(&msg, sidesocket_, 0) |
| 4350 + break |
| 4351 + return rc |
| 4352 + |
| 4353 +# the MonitoredQueue C function, adapted from zmq::queue.cpp : |
| 4354 +cdef inline int c_monitored_queue (void *insocket_, void *outsocket_, |
| 4355 + void *sidesocket_, zmq_msg_t *in_msg_ptr, |
| 4356 + zmq_msg_t *out_msg_ptr, int swap_ids) nogil: |
| 4357 + """The actual C function for a monitored queue device. |
| 4358 + |
| 4359 + See ``monitored_queue()`` for details. |
| 4360 + """ |
| 4361 + |
| 4362 + cdef zmq_msg_t msg |
| 4363 + cdef int rc = zmq_msg_init (&msg) |
| 4364 + cdef zmq_msg_t id_msg |
| 4365 + rc = zmq_msg_init (&id_msg) |
| 4366 + cdef zmq_msg_t side_msg |
| 4367 + rc = zmq_msg_init (&side_msg) |
| 4368 + # assert (rc == 0) |
| 4369 + |
| 4370 + |
| 4371 + cdef zmq_pollitem_t items [2] |
| 4372 + items [0].socket = insocket_ |
| 4373 + items [0].fd = 0 |
| 4374 + items [0].events = ZMQ_POLLIN |
| 4375 + items [0].revents = 0 |
| 4376 + items [1].socket = outsocket_ |
| 4377 + items [1].fd = 0 |
| 4378 + items [1].events = ZMQ_POLLIN |
| 4379 + items [1].revents = 0 |
| 4380 + # I don't think sidesocket should be polled? |
| 4381 + # items [2].socket = sidesocket_ |
| 4382 + # items [2].fd = 0 |
| 4383 + # items [2].events = ZMQ_POLLIN |
| 4384 + # items [2].revents = 0 |
| 4385 + |
| 4386 + while (True): |
| 4387 + |
| 4388 + # // Wait while there are either requests or replies to process. |
| 4389 + rc = zmq_poll (&items [0], 2, -1) |
| 4390 + if rc < 0: |
| 4391 + return rc |
| 4392 + # // The algorithm below asumes ratio of request and replies processed |
| 4393 + # // under full load to be 1:1. Although processing requests replies |
| 4394 + # // first is tempting it is suspectible to DoS attacks (overloading |
| 4395 + # // the system with unsolicited replies). |
| 4396 + # |
| 4397 + # // Process a request. |
| 4398 + if (items [0].revents & ZMQ_POLLIN): |
| 4399 + # send in_prefix to side socket |
| 4400 + rc = zmq_msg_copy(&side_msg, in_msg_ptr) |
| 4401 + rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| 4402 + if rc < 0: |
| 4403 + return rc |
| 4404 + # relay the rest of the message |
| 4405 + rc = _relay(insocket_, outsocket_, sidesocket_, msg, side_msg, id_m
sg, swap_ids) |
| 4406 + if rc < 0: |
| 4407 + return rc |
| 4408 + if (items [1].revents & ZMQ_POLLIN): |
| 4409 + # send out_prefix to side socket |
| 4410 + rc = zmq_msg_copy(&side_msg, out_msg_ptr) |
| 4411 + rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| 4412 + if rc < 0: |
| 4413 + return rc |
| 4414 + # relay the rest of the message |
| 4415 + rc = _relay(outsocket_, insocket_, sidesocket_, msg, side_msg, id_m
sg, swap_ids) |
| 4416 + if rc < 0: |
| 4417 + return rc |
| 4418 + return 0 |
| 4419 diff --git a/zmq/devices/_zmonitoredqueue.pyx b/zmq/devices/_zmonitoredqueue.pyx |
| 4420 new file mode 100644 |
| 4421 index 0000000..a74ae8e |
| 4422 --- /dev/null |
| 4423 +++ b/zmq/devices/_zmonitoredqueue.pyx |
| 4424 @@ -0,0 +1,108 @@ |
| 4425 +"""MonitoredQueue classes and functions. |
| 4426 + |
| 4427 +Authors |
| 4428 +------- |
| 4429 +* MinRK |
| 4430 +* Brian Granger |
| 4431 +""" |
| 4432 + |
| 4433 +#----------------------------------------------------------------------------- |
| 4434 +# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| 4435 +# |
| 4436 +# This file is part of pyzmq |
| 4437 +# |
| 4438 +# Distributed under the terms of the New BSD License. The full license is in |
| 4439 +# the file COPYING.BSD, distributed as part of this software. |
| 4440 +#----------------------------------------------------------------------------- |
| 4441 + |
| 4442 +#----------------------------------------------------------------------------- |
| 4443 +# Imports |
| 4444 +#----------------------------------------------------------------------------- |
| 4445 + |
| 4446 +cdef extern from "Python.h": |
| 4447 + ctypedef int Py_ssize_t |
| 4448 + |
| 4449 +from libc.string cimport memcpy |
| 4450 + |
| 4451 +from buffers cimport asbuffer_r |
| 4452 +from libzmq cimport * |
| 4453 + |
| 4454 +from zmq.core._zsocket cimport Socket |
| 4455 +from zmq.core.checkrc cimport _check_rc |
| 4456 + |
| 4457 +from zmq import ROUTER, ZMQError |
| 4458 + |
| 4459 +#----------------------------------------------------------------------------- |
| 4460 +# MonitoredQueue functions |
| 4461 +#----------------------------------------------------------------------------- |
| 4462 + |
| 4463 + |
| 4464 +def monitored_queue(Socket in_socket, Socket out_socket, Socket mon_socket, |
| 4465 + bytes in_prefix=b'in', bytes out_prefix=b'out'): |
| 4466 + """monitored_queue(in_socket, out_socket, mon_socket, |
| 4467 + in_prefix='in', out_prefix='out') |
| 4468 + |
| 4469 + Start a monitored queue device. |
| 4470 + |
| 4471 + A monitored queue behaves just like a zmq QUEUE device as far as in_socket |
| 4472 + and out_socket are concerned, except that all messages *also* go out on |
| 4473 + mon_socket. mon_socket also prefixes the messages coming from each with a |
| 4474 + prefix, by default 'in' and 'out', so all messages sent by mon_socket are |
| 4475 + multipart. |
| 4476 + |
| 4477 + The only difference between this and a QUEUE as far as in/out are |
| 4478 + concerned is that it works with two ROUTER sockets by swapping the IDENT |
| 4479 + prefixes. |
| 4480 + |
| 4481 + Parameters |
| 4482 + ---------- |
| 4483 + in_socket : Socket |
| 4484 + One of the sockets to the Queue. Its messages will be prefixed with |
| 4485 + 'in'. |
| 4486 + out_socket : Socket |
| 4487 + One of the sockets to the Queue. Its messages will be prefixed with |
| 4488 + 'out'. The only difference between in/out socket is this prefix. |
| 4489 + mon_socket : Socket |
| 4490 + This socket sends out every message received by each of the others |
| 4491 + with an in/out prefix specifying which one it was. |
| 4492 + in_prefix : str |
| 4493 + Prefix added to broadcast messages from in_socket. |
| 4494 + out_prefix : str |
| 4495 + Prefix added to broadcast messages from out_socket. |
| 4496 + """ |
| 4497 + |
| 4498 + cdef void *ins=in_socket.handle |
| 4499 + cdef void *outs=out_socket.handle |
| 4500 + cdef void *mons=mon_socket.handle |
| 4501 + cdef zmq_msg_t in_msg |
| 4502 + cdef zmq_msg_t out_msg |
| 4503 + cdef bint swap_ids |
| 4504 + cdef char *msg_c = NULL |
| 4505 + cdef Py_ssize_t msg_c_len |
| 4506 + cdef int rc |
| 4507 + |
| 4508 + # force swap_ids if both ROUTERs |
| 4509 + swap_ids = (in_socket.socket_type == ROUTER and |
| 4510 + out_socket.socket_type == ROUTER) |
| 4511 + |
| 4512 + # build zmq_msg objects from str prefixes |
| 4513 + asbuffer_r(in_prefix, <void **>&msg_c, &msg_c_len) |
| 4514 + with nogil: |
| 4515 + rc = zmq_msg_init_size(&in_msg, msg_c_len) |
| 4516 + _check_rc(rc) |
| 4517 + |
| 4518 + with nogil: |
| 4519 + memcpy(zmq_msg_data(&in_msg), msg_c, zmq_msg_size(&in_msg)) |
| 4520 + |
| 4521 + asbuffer_r(out_prefix, <void **>&msg_c, &msg_c_len) |
| 4522 + |
| 4523 + with nogil: |
| 4524 + rc = zmq_msg_init_size(&out_msg, msg_c_len) |
| 4525 + _check_rc(rc) |
| 4526 + |
| 4527 + with nogil: |
| 4528 + memcpy(zmq_msg_data(&out_msg), msg_c, zmq_msg_size(&out_msg)) |
| 4529 + rc = c_monitored_queue(ins, outs, mons, &in_msg, &out_msg, swap_ids) |
| 4530 + return rc |
| 4531 + |
| 4532 +__all__ = ['monitored_queue'] |
| 4533 diff --git a/zmq/devices/basedevice.py b/zmq/devices/basedevice.py |
| 4534 index f65ba1f..4b2c42b 100644 |
| 4535 --- a/zmq/devices/basedevice.py |
| 4536 +++ b/zmq/devices/basedevice.py |
| 4537 @@ -20,8 +20,15 @@ Authors |
| 4538 #----------------------------------------------------------------------------- |
| 4539 |
| 4540 import time |
| 4541 -from threading import Thread |
| 4542 -from multiprocessing import Process |
| 4543 +try: |
| 4544 + from threading import Thread |
| 4545 +except ImportError: |
| 4546 + Thread = None |
| 4547 + |
| 4548 +try: |
| 4549 + from multiprocessing import Process |
| 4550 +except ImportError: |
| 4551 + Process = None |
| 4552 |
| 4553 from zmq import device, QUEUE, Context |
| 4554 |
| 4555 diff --git a/zmq/devices/monitoredqueue.pxd b/zmq/devices/monitoredqueue.pxd |
| 4556 deleted file mode 100644 |
| 4557 index e04354a..0000000 |
| 4558 --- a/zmq/devices/monitoredqueue.pxd |
| 4559 +++ /dev/null |
| 4560 @@ -1,166 +0,0 @@ |
| 4561 -"""MonitoredQueue class declarations. |
| 4562 - |
| 4563 -Authors |
| 4564 -------- |
| 4565 -* MinRK |
| 4566 -* Brian Granger |
| 4567 -""" |
| 4568 - |
| 4569 -# |
| 4570 -# Copyright (c) 2010 Min Ragan-Kelley, Brian Granger |
| 4571 -# |
| 4572 -# This file is part of pyzmq, but is derived and adapted from zmq_queue.cpp |
| 4573 -# originally from libzmq-2.1.6, used under LGPLv3 |
| 4574 -# |
| 4575 -# pyzmq is free software; you can redistribute it and/or modify it under |
| 4576 -# the terms of the Lesser GNU General Public License as published by |
| 4577 -# the Free Software Foundation; either version 3 of the License, or |
| 4578 -# (at your option) any later version. |
| 4579 -# |
| 4580 -# pyzmq is distributed in the hope that it will be useful, |
| 4581 -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 4582 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 4583 -# Lesser GNU General Public License for more details. |
| 4584 -# |
| 4585 -# You should have received a copy of the Lesser GNU General Public License |
| 4586 -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 4587 -# |
| 4588 - |
| 4589 -#----------------------------------------------------------------------------- |
| 4590 -# Imports |
| 4591 -#----------------------------------------------------------------------------- |
| 4592 - |
| 4593 -from libzmq cimport * |
| 4594 - |
| 4595 -#----------------------------------------------------------------------------- |
| 4596 -# MonitoredQueue C functions |
| 4597 -#----------------------------------------------------------------------------- |
| 4598 - |
| 4599 -cdef inline int _relay(void *insocket_, void *outsocket_, void *sidesocket_, |
| 4600 - zmq_msg_t msg, zmq_msg_t side_msg, zmq_msg_t id_msg, |
| 4601 - bint swap_ids) nogil: |
| 4602 - cdef int rc |
| 4603 - cdef int64_t flag_2 |
| 4604 - cdef int flag_3 |
| 4605 - cdef int flags |
| 4606 - cdef bint more |
| 4607 - cdef size_t flagsz |
| 4608 - cdef void * flag_ptr |
| 4609 - |
| 4610 - if ZMQ_VERSION_MAJOR < 3: |
| 4611 - flagsz = sizeof (int64_t) |
| 4612 - flag_ptr = &flag_2 |
| 4613 - else: |
| 4614 - flagsz = sizeof (int) |
| 4615 - flag_ptr = &flag_3 |
| 4616 - |
| 4617 - if swap_ids:# both router, must send second identity first |
| 4618 - # recv two ids into msg, id_msg |
| 4619 - rc = zmq_msg_recv(&msg, insocket_, 0) |
| 4620 - rc = zmq_msg_recv(&id_msg, insocket_, 0) |
| 4621 - |
| 4622 - # send second id (id_msg) first |
| 4623 - #!!!! always send a copy before the original !!!! |
| 4624 - rc = zmq_msg_copy(&side_msg, &id_msg) |
| 4625 - rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| 4626 - rc = zmq_msg_send(&id_msg, sidesocket_, ZMQ_SNDMORE) |
| 4627 - # send first id (msg) second |
| 4628 - rc = zmq_msg_copy(&side_msg, &msg) |
| 4629 - rc = zmq_msg_send(&side_msg, outsocket_, ZMQ_SNDMORE) |
| 4630 - rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| 4631 - if rc < 0: |
| 4632 - return rc |
| 4633 - while (True): |
| 4634 - rc = zmq_msg_recv(&msg, insocket_, 0) |
| 4635 - # assert (rc == 0) |
| 4636 - rc = zmq_getsockopt (insocket_, ZMQ_RCVMORE, flag_ptr, &flagsz) |
| 4637 - flags = 0 |
| 4638 - if ZMQ_VERSION_MAJOR < 3: |
| 4639 - if flag_2: |
| 4640 - flags |= ZMQ_SNDMORE |
| 4641 - else: |
| 4642 - if flag_3: |
| 4643 - flags |= ZMQ_SNDMORE |
| 4644 - # LABEL has been removed: |
| 4645 - # rc = zmq_getsockopt (insocket_, ZMQ_RCVLABEL, flag_ptr, &flagsz) |
| 4646 - # if flag_3: |
| 4647 - # flags |= ZMQ_SNDLABEL |
| 4648 - # assert (rc == 0) |
| 4649 - |
| 4650 - rc = zmq_msg_copy(&side_msg, &msg) |
| 4651 - if flags: |
| 4652 - rc = zmq_msg_send(&side_msg, outsocket_, flags) |
| 4653 - # only SNDMORE for side-socket |
| 4654 - rc = zmq_msg_send(&msg, sidesocket_, ZMQ_SNDMORE) |
| 4655 - else: |
| 4656 - rc = zmq_msg_send(&side_msg, outsocket_, 0) |
| 4657 - rc = zmq_msg_send(&msg, sidesocket_, 0) |
| 4658 - break |
| 4659 - return rc |
| 4660 - |
| 4661 -# the MonitoredQueue C function, adapted from zmq::queue.cpp : |
| 4662 -cdef inline int c_monitored_queue (void *insocket_, void *outsocket_, |
| 4663 - void *sidesocket_, zmq_msg_t *in_msg_ptr, |
| 4664 - zmq_msg_t *out_msg_ptr, int swap_ids) nogil: |
| 4665 - """The actual C function for a monitored queue device. |
| 4666 - |
| 4667 - See ``monitored_queue()`` for details. |
| 4668 - """ |
| 4669 - |
| 4670 - cdef zmq_msg_t msg |
| 4671 - cdef int rc = zmq_msg_init (&msg) |
| 4672 - cdef zmq_msg_t id_msg |
| 4673 - rc = zmq_msg_init (&id_msg) |
| 4674 - cdef zmq_msg_t side_msg |
| 4675 - rc = zmq_msg_init (&side_msg) |
| 4676 - # assert (rc == 0) |
| 4677 - |
| 4678 - |
| 4679 - cdef zmq_pollitem_t items [2] |
| 4680 - items [0].socket = insocket_ |
| 4681 - items [0].fd = 0 |
| 4682 - items [0].events = ZMQ_POLLIN |
| 4683 - items [0].revents = 0 |
| 4684 - items [1].socket = outsocket_ |
| 4685 - items [1].fd = 0 |
| 4686 - items [1].events = ZMQ_POLLIN |
| 4687 - items [1].revents = 0 |
| 4688 - # I don't think sidesocket should be polled? |
| 4689 - # items [2].socket = sidesocket_ |
| 4690 - # items [2].fd = 0 |
| 4691 - # items [2].events = ZMQ_POLLIN |
| 4692 - # items [2].revents = 0 |
| 4693 - |
| 4694 - while (True): |
| 4695 - |
| 4696 - # // Wait while there are either requests or replies to process. |
| 4697 - rc = zmq_poll (&items [0], 2, -1) |
| 4698 - if rc < 0: |
| 4699 - return rc |
| 4700 - # // The algorithm below asumes ratio of request and replies processed |
| 4701 - # // under full load to be 1:1. Although processing requests replies |
| 4702 - # // first is tempting it is suspectible to DoS attacks (overloading |
| 4703 - # // the system with unsolicited replies). |
| 4704 - # |
| 4705 - # // Process a request. |
| 4706 - if (items [0].revents & ZMQ_POLLIN): |
| 4707 - # send in_prefix to side socket |
| 4708 - rc = zmq_msg_copy(&side_msg, in_msg_ptr) |
| 4709 - rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| 4710 - if rc < 0: |
| 4711 - return rc |
| 4712 - # relay the rest of the message |
| 4713 - rc = _relay(insocket_, outsocket_, sidesocket_, msg, side_msg, id_m
sg, swap_ids) |
| 4714 - if rc < 0: |
| 4715 - return rc |
| 4716 - if (items [1].revents & ZMQ_POLLIN): |
| 4717 - # send out_prefix to side socket |
| 4718 - rc = zmq_msg_copy(&side_msg, out_msg_ptr) |
| 4719 - rc = zmq_msg_send(&side_msg, sidesocket_, ZMQ_SNDMORE) |
| 4720 - if rc < 0: |
| 4721 - return rc |
| 4722 - # relay the rest of the message |
| 4723 - rc = _relay(outsocket_, insocket_, sidesocket_, msg, side_msg, id_m
sg, swap_ids) |
| 4724 - if rc < 0: |
| 4725 - return rc |
| 4726 - return 0 |
| 4727 diff --git a/zmq/devices/monitoredqueue.pyx b/zmq/devices/monitoredqueue.pyx |
| 4728 deleted file mode 100644 |
| 4729 index 65db882..0000000 |
| 4730 --- a/zmq/devices/monitoredqueue.pyx |
| 4731 +++ /dev/null |
| 4732 @@ -1,108 +0,0 @@ |
| 4733 -"""MonitoredQueue classes and functions. |
| 4734 - |
| 4735 -Authors |
| 4736 -------- |
| 4737 -* MinRK |
| 4738 -* Brian Granger |
| 4739 -""" |
| 4740 - |
| 4741 -#----------------------------------------------------------------------------- |
| 4742 -# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| 4743 -# |
| 4744 -# This file is part of pyzmq |
| 4745 -# |
| 4746 -# Distributed under the terms of the New BSD License. The full license is in |
| 4747 -# the file COPYING.BSD, distributed as part of this software. |
| 4748 -#----------------------------------------------------------------------------- |
| 4749 - |
| 4750 -#----------------------------------------------------------------------------- |
| 4751 -# Imports |
| 4752 -#----------------------------------------------------------------------------- |
| 4753 - |
| 4754 -cdef extern from "Python.h": |
| 4755 - ctypedef int Py_ssize_t |
| 4756 - |
| 4757 -from libc.string cimport memcpy |
| 4758 - |
| 4759 -from buffers cimport asbuffer_r |
| 4760 -from libzmq cimport * |
| 4761 - |
| 4762 -from zmq.core.socket cimport Socket |
| 4763 -from zmq.core.checkrc cimport _check_rc |
| 4764 - |
| 4765 -from zmq import ROUTER, ZMQError |
| 4766 - |
| 4767 -#----------------------------------------------------------------------------- |
| 4768 -# MonitoredQueue functions |
| 4769 -#----------------------------------------------------------------------------- |
| 4770 - |
| 4771 - |
| 4772 -def monitored_queue(Socket in_socket, Socket out_socket, Socket mon_socket, |
| 4773 - bytes in_prefix=b'in', bytes out_prefix=b'out'): |
| 4774 - """monitored_queue(in_socket, out_socket, mon_socket, |
| 4775 - in_prefix='in', out_prefix='out') |
| 4776 - |
| 4777 - Start a monitored queue device. |
| 4778 - |
| 4779 - A monitored queue behaves just like a zmq QUEUE device as far as in_socket |
| 4780 - and out_socket are concerned, except that all messages *also* go out on |
| 4781 - mon_socket. mon_socket also prefixes the messages coming from each with a |
| 4782 - prefix, by default 'in' and 'out', so all messages sent by mon_socket are |
| 4783 - multipart. |
| 4784 - |
| 4785 - The only difference between this and a QUEUE as far as in/out are |
| 4786 - concerned is that it works with two ROUTER sockets by swapping the IDENT |
| 4787 - prefixes. |
| 4788 - |
| 4789 - Parameters |
| 4790 - ---------- |
| 4791 - in_socket : Socket |
| 4792 - One of the sockets to the Queue. Its messages will be prefixed with |
| 4793 - 'in'. |
| 4794 - out_socket : Socket |
| 4795 - One of the sockets to the Queue. Its messages will be prefixed with |
| 4796 - 'out'. The only difference between in/out socket is this prefix. |
| 4797 - mon_socket : Socket |
| 4798 - This socket sends out every message received by each of the others |
| 4799 - with an in/out prefix specifying which one it was. |
| 4800 - in_prefix : str |
| 4801 - Prefix added to broadcast messages from in_socket. |
| 4802 - out_prefix : str |
| 4803 - Prefix added to broadcast messages from out_socket. |
| 4804 - """ |
| 4805 - |
| 4806 - cdef void *ins=in_socket.handle |
| 4807 - cdef void *outs=out_socket.handle |
| 4808 - cdef void *mons=mon_socket.handle |
| 4809 - cdef zmq_msg_t in_msg |
| 4810 - cdef zmq_msg_t out_msg |
| 4811 - cdef bint swap_ids |
| 4812 - cdef char *msg_c = NULL |
| 4813 - cdef Py_ssize_t msg_c_len |
| 4814 - cdef int rc |
| 4815 - |
| 4816 - # force swap_ids if both ROUTERs |
| 4817 - swap_ids = (in_socket.socket_type == ROUTER and |
| 4818 - out_socket.socket_type == ROUTER) |
| 4819 - |
| 4820 - # build zmq_msg objects from str prefixes |
| 4821 - asbuffer_r(in_prefix, <void **>&msg_c, &msg_c_len) |
| 4822 - with nogil: |
| 4823 - rc = zmq_msg_init_size(&in_msg, msg_c_len) |
| 4824 - _check_rc(rc) |
| 4825 - |
| 4826 - with nogil: |
| 4827 - memcpy(zmq_msg_data(&in_msg), msg_c, zmq_msg_size(&in_msg)) |
| 4828 - |
| 4829 - asbuffer_r(out_prefix, <void **>&msg_c, &msg_c_len) |
| 4830 - |
| 4831 - with nogil: |
| 4832 - rc = zmq_msg_init_size(&out_msg, msg_c_len) |
| 4833 - _check_rc(rc) |
| 4834 - |
| 4835 - with nogil: |
| 4836 - memcpy(zmq_msg_data(&out_msg), msg_c, zmq_msg_size(&out_msg)) |
| 4837 - rc = c_monitored_queue(ins, outs, mons, &in_msg, &out_msg, swap_ids) |
| 4838 - return rc |
| 4839 - |
| 4840 -__all__ = ['monitored_queue'] |
| 4841 diff --git a/zmq/devices/monitoredqueuedevice.py b/zmq/devices/monitoredqueuedev
ice.py |
| 4842 index a9f5c3f..422715c 100644 |
| 4843 --- a/zmq/devices/monitoredqueuedevice.py |
| 4844 +++ b/zmq/devices/monitoredqueuedevice.py |
| 4845 @@ -24,7 +24,7 @@ import time |
| 4846 |
| 4847 from zmq import ZMQError, PUB |
| 4848 from zmq.devices.proxydevice import ProxyBase, Proxy, ThreadProxy, ProcessProxy |
| 4849 -from zmq.devices.monitoredqueue import monitored_queue |
| 4850 +from zmq.devices._zmonitoredqueue import monitored_queue |
| 4851 |
| 4852 #----------------------------------------------------------------------------- |
| 4853 # Classes |
| 4854 diff --git a/zmq/sugar/backend.py b/zmq/sugar/backend.py |
| 4855 index ad07379..6f87c1b 100644 |
| 4856 --- a/zmq/sugar/backend.py |
| 4857 +++ b/zmq/sugar/backend.py |
| 4858 @@ -23,8 +23,9 @@ try: |
| 4859 strerror, zmq_errno, |
| 4860 zmq_poll, |
| 4861 zmq_version_info, |
| 4862 - constants, |
| 4863 + _zconstants, |
| 4864 ) |
| 4865 + constants = _zconstants |
| 4866 except ImportError: |
| 4867 from zmq.cffi_core import ( |
| 4868 Context, |
| 4869 diff --git a/zmq/sugar/context.py b/zmq/sugar/context.py |
| 4870 index bcc4686..f0f3325 100644 |
| 4871 --- a/zmq/sugar/context.py |
| 4872 +++ b/zmq/sugar/context.py |
| 4873 @@ -128,4 +128,4 @@ class Context(ContextBase, AttributeSetter): |
| 4874 else: |
| 4875 del self.sockopts[opt] |
| 4876 |
| 4877 -__all__ = ['Context'] |
| 4878 \ No newline at end of file |
| 4879 +__all__ = ['Context'] |
| 4880 diff --git a/zmq/utils/_zinitthreads.pyx b/zmq/utils/_zinitthreads.pyx |
| 4881 new file mode 100644 |
| 4882 index 0000000..6c57c9f |
| 4883 --- /dev/null |
| 4884 +++ b/zmq/utils/_zinitthreads.pyx |
| 4885 @@ -0,0 +1,23 @@ |
| 4886 +"""Utility to initialize threads.""" |
| 4887 + |
| 4888 +#----------------------------------------------------------------------------- |
| 4889 +# Copyright (c) 2010 Brian Granger, Min Ragan-Kelley |
| 4890 +# |
| 4891 +# Distributed under the terms of the New BSD License. The full license is in |
| 4892 +# the file COPYING.BSD, distributed as part of this software. |
| 4893 +#----------------------------------------------------------------------------- |
| 4894 + |
| 4895 +#----------------------------------------------------------------------------- |
| 4896 +# Imports |
| 4897 +#----------------------------------------------------------------------------- |
| 4898 + |
| 4899 +cdef extern from "Python.h": |
| 4900 + cdef void PyEval_InitThreads() |
| 4901 + |
| 4902 +# It seems that in only *some* version of Python/Cython we need to call this |
| 4903 +# by hand to get threads initialized. Not clear why this is the case though. |
| 4904 +# If we don't have this, pyzmq will segfault. |
| 4905 +def init_threads(): |
| 4906 + PyEval_InitThreads() |
| 4907 + |
| 4908 +__all__ = ['init_threads'] |
| 4909 diff --git a/zmq/utils/_zrebuffer.pyx b/zmq/utils/_zrebuffer.pyx |
| 4910 new file mode 100644 |
| 4911 index 0000000..ca240d3 |
| 4912 --- /dev/null |
| 4913 +++ b/zmq/utils/_zrebuffer.pyx |
| 4914 @@ -0,0 +1,104 @@ |
| 4915 +""" |
| 4916 +Utility for changing itemsize of memoryviews, and getting |
| 4917 +numpy arrays from byte-arrays that should be interpreted with a different |
| 4918 +itemsize. |
| 4919 + |
| 4920 +Authors |
| 4921 +------- |
| 4922 +* MinRK |
| 4923 +""" |
| 4924 + |
| 4925 +#----------------------------------------------------------------------------- |
| 4926 +# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| 4927 +# |
| 4928 +# This file is part of pyzmq |
| 4929 +# |
| 4930 +# Distributed under the terms of the New BSD License. The full license is in |
| 4931 +# the file COPYING.BSD, distributed as part of this software. |
| 4932 +#----------------------------------------------------------------------------- |
| 4933 + |
| 4934 +from libc.stdlib cimport malloc |
| 4935 +from buffers cimport * |
| 4936 + |
| 4937 +cdef inline object _rebuffer(object obj, char * format, int itemsize): |
| 4938 + """clobber the format & itemsize of a 1-D |
| 4939 + |
| 4940 + This is the Python 3 model, but will work on Python >= 2.6. Currently, |
| 4941 + we use it only on >= 3.0. |
| 4942 + """ |
| 4943 + cdef Py_buffer view |
| 4944 + cdef int flags = PyBUF_SIMPLE |
| 4945 + cdef int mode = 0 |
| 4946 + # cdef Py_ssize_t *shape, *strides, *suboffsets |
| 4947 + |
| 4948 + mode = check_buffer(obj) |
| 4949 + if mode == 0: |
| 4950 + raise TypeError("%r does not provide a buffer interface."%obj) |
| 4951 + |
| 4952 + if mode == 3: |
| 4953 + flags = PyBUF_ANY_CONTIGUOUS |
| 4954 + if format: |
| 4955 + flags |= PyBUF_FORMAT |
| 4956 + PyObject_GetBuffer(obj, &view, flags) |
| 4957 + assert view.ndim <= 1, "Can only reinterpret 1-D memoryviews" |
| 4958 + assert view.len % itemsize == 0, "Buffer of length %i not divisible int
o items of size %i"%(view.len, itemsize) |
| 4959 + # hack the format |
| 4960 + view.ndim = 1 |
| 4961 + view.format = format |
| 4962 + view.itemsize = itemsize |
| 4963 + view.strides = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| 4964 + view.strides[0] = itemsize |
| 4965 + view.shape = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| 4966 + view.shape[0] = view.len/itemsize |
| 4967 + view.suboffsets = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| 4968 + view.suboffsets[0] = 0 |
| 4969 + # for debug: make buffer writable, for zero-copy testing |
| 4970 + # view.readonly = 0 |
| 4971 + |
| 4972 + return PyMemoryView_FromBuffer(&view) |
| 4973 + else: |
| 4974 + raise TypeError("This funciton is only for new-style buffer objects.") |
| 4975 + |
| 4976 +def rebuffer(obj, format, itemsize): |
| 4977 + """Change the itemsize of a memoryview. |
| 4978 + |
| 4979 + Only for 1D contiguous buffers. |
| 4980 + """ |
| 4981 + return _rebuffer(obj, format, itemsize) |
| 4982 + |
| 4983 +def array_from_buffer(view, dtype, shape): |
| 4984 + """Get a numpy array from a memoryview, regardless of the itemsize of the o
riginal |
| 4985 + memoryview. This is important, because pyzmq does not send memoryview shap
e data |
| 4986 + over the wire, so we need to change the memoryview itemsize before calling |
| 4987 + asarray. |
| 4988 + """ |
| 4989 + import numpy |
| 4990 + A = numpy.array([],dtype=dtype) |
| 4991 + ref = viewfromobject(A,0) |
| 4992 + fmt = ref.format.encode() |
| 4993 + buf = viewfromobject(view, 0) |
| 4994 + buf = _rebuffer(view, fmt, ref.itemsize) |
| 4995 + return numpy.asarray(buf, dtype=dtype).reshape(shape) |
| 4996 + |
| 4997 +def print_view_info(obj): |
| 4998 + """simple utility for printing info on a new-style buffer object""" |
| 4999 + cdef Py_buffer view |
| 5000 + cdef int flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT |
| 5001 + cdef int mode = 0 |
| 5002 + |
| 5003 + mode = check_buffer(obj) |
| 5004 + if mode == 0: |
| 5005 + raise TypeError("%r does not provide a buffer interface."%obj) |
| 5006 + |
| 5007 + if mode == 3: |
| 5008 + PyObject_GetBuffer(obj, &view, flags) |
| 5009 + print <Py_ssize_t>view.buf, view.len, view.format, view.ndim, |
| 5010 + if view.ndim: |
| 5011 + if view.shape: |
| 5012 + print view.shape[0], |
| 5013 + if view.strides: |
| 5014 + print view.strides[0], |
| 5015 + if view.suboffsets: |
| 5016 + print view.suboffsets[0], |
| 5017 + print |
| 5018 + |
| 5019 \ No newline at end of file |
| 5020 diff --git a/zmq/utils/initthreads.pyx b/zmq/utils/initthreads.pyx |
| 5021 deleted file mode 100644 |
| 5022 index 6c57c9f..0000000 |
| 5023 --- a/zmq/utils/initthreads.pyx |
| 5024 +++ /dev/null |
| 5025 @@ -1,23 +0,0 @@ |
| 5026 -"""Utility to initialize threads.""" |
| 5027 - |
| 5028 -#----------------------------------------------------------------------------- |
| 5029 -# Copyright (c) 2010 Brian Granger, Min Ragan-Kelley |
| 5030 -# |
| 5031 -# Distributed under the terms of the New BSD License. The full license is in |
| 5032 -# the file COPYING.BSD, distributed as part of this software. |
| 5033 -#----------------------------------------------------------------------------- |
| 5034 - |
| 5035 -#----------------------------------------------------------------------------- |
| 5036 -# Imports |
| 5037 -#----------------------------------------------------------------------------- |
| 5038 - |
| 5039 -cdef extern from "Python.h": |
| 5040 - cdef void PyEval_InitThreads() |
| 5041 - |
| 5042 -# It seems that in only *some* version of Python/Cython we need to call this |
| 5043 -# by hand to get threads initialized. Not clear why this is the case though. |
| 5044 -# If we don't have this, pyzmq will segfault. |
| 5045 -def init_threads(): |
| 5046 - PyEval_InitThreads() |
| 5047 - |
| 5048 -__all__ = ['init_threads'] |
| 5049 diff --git a/zmq/utils/rebuffer.pyx b/zmq/utils/rebuffer.pyx |
| 5050 deleted file mode 100644 |
| 5051 index ca240d3..0000000 |
| 5052 --- a/zmq/utils/rebuffer.pyx |
| 5053 +++ /dev/null |
| 5054 @@ -1,104 +0,0 @@ |
| 5055 -""" |
| 5056 -Utility for changing itemsize of memoryviews, and getting |
| 5057 -numpy arrays from byte-arrays that should be interpreted with a different |
| 5058 -itemsize. |
| 5059 - |
| 5060 -Authors |
| 5061 -------- |
| 5062 -* MinRK |
| 5063 -""" |
| 5064 - |
| 5065 -#----------------------------------------------------------------------------- |
| 5066 -# Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley |
| 5067 -# |
| 5068 -# This file is part of pyzmq |
| 5069 -# |
| 5070 -# Distributed under the terms of the New BSD License. The full license is in |
| 5071 -# the file COPYING.BSD, distributed as part of this software. |
| 5072 -#----------------------------------------------------------------------------- |
| 5073 - |
| 5074 -from libc.stdlib cimport malloc |
| 5075 -from buffers cimport * |
| 5076 - |
| 5077 -cdef inline object _rebuffer(object obj, char * format, int itemsize): |
| 5078 - """clobber the format & itemsize of a 1-D |
| 5079 - |
| 5080 - This is the Python 3 model, but will work on Python >= 2.6. Currently, |
| 5081 - we use it only on >= 3.0. |
| 5082 - """ |
| 5083 - cdef Py_buffer view |
| 5084 - cdef int flags = PyBUF_SIMPLE |
| 5085 - cdef int mode = 0 |
| 5086 - # cdef Py_ssize_t *shape, *strides, *suboffsets |
| 5087 - |
| 5088 - mode = check_buffer(obj) |
| 5089 - if mode == 0: |
| 5090 - raise TypeError("%r does not provide a buffer interface."%obj) |
| 5091 - |
| 5092 - if mode == 3: |
| 5093 - flags = PyBUF_ANY_CONTIGUOUS |
| 5094 - if format: |
| 5095 - flags |= PyBUF_FORMAT |
| 5096 - PyObject_GetBuffer(obj, &view, flags) |
| 5097 - assert view.ndim <= 1, "Can only reinterpret 1-D memoryviews" |
| 5098 - assert view.len % itemsize == 0, "Buffer of length %i not divisible int
o items of size %i"%(view.len, itemsize) |
| 5099 - # hack the format |
| 5100 - view.ndim = 1 |
| 5101 - view.format = format |
| 5102 - view.itemsize = itemsize |
| 5103 - view.strides = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| 5104 - view.strides[0] = itemsize |
| 5105 - view.shape = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| 5106 - view.shape[0] = view.len/itemsize |
| 5107 - view.suboffsets = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)) |
| 5108 - view.suboffsets[0] = 0 |
| 5109 - # for debug: make buffer writable, for zero-copy testing |
| 5110 - # view.readonly = 0 |
| 5111 - |
| 5112 - return PyMemoryView_FromBuffer(&view) |
| 5113 - else: |
| 5114 - raise TypeError("This funciton is only for new-style buffer objects.") |
| 5115 - |
| 5116 -def rebuffer(obj, format, itemsize): |
| 5117 - """Change the itemsize of a memoryview. |
| 5118 - |
| 5119 - Only for 1D contiguous buffers. |
| 5120 - """ |
| 5121 - return _rebuffer(obj, format, itemsize) |
| 5122 - |
| 5123 -def array_from_buffer(view, dtype, shape): |
| 5124 - """Get a numpy array from a memoryview, regardless of the itemsize of the o
riginal |
| 5125 - memoryview. This is important, because pyzmq does not send memoryview shap
e data |
| 5126 - over the wire, so we need to change the memoryview itemsize before calling |
| 5127 - asarray. |
| 5128 - """ |
| 5129 - import numpy |
| 5130 - A = numpy.array([],dtype=dtype) |
| 5131 - ref = viewfromobject(A,0) |
| 5132 - fmt = ref.format.encode() |
| 5133 - buf = viewfromobject(view, 0) |
| 5134 - buf = _rebuffer(view, fmt, ref.itemsize) |
| 5135 - return numpy.asarray(buf, dtype=dtype).reshape(shape) |
| 5136 - |
| 5137 -def print_view_info(obj): |
| 5138 - """simple utility for printing info on a new-style buffer object""" |
| 5139 - cdef Py_buffer view |
| 5140 - cdef int flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT |
| 5141 - cdef int mode = 0 |
| 5142 - |
| 5143 - mode = check_buffer(obj) |
| 5144 - if mode == 0: |
| 5145 - raise TypeError("%r does not provide a buffer interface."%obj) |
| 5146 - |
| 5147 - if mode == 3: |
| 5148 - PyObject_GetBuffer(obj, &view, flags) |
| 5149 - print <Py_ssize_t>view.buf, view.len, view.format, view.ndim, |
| 5150 - if view.ndim: |
| 5151 - if view.shape: |
| 5152 - print view.shape[0], |
| 5153 - if view.strides: |
| 5154 - print view.strides[0], |
| 5155 - if view.suboffsets: |
| 5156 - print view.suboffsets[0], |
| 5157 - print |
| 5158 - |
| 5159 \ No newline at end of file |
OLD | NEW |