Hello community,
here is the log from the commit of package python-amqp for openSUSE:Factory checked in at 2014-01-15 16:26:33
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-amqp (Old)
and /work/SRC/openSUSE:Factory/.python-amqp.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-amqp"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-amqp/python-amqp.changes 2013-12-02 09:53:05.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-amqp.new/python-amqp.changes 2014-01-15 16:26:34.000000000 +0100
@@ -1,0 +2,8 @@
+Tue Jan 14 10:56:30 UTC 2014 - dmueller@suse.com
+
+- update to 1.4.0:
+ - Heartbeat implementation improved (Issue #6).
+ - NoneType is now supported in tables and arrays.
+ - SSLTransport: Now handles ``ENOENT``.
+
+-------------------------------------------------------------------
Old:
----
amqp-1.3.3.tar.gz
New:
----
amqp-1.4.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-amqp.spec ++++++
--- /var/tmp/diff_new_pack.seb3u1/_old 2014-01-15 16:26:34.000000000 +0100
+++ /var/tmp/diff_new_pack.seb3u1/_new 2014-01-15 16:26:34.000000000 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-amqp
#
-# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
Name: python-amqp
-Version: 1.3.3
+Version: 1.4.0
Release: 0
Summary: Low-level AMQP client for Python (fork of amqplib)
License: LGPL-2.1
++++++ amqp-1.3.3.tar.gz -> amqp-1.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/Changelog new/amqp-1.4.0/Changelog
--- old/amqp-1.3.3/Changelog 2013-11-11 16:25:08.000000000 +0100
+++ new/amqp-1.4.0/Changelog 2014-01-13 15:50:56.000000000 +0100
@@ -5,6 +5,36 @@
The previous amqplib changelog is here:
http://code.google.com/p/py-amqplib/source/browse/CHANGES
+.. _version-1.4.0:
+
+1.4.0
+:release-date: 2014-01-13 3:00 P.M UTC
+
+- Heartbeat implementation improved (Issue #6).
+
+ The new heartbeat behavior is the same approach as taken by the
+ RabbitMQ java library.
+
+ This also means that clients should preferably call the ``heartbeat_tick``
+ method more frequently (like every second) instead of using the old
+ ``rate`` argument (which is now ignored).
+
+ - Heartbeat interval is negotiated with the server.
+ - Some delay is allowed if the heartbeat is late.
+ - Monotonic time is used to keep track of the heartbeat
+ instead of relying on the caller to call the checking function
+ at the right time.
+
+ Contributed by Dustin J. Mitchell.
+
+- NoneType is now supported in tables and arrays.
+
+ Contributed by Dominik Fässler.
+
+- SSLTransport: Now handles ``ENOENT``.
+
+ Fix contributed by Adrien Guinet.
+
.. _version-1.3.3:
1.3.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/PKG-INFO new/amqp-1.4.0/PKG-INFO
--- old/amqp-1.3.3/PKG-INFO 2013-11-11 16:25:52.000000000 +0100
+++ new/amqp-1.4.0/PKG-INFO 2014-01-13 16:01:08.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: amqp
-Version: 1.3.3
+Version: 1.4.0
Summary: Low-level AMQP client for Python (fork of amqplib)
Home-page: http://github.com/celery/py-amqp
Author: Ask Solem
@@ -10,7 +10,7 @@
Python AMQP 0.9.1 client library
=====================================================================
- :Version: 1.3.3
+ :Version: 1.4.0
:Web: http://amqp.readthedocs.org/
:Download: http://pypi.python.org/pypi/amqp/
:Source: http://github.com/celery/py-amqp/
@@ -107,6 +107,9 @@
http://www.rabbitmq.com/devtools.html#python-dev
+ .. image:: https://d2weczhvl823v0.cloudfront.net/celery/celery/trend.png
+ :alt: Bitdeli badge
+ :target: https://bitdeli.com/free
Platform: any
Classifier: Development Status :: 5 - Production/Stable
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/README.rst new/amqp-1.4.0/README.rst
--- old/amqp-1.3.3/README.rst 2013-11-11 16:24:04.000000000 +0100
+++ new/amqp-1.4.0/README.rst 2014-01-13 15:51:21.000000000 +0100
@@ -2,7 +2,7 @@
Python AMQP 0.9.1 client library
=====================================================================
-:Version: 1.3.3
+:Version: 1.4.0
:Web: http://amqp.readthedocs.org/
:Download: http://pypi.python.org/pypi/amqp/
:Source: http://github.com/celery/py-amqp/
@@ -99,3 +99,6 @@
http://www.rabbitmq.com/devtools.html#python-dev
+.. image:: https://d2weczhvl823v0.cloudfront.net/celery/celery/trend.png
+ :alt: Bitdeli badge
+ :target: https://bitdeli.com/free
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/__init__.py new/amqp-1.4.0/amqp/__init__.py
--- old/amqp-1.3.3/amqp/__init__.py 2013-11-11 16:24:00.000000000 +0100
+++ new/amqp-1.4.0/amqp/__init__.py 2014-01-13 15:51:11.000000000 +0100
@@ -16,7 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
from __future__ import absolute_import
-VERSION = (1, 3, 3)
+VERSION = (1, 4, 0)
__version__ = '.'.join(map(str, VERSION[0:3])) + ''.join(VERSION[3:])
__author__ = 'Barry Pederson'
__maintainer__ = 'Ask Solem'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/abstract_channel.py new/amqp-1.4.0/amqp/abstract_channel.py
--- old/amqp-1.3.3/amqp/abstract_channel.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/amqp/abstract_channel.py 2014-01-13 15:26:01.000000000 +0100
@@ -19,12 +19,6 @@
from .exceptions import AMQPNotImplementedError, RecoverableConnectionError
from .serialization import AMQPWriter
-try:
- bytes
-except NameError:
- # Python 2.5 and lower
- bytes = str
-
__all__ = ['AbstractChannel']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/connection.py new/amqp-1.4.0/amqp/connection.py
--- old/amqp-1.3.3/amqp/connection.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/amqp/connection.py 2014-01-13 15:34:16.000000000 +0100
@@ -34,7 +34,7 @@
ConnectionForced, ConnectionError, error_for_code,
RecoverableConnectionError, RecoverableChannelError,
)
-from .five import items, range, values
+from .five import items, range, values, monotonic
from .method_framing import MethodReader, MethodWriter
from .serialization import AMQPWriter
from .transport import create_transport
@@ -80,9 +80,26 @@
"""
Channel = Channel
+ #: Final heartbeat interval value (in float seconds) after negotiation
+ heartbeat = None
+
+ #: Original heartbeat interval value proposed by client.
+ client_heartbeat = None
+
+ #: Original heartbeat interval proposed by server.
+ server_heartbeat = None
+
+ #: Time of last heartbeat sent (in monotonic time, if available).
+ last_heartbeat_sent = 0
+
+ #: Time of last heartbeat received (in monotonic time, if available).
+ last_heartbeat_received = 0
+
+ #: Number of bytes sent to socket at the last heartbeat check.
prev_sent = None
+
+ #: Number of bytes received from socket at the last heartbeat check.
prev_recv = None
- missed_heartbeats = 0
def __init__(self, host='localhost', userid='guest', password='guest',
login_method='AMQPLAIN', login_response=None,
@@ -125,7 +142,7 @@
# Properties set in the Tune method
self.channel_max = channel_max
self.frame_max = frame_max
- self.heartbeat = heartbeat
+ self.client_heartbeat = heartbeat
self.confirm_publish = confirm_publish
@@ -843,7 +860,14 @@
self.channel_max = args.read_short() or self.channel_max
self.frame_max = args.read_long() or self.frame_max
self.method_writer.frame_max = self.frame_max
- heartbeat = args.read_short() # noqa
+ self.server_heartbeat = args.read_short()
+
+ # negotiate the heartbeat interval to the smaller of the
+ # specified values
+ if self.server_heartbeat == 0 or self.client_heartbeat == 0:
+ self.heartbeat = max(self.server_heartbeat, self.client_heartbeat)
+ else:
+ self.heartbeat = min(self.server_heartbeat, self.client_heartbeat)
self._x_tune_ok(self.channel_max, self.frame_max, self.heartbeat)
@@ -851,28 +875,34 @@
self.transport.write_frame(8, 0, bytes())
def heartbeat_tick(self, rate=2):
- """Verify that hartbeats are sent and received.
-
- :keyword rate: Rate is how often the tick is called
- compared to the actual heartbeat value. E.g. if
- the heartbeat is set to 3 seconds, and the tick
- is called every 3 / 2 seconds, then the rate is 2.
+ """Send heartbeat packets, if necessary, and fail if none have been
+ received recently. This should be called frequently, on the order of
+ once per second.
+ :keyword rate: Ignored
"""
+ if not self.heartbeat:
+ return
+
+ # treat actual data exchange in either direction as a heartbeat
sent_now = self.method_writer.bytes_sent
recv_now = self.method_reader.bytes_recv
+ if self.prev_sent is None or self.prev_sent != sent_now:
+ self.last_heartbeat_sent = monotonic()
+ if self.prev_recv is None or self.prev_recv != recv_now:
+ self.last_heartbeat_received = monotonic()
+ self.prev_sent, self.prev_recv = sent_now, recv_now
- if self.prev_sent is not None and self.prev_sent == sent_now:
+ # send a heartbeat if it's time to do so
+ if monotonic() > self.last_heartbeat_sent + self.heartbeat:
self.send_heartbeat()
+ self.last_heartbeat_sent = monotonic()
- if self.prev_recv is not None and self.prev_recv == recv_now:
- self.missed_heartbeats += 1
- else:
- self.missed_heartbeats = 0
-
- self.prev_sent, self.prev_recv = sent_now, recv_now
-
- if self.missed_heartbeats >= rate:
+ # if we've missed two intervals' heartbeats, fail; this gives the
+ # server enough time to send heartbeats a little late
+ if (self.last_heartbeat_received and
+ self.last_heartbeat_received + 2 *
+ self.heartbeat < monotonic()):
raise ConnectionForced('Too many heartbeats missed')
def _x_tune_ok(self, channel_max, frame_max, heartbeat):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/five.py new/amqp-1.4.0/amqp/five.py
--- old/amqp-1.3.3/amqp/five.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/amqp/five.py 2014-01-13 15:34:29.000000000 +0100
@@ -131,3 +131,58 @@
return Type(Class.__name__, Class.__bases__, attrs)
return _clone_with_metaclass
+
+############## time.monotonic ################################################
+
+if sys.version_info < (3, 3):
+
+ import platform
+ SYSTEM = platform.system()
+
+ if SYSTEM == 'Darwin':
+ import ctypes
+ from ctypes.util import find_library
+ libSystem = ctypes.CDLL('libSystem.dylib')
+ CoreServices = ctypes.CDLL(find_library('CoreServices'),
+ use_errno=True)
+ mach_absolute_time = libSystem.mach_absolute_time
+ mach_absolute_time.restype = ctypes.c_uint64
+ absolute_to_nanoseconds = CoreServices.AbsoluteToNanoseconds
+ absolute_to_nanoseconds.restype = ctypes.c_uint64
+ absolute_to_nanoseconds.argtypes = [ctypes.c_uint64]
+
+ def _monotonic():
+ return absolute_to_nanoseconds(mach_absolute_time()) * 1e-9
+
+ elif SYSTEM == 'Linux':
+ # from stackoverflow:
+ # questions/1205722/how-do-i-get-monotonic-time-durations-in-python
+ import ctypes
+ import os
+
+ CLOCK_MONOTONIC = 1 # see
+
+ class timespec(ctypes.Structure):
+ _fields_ = [
+ ('tv_sec', ctypes.c_long),
+ ('tv_nsec', ctypes.c_long),
+ ]
+
+ librt = ctypes.CDLL('librt.so.1', use_errno=True)
+ clock_gettime = librt.clock_gettime
+ clock_gettime.argtypes = [
+ ctypes.c_int, ctypes.POINTER(timespec),
+ ]
+
+ def _monotonic(): # noqa
+ t = timespec()
+ if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
+ errno_ = ctypes.get_errno()
+ raise OSError(errno_, os.strerror(errno_))
+ return t.tv_sec + t.tv_nsec * 1e-9
+ else:
+ from time import time as _monotonic
+try:
+ from time import monotonic
+except ImportError:
+ monotonic = _monotonic # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/method_framing.py new/amqp-1.4.0/amqp/method_framing.py
--- old/amqp-1.3.3/amqp/method_framing.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/amqp/method_framing.py 2014-01-13 15:26:07.000000000 +0100
@@ -19,12 +19,6 @@
from collections import defaultdict, deque
from struct import pack, unpack
-try:
- bytes
-except NameError:
- # Python 2.5 and lower
- bytes = str
-
from .basic_message import Message
from .exceptions import AMQPError, UnexpectedFrame
from .five import range, string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/serialization.py new/amqp-1.4.0/amqp/serialization.py
--- old/amqp-1.3.3/amqp/serialization.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/amqp/serialization.py 2014-01-13 15:34:38.000000000 +0100
@@ -25,6 +25,7 @@
from datetime import datetime
from decimal import Decimal
+from io import BytesIO
from struct import pack, unpack
from time import mktime
@@ -39,19 +40,6 @@
else:
byte = chr
-try:
- from io import BytesIO
-except ImportError: # Py2.5
- try:
- from cStringIO import StringIO as BytesIO # noqa
- except ImportError:
- from StringIO import StringIO as BytesIO # noqa
-
-try:
- bytes
-except NameError:
- # Python 2.5 and lower
- bytes = str
ILLEGAL_TABLE_TYPE_WITH_KEY = """\
Table type {0!r} for key {1!r} not handled by amqp. [value: {2!r}]
@@ -174,6 +162,8 @@
val = self.read_bit()
elif ftype == 100:
val = self.read_float()
+ elif ftype == 86: # 'V'
+ val = None
else:
raise FrameSyntaxError(
'Unknown value in table: {0!r} ({1!r})'.format(
@@ -357,6 +347,8 @@
elif isinstance(v, (list, tuple)):
self.write(b'A')
self.write_array(v)
+ elif v is None:
+ self.write(b'V')
else:
err = (ILLEGAL_TABLE_TYPE_WITH_KEY.format(type(v), k, v) if k
else ILLEGAL_TABLE_TYPE.format(type(v), v))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/transport.py new/amqp-1.4.0/amqp/transport.py
--- old/amqp-1.3.3/amqp/transport.py 2013-11-11 16:23:01.000000000 +0100
+++ new/amqp-1.4.0/amqp/transport.py 2014-01-13 15:34:57.000000000 +0100
@@ -1,9 +1,3 @@
-"""
-Read/Write AMQP frames over network transports.
-
-2009-01-14 Barry Pederson
-
-"""
# Copyright (C) 2009 Barry Pederson
#
# This library is free software; you can redistribute it and/or
@@ -24,6 +18,7 @@
import errno
import re
import socket
+import ssl
# Jython does not have this attribute
try:
@@ -31,27 +26,12 @@
except ImportError: # pragma: no cover
from socket import IPPROTO_TCP as SOL_TCP # noqa
-#
-# See if Python 2.6+ SSL support is available
-#
-try:
- import ssl
- HAVE_PY26_SSL = True
-except:
- HAVE_PY26_SSL = False
-
-try:
- bytes
-except:
- # Python 2.5 and lower
- bytes = str
-
from struct import pack, unpack
from .exceptions import UnexpectedFrame
from .utils import get_errno, set_cloexec
-_UNAVAIL = errno.EAGAIN, errno.EINTR
+_UNAVAIL = errno.EAGAIN, errno.EINTR, errno.ENOENT
AMQP_PORT = 5672
@@ -200,22 +180,17 @@
super(SSLTransport, self).__init__(host, connect_timeout)
def _setup_transport(self):
- """Wrap the socket in an SSL object, either the
- new Python 2.6 version, or the older Python 2.5 and
- lower version."""
- if HAVE_PY26_SSL:
- if hasattr(self, 'sslopts'):
- self.sock = ssl.wrap_socket(self.sock, **self.sslopts)
- else:
- self.sock = ssl.wrap_socket(self.sock)
- self.sock.do_handshake()
+ """Wrap the socket in an SSL object."""
+ if hasattr(self, 'sslopts'):
+ self.sock = ssl.wrap_socket(self.sock, **self.sslopts)
else:
- self.sock = socket.ssl(self.sock)
+ self.sock = ssl.wrap_socket(self.sock)
+ self.sock.do_handshake()
self._quick_recv = self.sock.read
def _shutdown_transport(self):
"""Unwrap a Python 2.6 SSL socket, so we can call shutdown()"""
- if HAVE_PY26_SSL and self.sock is not None:
+ if self.sock is not None:
try:
unwrap = self.sock.unwrap
except AttributeError:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp/utils.py new/amqp-1.4.0/amqp/utils.py
--- old/amqp-1.3.3/amqp/utils.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/amqp/utils.py 2014-01-13 14:55:09.000000000 +0100
@@ -11,7 +11,8 @@
class promise(object):
if not hasattr(sys, 'pypy_version_info'):
__slots__ = tuple(
- 'fun args kwargs value ready failed on_success on_error'.split()
+ 'fun args kwargs value ready failed '
+ ' on_success on_error calls'.split()
)
def __init__(self, fun, args=(), kwargs=(),
@@ -24,6 +25,7 @@
self.on_success = on_success
self.on_error = on_error
self.value = None
+ self.calls = 0
def __repr__(self):
return '<$: {0.fun.__name__}(*{0.args!r}, **{0.kwargs!r})'.format(
@@ -43,6 +45,7 @@
self.on_success(self.value)
finally:
self.ready = True
+ self.calls += 1
def then(self, callback=None, on_error=None):
self.on_success = callback
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/amqp.egg-info/PKG-INFO new/amqp-1.4.0/amqp.egg-info/PKG-INFO
--- old/amqp-1.3.3/amqp.egg-info/PKG-INFO 2013-11-11 16:25:49.000000000 +0100
+++ new/amqp-1.4.0/amqp.egg-info/PKG-INFO 2014-01-13 16:01:03.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: amqp
-Version: 1.3.3
+Version: 1.4.0
Summary: Low-level AMQP client for Python (fork of amqplib)
Home-page: http://github.com/celery/py-amqp
Author: Ask Solem
@@ -10,7 +10,7 @@
Python AMQP 0.9.1 client library
=====================================================================
- :Version: 1.3.3
+ :Version: 1.4.0
:Web: http://amqp.readthedocs.org/
:Download: http://pypi.python.org/pypi/amqp/
:Source: http://github.com/celery/py-amqp/
@@ -107,6 +107,9 @@
http://www.rabbitmq.com/devtools.html#python-dev
+ .. image:: https://d2weczhvl823v0.cloudfront.net/celery/celery/trend.png
+ :alt: Bitdeli badge
+ :target: https://bitdeli.com/free
Platform: any
Classifier: Development Status :: 5 - Production/Stable
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/demo/amqp_clock.py new/amqp-1.4.0/demo/amqp_clock.py
--- old/amqp-1.3.3/demo/amqp_clock.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/demo/amqp_clock.py 2014-01-13 15:36:30.000000000 +0100
@@ -27,18 +27,23 @@
def main():
parser = OptionParser()
- parser.add_option('--host', dest='host',
- help='AMQP server to connect to (default: %default)',
- default='localhost')
- parser.add_option('-u', '--userid', dest='userid',
+ parser.add_option(
+ '--host', dest='host',
+ help='AMQP server to connect to (default: %default)',
+ default='localhost',
+ )
+ parser.add_option(
+ '-u', '--userid', dest='userid',
help='AMQP userid to authenticate as (default: %default)',
default='guest',
)
- parser.add_option('-p', '--password', dest='password',
+ parser.add_option(
+ '-p', '--password', dest='password',
help='AMQP password to authenticate with (default: %default)',
default='guest',
)
- parser.add_option('--ssl', dest='ssl', action='store_true',
+ parser.add_option(
+ '--ssl', dest='ssl', action='store_true',
help='Enable SSL with AMQP server (default: not enabled)',
default=False,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/demo/demo_receive.py new/amqp-1.4.0/demo/demo_receive.py
--- old/amqp-1.3.3/demo/demo_receive.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/demo/demo_receive.py 2014-01-13 15:36:06.000000000 +0100
@@ -16,14 +16,14 @@
def callback(channel, msg):
for key, val in msg.properties.items():
- print ('%s: %s' % (key, str(val)))
+ print('%s: %s' % (key, str(val)))
for key, val in msg.delivery_info.items():
- print ('> %s: %s' % (key, str(val)))
+ print('> %s: %s' % (key, str(val)))
- print ('')
- print (msg.body)
- print ('-------')
- print msg.delivery_tag
+ print('')
+ print(msg.body)
+ print('-------')
+ print(msg.delivery_tag)
channel.basic_ack(msg.delivery_tag)
#
@@ -35,19 +35,23 @@
def main():
parser = OptionParser()
- parser.add_option('--host', dest='host',
+ parser.add_option(
+ '--host', dest='host',
help='AMQP server to connect to (default: %default)',
default='localhost',
)
- parser.add_option('-u', '--userid', dest='userid',
+ parser.add_option(
+ '-u', '--userid', dest='userid',
help='userid to authenticate as (default: %default)',
default='guest',
)
- parser.add_option('-p', '--password', dest='password',
+ parser.add_option(
+ '-p', '--password', dest='password',
help='password to authenticate with (default: %default)',
default='guest',
)
- parser.add_option('--ssl', dest='ssl', action='store_true',
+ parser.add_option(
+ '--ssl', dest='ssl', action='store_true',
help='Enable SSL (default: not enabled)',
default=False,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/demo/demo_send.py new/amqp-1.4.0/demo/demo_send.py
--- old/amqp-1.3.3/demo/demo_send.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/demo/demo_send.py 2014-01-13 15:35:20.000000000 +0100
@@ -19,19 +19,23 @@
parser = OptionParser(
usage='usage: %prog [options] message\nexample: %prog hello world',
)
- parser.add_option('--host', dest='host',
+ parser.add_option(
+ '--host', dest='host',
help='AMQP server to connect to (default: %default)',
default='localhost',
)
- parser.add_option('-u', '--userid', dest='userid',
+ parser.add_option(
+ '-u', '--userid', dest='userid',
help='userid to authenticate as (default: %default)',
default='guest',
)
- parser.add_option('-p', '--password', dest='password',
+ parser.add_option(
+ '-p', '--password', dest='password',
help='password to authenticate with (default: %default)',
default='guest',
)
- parser.add_option('--ssl', dest='ssl', action='store_true',
+ parser.add_option(
+ '--ssl', dest='ssl', action='store_true',
help='Enable SSL (default: not enabled)',
default=False,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/docs/_ext/applyxrefs.py new/amqp-1.4.0/docs/_ext/applyxrefs.py
--- old/amqp-1.3.3/docs/_ext/applyxrefs.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/docs/_ext/applyxrefs.py 2014-01-13 15:40:23.000000000 +0100
@@ -6,8 +6,8 @@
testing = False
DONT_TOUCH = (
- './index.txt',
- )
+ './index.txt',
+)
def target_name(fn):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/docs/_ext/literals_to_xrefs.py new/amqp-1.4.0/docs/_ext/literals_to_xrefs.py
--- old/amqp-1.3.3/docs/_ext/literals_to_xrefs.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/docs/_ext/literals_to_xrefs.py 2014-01-13 15:41:47.000000000 +0100
@@ -95,8 +95,8 @@
replace_type in ("class", "func", "meth"):
default = default[:-2]
replace_value = raw_input(
- colorize("Text <target> [", fg="yellow") + default + \
- colorize("]: ", fg="yellow")).strip()
+ colorize("Text <target> [", fg="yellow") + default +
+ colorize("]: ", fg="yellow")).strip()
if not replace_value:
replace_value = default
new.append(":%s:`%s`" % (replace_type, replace_value))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/docs/changelog.rst new/amqp-1.4.0/docs/changelog.rst
--- old/amqp-1.3.3/docs/changelog.rst 2013-11-11 16:25:08.000000000 +0100
+++ new/amqp-1.4.0/docs/changelog.rst 2014-01-13 15:50:56.000000000 +0100
@@ -5,6 +5,36 @@
The previous amqplib changelog is here:
http://code.google.com/p/py-amqplib/source/browse/CHANGES
+.. _version-1.4.0:
+
+1.4.0
+:release-date: 2014-01-13 3:00 P.M UTC
+
+- Heartbeat implementation improved (Issue #6).
+
+ The new heartbeat behavior is the same approach as taken by the
+ RabbitMQ java library.
+
+ This also means that clients should preferably call the ``heartbeat_tick``
+ method more frequently (like every second) instead of using the old
+ ``rate`` argument (which is now ignored).
+
+ - Heartbeat interval is negotiated with the server.
+ - Some delay is allowed if the heartbeat is late.
+ - Monotonic time is used to keep track of the heartbeat
+ instead of relying on the caller to call the checking function
+ at the right time.
+
+ Contributed by Dustin J. Mitchell.
+
+- NoneType is now supported in tables and arrays.
+
+ Contributed by Dominik Fässler.
+
+- SSLTransport: Now handles ``ENOENT``.
+
+ Fix contributed by Adrien Guinet.
+
.. _version-1.3.3:
1.3.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/docs/conf.py new/amqp-1.4.0/docs/conf.py
--- old/amqp-1.3.3/docs/conf.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/docs/conf.py 2014-01-13 15:40:14.000000000 +0100
@@ -70,8 +70,8 @@
html_use_index = True
latex_documents = [
- ('index', 'py-amqp.tex', ur'py-amqp Documentation',
- ur'Ask Solem & Contributors', 'manual'),
+ ('index', 'py-amqp.tex', ur'py-amqp Documentation',
+ ur'Ask Solem & Contributors', 'manual'),
]
html_theme = "celery"
@@ -89,7 +89,7 @@
issuetracker_project = "celery/py-amqp"
issuetracker_issue_pattern = r'[Ii]ssue #(\d+)'
-# -- Options for Epub output ---------------------------------------------------
+# -- Options for Epub output ------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = 'py-amqp Manual, Version 1.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/extra/generate_skeleton_0_8.py new/amqp-1.4.0/extra/generate_skeleton_0_8.py
--- old/amqp-1.3.3/extra/generate_skeleton_0_8.py 2012-12-18 17:41:48.000000000 +0100
+++ new/amqp-1.4.0/extra/generate_skeleton_0_8.py 2014-01-13 15:39:36.000000000 +0100
@@ -204,9 +204,10 @@
if 'content' in amqp_method.attrib:
params.append('msg')
- out.write(' def %s(%s):\n' %
- (_fixup_method_name(class_element, amqp_method),
- ', '.join(params + fieldnames)))
+ out.write(' def %s(%s):\n' % (
+ _fixup_method_name(class_element, amqp_method),
+ ', '.join(params + fieldnames)),
+ )
s = generate_docstr(amqp_method, ' ', ' """')
if s:
@@ -231,7 +232,7 @@
if 'synchronous' in amqp_method.attrib:
responses = [x.attrib['name']
- for x in amqp_method.findall('response')]
+ for x in amqp_method.findall('response')]
out.write(' return self.wait(allowed_methods=[\n')
for r in responses:
resp = method_name_map[(class_element.attrib['name'], r)]
@@ -274,7 +275,7 @@
#
for amqp_class in spec.findall('class'):
if (amqp_class.attrib['handler'] == class_element.attrib['name']) and \
- (amqp_class.attrib['name'] != class_element.attrib['name']):
+ (amqp_class.attrib['name'] != class_element.attrib['name']):
out.write(' #############\n')
out.write(' #\n')
out.write(' # %s\n' % amqp_class.attrib['name'].capitalize())
@@ -315,8 +316,8 @@
(
amqp_class.attrib['index'],
amqp_method.attrib['index'],
- amqp_class.attrib['handler'].capitalize() + '.' +
- _fixup_method_name(amqp_class, amqp_method),
+ (amqp_class.attrib['handler'].capitalize() + '.' +
+ _fixup_method_name(amqp_class, amqp_method)),
)
#### Actually generate output
@@ -335,7 +336,7 @@
# for chassis in amqp_method.findall('chassis'):
# print ' ', chassis.attrib
chassis = [x.attrib['name']
- for x in amqp_method.findall('chassis')]
+ for x in amqp_method.findall('chassis')]
if 'client' in chassis:
out.write(" (%s, %s): (%s, %s._%s),\n" % (
amqp_class.attrib['index'],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/funtests/test_channel.py new/amqp-1.4.0/funtests/test_channel.py
--- old/amqp-1.3.3/funtests/test_channel.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/funtests/test_channel.py 2014-01-13 15:33:10.000000000 +0100
@@ -22,15 +22,8 @@
import sys
import unittest
-try:
- bytes
-except NameError:
- # Python 2.5 and lower
- bytes = str
-
import settings
-
from amqp import ChannelError, Connection, Message, FrameSyntaxError
@@ -163,14 +156,19 @@
self.assertTrue(isinstance(msg2.body, bytes))
self.assertEqual(msg2.body, u'hello w\xf6rld'.encode('latin_1'))
- def test_exception(self):
- """
- Check that Channel exceptions are actually raised as Python
- exceptions.
+ def test_queue_delete_empty(self):
+ self.assertFalse(
+ self.ch.queue_delete('bogus_queue_that_does_not_exist')
+ )
- """
+ def test_survives_channel_error(self):
with self.assertRaises(ChannelError):
- self.ch.queue_delete('bogus_queue_that_does_not_exist')
+ self.ch.queue_declare('krjqheewq_bogus', passive=True)
+ self.ch.queue_declare('funtest_survive')
+ self.ch.queue_declare('funtest_survive', passive=True)
+ self.assertEqual(
+ 0, self.ch.queue_delete('funtest_survive'),
+ )
def test_invalid_header(self):
"""
@@ -181,7 +179,7 @@
"""
qname, _, _ = self.ch.queue_declare()
- msg = Message(application_headers={'test': None})
+ msg = Message(application_headers={'test': object()})
self.assertRaises(
FrameSyntaxError, self.ch.basic_publish, msg, routing_key=qname,
@@ -248,10 +246,10 @@
content_type='text/plain',
application_headers={'foo': 7, 'bar': 'baz'})
- self.ch.basic_publish(msg, 'unittest.fanout')
- self.ch.basic_publish(msg, 'unittest.fanout', mandatory=True)
- self.ch.basic_publish(msg, 'unittest.fanout', mandatory=True)
- self.ch.basic_publish(msg, 'unittest.fanout', mandatory=True)
+ self.ch.basic_publish(msg, 'funtest.fanout')
+ self.ch.basic_publish(msg, 'funtest.fanout', mandatory=True)
+ self.ch.basic_publish(msg, 'funtest.fanout', mandatory=True)
+ self.ch.basic_publish(msg, 'funtest.fanout', mandatory=True)
self.ch.close()
#
@@ -264,38 +262,37 @@
Network configuration is as follows (-> is forwards to :
source_exchange -> dest_exchange -> queue
The test checks that once the message is publish to the
- destination exchange(unittest.topic_dest) it is delivered to the queue.
+ destination exchange(funtest.topic_dest) it is delivered to the queue.
"""
test_routing_key = 'unit_test__key'
- dest_exchange = 'unittest.topic_dest_bind'
- source_exchange = 'unittest.topic_source_bind'
+ dest_exchange = 'funtest.topic_dest_bind'
+ source_exchange = 'funtest.topic_source_bind'
self.ch.exchange_declare(dest_exchange, 'topic', auto_delete=True)
self.ch.exchange_declare(source_exchange, 'topic', auto_delete=True)
qname, _, _ = self.ch.queue_declare()
- self.ch.exchange_bind(destination = dest_exchange,
- source = source_exchange,
- routing_key = test_routing_key)
+ self.ch.exchange_bind(destination=dest_exchange,
+ source=source_exchange,
+ routing_key=test_routing_key)
self.ch.queue_bind(qname, dest_exchange,
routing_key=test_routing_key)
- msg = Message('unittest message',
+ msg = Message('funtest message',
content_type='text/plain',
application_headers={'foo': 7, 'bar': 'baz'})
-
self.ch.basic_publish(msg, source_exchange,
- routing_key = test_routing_key)
+ routing_key=test_routing_key)
msg2 = self.ch.basic_get(qname, no_ack=True)
self.assertEqual(msg, msg2)
def test_exchange_unbind(self):
- dest_exchange = 'unittest.topic_dest_unbind'
- source_exchange = 'unittest.topic_source_unbind'
+ dest_exchange = 'funtest.topic_dest_unbind'
+ source_exchange = 'funtest.topic_source_unbind'
test_routing_key = 'unit_test__key'
self.ch.exchange_declare(dest_exchange,
@@ -311,6 +308,7 @@
source=source_exchange,
routing_key=test_routing_key)
+
def main():
suite = unittest.TestLoader().loadTestsFromTestCase(TestChannel)
unittest.TextTestRunner(**settings.test_args).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/funtests/test_serialization.py new/amqp-1.4.0/funtests/test_serialization.py
--- old/amqp-1.3.3/funtests/test_serialization.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/funtests/test_serialization.py 2014-01-13 15:33:25.000000000 +0100
@@ -26,12 +26,6 @@
import sys
import unittest
-try:
- bytes
-except NameError:
- # Python 2.5 and lower
- bytes = str
-
import settings
from amqp.serialization import (
@@ -316,7 +310,7 @@
Check that an un-serializable table entry raises a ValueError
"""
- val = {'test': None}
+ val = {'test': object()}
w = AMQPWriter()
self.assertRaises(FrameSyntaxError, w.write_table, val)
@@ -327,6 +321,7 @@
'baz': 'this is some random string I typed',
'ubaz': u'And something in unicode',
'dday_aniv': datetime(1994, 6, 6),
+ 'nothing': None,
'more': {
'abc': -123,
'def': 'hello world',
@@ -351,26 +346,26 @@
# Array
#
def test_array_from_list(self):
- val = [1, 'foo']
+ val = [1, 'foo', None]
w = AMQPWriter()
w.write_array(val)
s = w.getvalue()
self.assertEqualBinary(
- s, '\x00\x00\x00\x0DI\x00\x00\x00\x01S\x00\x00\x00\x03foo',
+ s, '\x00\x00\x00\x0EI\x00\x00\x00\x01S\x00\x00\x00\x03fooV',
)
r = AMQPReader(s)
self.assertEqual(r.read_array(), val)
def test_array_from_tuple(self):
- val = (1, 'foo')
+ val = (1, 'foo', None)
w = AMQPWriter()
w.write_array(val)
s = w.getvalue()
self.assertEqualBinary(
- s, '\x00\x00\x00\x0DI\x00\x00\x00\x01S\x00\x00\x00\x03foo',
+ s, '\x00\x00\x00\x0EI\x00\x00\x00\x01S\x00\x00\x00\x03fooV',
)
r = AMQPReader(s)
@@ -387,48 +382,6 @@
}
w = AMQPWriter()
- w.write_table(val)
- s = w.getvalue()
-
- r = AMQPReader(s)
- self.assertEqual(r.read_table(), val)
-
- #
- # Array
- #
- def test_array_from_list(self):
- val = [1, 'foo']
- w = AMQPWriter()
- w.write_array(val)
- s = w.getvalue()
-
- self.assertEqualBinary(s, '\x00\x00\x00\x0DI\x00\x00\x00\x01S\x00\x00\x00\x03foo')
-
- r = AMQPReader(s)
- self.assertEqual(r.read_array(), val)
-
- def test_array_from_tuple(self):
- val = (1, 'foo')
- w = AMQPWriter()
- w.write_array(val)
- s = w.getvalue()
-
- self.assertEqualBinary(s, '\x00\x00\x00\x0DI\x00\x00\x00\x01S\x00\x00\x00\x03foo')
-
- r = AMQPReader(s)
- self.assertEqual(r.read_array(), list(val))
-
- def test_table_with_array(self):
- val = {
- 'foo': 7,
- 'bar': Decimal('123345.1234'),
- 'baz': 'this is some random string I typed',
- 'blist': [1,2,3],
- 'nlist': [1, [2,3,4]],
- 'ndictl': {'nfoo': 8, 'nblist': [5,6,7] }
- }
-
- w = AMQPWriter()
w.write_table(val)
s = w.getvalue()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/amqp-1.3.3/setup.py new/amqp-1.4.0/setup.py
--- old/amqp-1.3.3/setup.py 2013-11-10 01:53:13.000000000 +0100
+++ new/amqp-1.4.0/setup.py 2014-01-13 15:42:15.000000000 +0100
@@ -15,8 +15,8 @@
import sys
import codecs
-if sys.version_info < (2, 5):
- raise Exception('amqp requires Python 2.5 or higher.')
+if sys.version_info < (2, 6):
+ raise Exception('amqp requires Python 2.6 or higher.')
NAME = 'amqp'
entrypoints = {}
@@ -35,7 +35,8 @@
Programming Language :: Python :: 3.1
Programming Language :: Python :: 3.2
Programming Language :: Python :: 3.3
- License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+ License :: OSI Approved :: GNU Library or \
+Lesser General Public License (LGPL)
Intended Audience :: Developers
License :: OSI Approved :: BSD License
Operating System :: OS Independent
--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org