Hello community,

here is the log from the commit of package python-kombu for openSUSE:Factory 
checked in at 2015-04-23 08:04:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-kombu (Old)
 and      /work/SRC/openSUSE:Factory/.python-kombu.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-kombu"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-kombu/python-kombu.changes        
2014-11-24 11:09:01.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-kombu.new/python-kombu.changes   
2015-04-23 08:05:00.000000000 +0200
@@ -1,0 +2,26 @@
+Wed Apr 22 13:39:19 UTC 2015 - tbecht...@suse.com
+
+- update to 3.0.25:
+  - pyamqp/librabbitmq now uses 5671 as default port when SSL is enabled
+    (Issue #459).
+  - Redis: Now supports passwords in ``redis+socket://:pass@host:port`` URLs
+    (Issue #460).
+  - ``Producer.publish`` now defines the ``expiration`` property in support
+    of the `RabbitMQ per-message TTL extension`_.
+  - Connection transport attribute now set correctly for all transports.
+  - qpid: Fixed bug where the connectionw as not being closed properly.
+  - :class:`~kombu.entity.bindings` is now JSON serializable (Issue #453).
+  - Fixed typo in error when yaml is not installed (said ``msgpack``).
+  - Redis: Now properly handles ``TimeoutError raised by py-redis.
+  - qpid: Adds additional string to check for when connecting to qpid.
+    When we connect to qpid, we need to ensure that we skip to the next SASL
+    mechanism if the current mechanism fails. Otherwise, we will keep retrying
+    the connection with a non-working mech.
+  - qpid: Handle ``NotFound`` exceptions.
+  - :class:`Queue.__repr__` now makes sure return value is not unicode
+    (Issue #440).
+  - qpid: ``Queue.purge`` incorrectly raised :exc:`AttributeErrror` if the
+    does not exist (Issue #439).
+  - Linux: Now ignores permission errors on epoll unregister.
+
+-------------------------------------------------------------------

Old:
----
  kombu-3.0.24.tar.gz

New:
----
  kombu-3.0.25.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-kombu.spec ++++++
--- /var/tmp/diff_new_pack.CZhid5/_old  2015-04-23 08:05:00.000000000 +0200
+++ /var/tmp/diff_new_pack.CZhid5/_new  2015-04-23 08:05:00.000000000 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-kombu
 #
-# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2015 SUSE LINUX 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-kombu
-Version:        3.0.24
+Version:        3.0.25
 Release:        0
 Summary:        AMQP Messaging Framework for Python
 License:        BSD-3-Clause

++++++ kombu-3.0.24.tar.gz -> kombu-3.0.25.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/AUTHORS new/kombu-3.0.25/AUTHORS
--- old/kombu-3.0.24/AUTHORS    2014-11-18 00:57:06.000000000 +0100
+++ new/kombu-3.0.25/AUTHORS    2015-04-17 15:49:28.000000000 +0200
@@ -8,6 +8,7 @@
 Adam Wentz
 Alex Koshelev <daeva...@gmail.com>
 Alexandre Bourget <alexandre.bour...@savoirfairelinux.com>
+Anastasis Andronidis <anastasi...@yahoo.gr>
 Andrew Watts
 Andrey Antukh <n...@niwi.be>
 Andrii Kostenko <and...@kostenko.name>
@@ -100,6 +101,7 @@
 Sean Bleier <seble...@gmail.com>
 Sean Creeley <sean.cree...@gmail.com>
 Seb Insua <sebastian.in...@saffrondigital.com>
+Sergey Tikhonov <zimb...@gmail.com>
 Shane Caraveo <sh...@caraveo.com>
 Steeve Morin <steeve.mo...@gmail.com>
 Stefan Eletzhofer <s...@nexiles.de>
@@ -120,3 +122,4 @@
 Zhao Xiaohong <mrlua...@gmail.com>
 haridsv
 iSlava <sig.c...@gmail.com>
+markow <mar...@red-sky.pl>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/Changelog new/kombu-3.0.25/Changelog
--- old/kombu-3.0.24/Changelog  2014-11-18 00:57:06.000000000 +0100
+++ new/kombu-3.0.25/Changelog  2015-04-21 16:09:36.000000000 +0200
@@ -4,6 +4,68 @@
  Change history
 ================
 
+.. _version-3.0.25:
+
+3.0.25
+======
+:release-date: 2015-04-21 02:00 P.M UTC
+:releasy-by: Ask Solem
+
+- pyamqp/librabbitmq now uses 5671 as default port when SSL is enabled
+  (Issue #459).
+
+- Redis: Now supports passwords in ``redis+socket://:pass@host:port`` URLs
+  (Issue #460).
+
+- ``Producer.publish`` now defines the ``expiration`` property in support
+  of the `RabbitMQ per-message TTL extension`_.
+
+    Contributed by Anastasis Andronidis.
+
+- Connection transport attribute now set correctly for all transports.
+
+    Contributed by Alex Koshelev.
+
+- qpid: Fixed bug where the connectionw as not being closed properly.
+
+    Contributed by Brian Bouterse.
+
+- :class:`~kombu.entity.bindings` is now JSON serializable (Issue #453).
+
+    Contributed by Sergey Tikhonov.
+
+- Fixed typo in error when yaml is not installed (said ``msgpack``).
+
+    Contributed by Joshua Harlow.
+
+- Redis: Now properly handles ``TimeoutError raised by py-redis.
+
+    Contributed by markow.
+
+- qpid: Adds additional string to check for when connecting to qpid.
+
+    When we connect to qpid, we need to ensure that we skip to the next SASL
+    mechanism if the current mechanism fails. Otherwise, we will keep retrying 
the
+    connection with a non-working mech.
+
+    Contributed by Chris Duryee.
+
+- qpid: Handle ``NotFound`` exceptions.
+
+    Contributed by Brian Bouterse.
+
+- :class:`Queue.__repr__` now makes sure return value is not unicode
+  (Issue #440).
+
+- qpid: ``Queue.purge`` incorrectly raised :exc:`AttributeErrror` if the
+  does not exist (Issue #439).
+
+    Contributed by Brian Bouterse.
+
+- Linux: Now ignores permission errors on epoll unregister.
+
+.. _`RabbitMQ per-message TTL extension`: https://www.rabbitmq.com/ttl.html
+
 .. _version-3.0.24:
 
 3.0.24
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/LICENSE new/kombu-3.0.25/LICENSE
--- old/kombu-3.0.24/LICENSE    2014-07-10 18:50:16.000000000 +0200
+++ new/kombu-3.0.25/LICENSE    2015-04-21 15:53:49.000000000 +0200
@@ -1,3 +1,4 @@
+Copyright (c) 2015 Ask Solem & contributors.  All rights reserved.
 Copyright (c) 2012-2014 GoPivotal, Inc.  All rights reserved.
 Copyright (c) 2009-2012, Ask Solem & contributors.
 All rights reserved.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/PKG-INFO new/kombu-3.0.25/PKG-INFO
--- old/kombu-3.0.24/PKG-INFO   2014-11-18 01:11:14.000000000 +0100
+++ new/kombu-3.0.25/PKG-INFO   2015-04-21 16:26:29.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: kombu
-Version: 3.0.24
+Version: 3.0.25
 Summary: Messaging library for Python
 Home-page: http://kombu.readthedocs.org
 Author: Ask Solem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/docs/changelog.rst 
new/kombu-3.0.25/docs/changelog.rst
--- old/kombu-3.0.24/docs/changelog.rst 2014-11-18 00:57:06.000000000 +0100
+++ new/kombu-3.0.25/docs/changelog.rst 2015-04-21 16:09:36.000000000 +0200
@@ -4,6 +4,68 @@
  Change history
 ================
 
+.. _version-3.0.25:
+
+3.0.25
+======
+:release-date: 2015-04-21 02:00 P.M UTC
+:releasy-by: Ask Solem
+
+- pyamqp/librabbitmq now uses 5671 as default port when SSL is enabled
+  (Issue #459).
+
+- Redis: Now supports passwords in ``redis+socket://:pass@host:port`` URLs
+  (Issue #460).
+
+- ``Producer.publish`` now defines the ``expiration`` property in support
+  of the `RabbitMQ per-message TTL extension`_.
+
+    Contributed by Anastasis Andronidis.
+
+- Connection transport attribute now set correctly for all transports.
+
+    Contributed by Alex Koshelev.
+
+- qpid: Fixed bug where the connectionw as not being closed properly.
+
+    Contributed by Brian Bouterse.
+
+- :class:`~kombu.entity.bindings` is now JSON serializable (Issue #453).
+
+    Contributed by Sergey Tikhonov.
+
+- Fixed typo in error when yaml is not installed (said ``msgpack``).
+
+    Contributed by Joshua Harlow.
+
+- Redis: Now properly handles ``TimeoutError raised by py-redis.
+
+    Contributed by markow.
+
+- qpid: Adds additional string to check for when connecting to qpid.
+
+    When we connect to qpid, we need to ensure that we skip to the next SASL
+    mechanism if the current mechanism fails. Otherwise, we will keep retrying 
the
+    connection with a non-working mech.
+
+    Contributed by Chris Duryee.
+
+- qpid: Handle ``NotFound`` exceptions.
+
+    Contributed by Brian Bouterse.
+
+- :class:`Queue.__repr__` now makes sure return value is not unicode
+  (Issue #440).
+
+- qpid: ``Queue.purge`` incorrectly raised :exc:`AttributeErrror` if the
+  does not exist (Issue #439).
+
+    Contributed by Brian Bouterse.
+
+- Linux: Now ignores permission errors on epoll unregister.
+
+.. _`RabbitMQ per-message TTL extension`: https://www.rabbitmq.com/ttl.html
+
 .. _version-3.0.24:
 
 3.0.24
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/__init__.py 
new/kombu-3.0.25/kombu/__init__.py
--- old/kombu-3.0.24/kombu/__init__.py  2014-11-18 00:57:06.000000000 +0100
+++ new/kombu-3.0.25/kombu/__init__.py  2015-04-21 15:53:16.000000000 +0200
@@ -7,7 +7,7 @@
     'version_info_t', ('major', 'minor', 'micro', 'releaselevel', 'serial'),
 )
 
-VERSION = version_info_t(3, 0, 24, '', '')
+VERSION = version_info_t(3, 0, 25, '', '')
 __version__ = '{0.major}.{0.minor}.{0.micro}{0.releaselevel}'.format(VERSION)
 __author__ = 'Ask Solem'
 __contact__ = 'a...@celeryproject.org'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/connection.py 
new/kombu-3.0.25/kombu/connection.py
--- old/kombu-3.0.24/kombu/connection.py        2014-11-18 00:57:06.000000000 
+0100
+++ new/kombu-3.0.25/kombu/connection.py        2015-04-17 15:49:28.000000000 
+0200
@@ -162,12 +162,12 @@
                 transport = self.uri_prefix = params['transport']
             else:
                 transport = transport or urlparse(hostname).scheme
-                if get_transport_cls(transport).can_parse_url:
-                    # set the transport so that the default is not used.
-                    params['transport'] = transport
-                else:
+                if not get_transport_cls(transport).can_parse_url:
                     # we must parse the URL
                     params.update(parse_url(hostname))
+
+                params['transport'] = transport
+
         self._init_params(**params)
 
         # fallback hosts
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/entity.py 
new/kombu-3.0.25/kombu/entity.py
--- old/kombu-3.0.24/kombu/entity.py    2014-09-30 17:28:50.000000000 +0200
+++ new/kombu-3.0.25/kombu/entity.py    2015-04-17 15:49:42.000000000 +0200
@@ -9,6 +9,7 @@
 
 from .abstract import MaybeChannelBound
 from .exceptions import ContentDisallowed
+from .five import string_t
 from .serialization import prepare_accept_content
 
 TRANSIENT_DELIVERY_MODE = 1
@@ -19,6 +20,13 @@
 __all__ = ['Exchange', 'Queue', 'binding']
 
 
+def _reprstr(s):
+    s = repr(s)
+    if isinstance(s, string_t) and s.startswith("u'"):
+        return s[2:-1]
+    return s[1:-1]
+
+
 def pretty_bindings(bindings):
     return '[%s]' % (', '.join(map(str, bindings)))
 
@@ -284,7 +292,7 @@
         return super(Exchange, self).__repr__(str(self))
 
     def __str__(self):
-        return 'Exchange %s(%s)' % (self.name or repr(''), self.type)
+        return 'Exchange %s(%s)' % (_reprstr(self.name) or repr(''), self.type)
 
     @property
     def can_cache_declaration(self):
@@ -332,7 +340,9 @@
         return '<binding: %s>' % (self, )
 
     def __str__(self):
-        return '%s->%s' % (self.exchange.name, self.routing_key)
+        return '%s->%s' % (
+            _reprstr(self.exchange.name), _reprstr(self.routing_key),
+        )
 
 
 class Queue(MaybeChannelBound):
@@ -663,12 +673,16 @@
     def __repr__(self):
         s = super(Queue, self).__repr__
         if self.bindings:
-            return s('Queue {0.name} -> {bindings}'.format(
-                self, bindings=pretty_bindings(self.bindings),
+            return s('Queue {name} -> {bindings}'.format(
+                name=_reprstr(self.name),
+                bindings=pretty_bindings(self.bindings),
             ))
         return s(
-            'Queue {0.name} -> {0.exchange!r} -> {0.routing_key}'.format(
-                self))
+            'Queue {name} -> {0.exchange!r} -> {routing_key}'.format(
+                self, name=_reprstr(self.name),
+                routing_key=_reprstr(self.routing_key),
+            ),
+        )
 
     @property
     def can_cache_declaration(self):
@@ -716,3 +730,12 @@
                      queue_arguments=q_arguments,
                      binding_arguments=b_arguments,
                      bindings=bindings)
+
+    def as_dict(self, recurse=False):
+        res = super(Queue, self).as_dict(recurse)
+        if not recurse:
+            return res
+        bindings = res.get('bindings')
+        if bindings:
+            res['bindings'] = [b.as_dict(recurse=True) for b in bindings]
+        return res
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/messaging.py 
new/kombu-3.0.25/kombu/messaging.py
--- old/kombu-3.0.24/kombu/messaging.py 2014-09-30 17:28:50.000000000 +0200
+++ new/kombu-3.0.25/kombu/messaging.py 2015-04-17 15:16:01.000000000 +0200
@@ -114,7 +114,7 @@
                 mandatory=False, immediate=False, priority=0,
                 content_type=None, content_encoding=None, serializer=None,
                 headers=None, compression=None, exchange=None, retry=False,
-                retry_policy=None, declare=[], **properties):
+                retry_policy=None, declare=[], expiration=None, **properties):
         """Publish message to the specified exchange.
 
         :param body: Message body.
@@ -138,6 +138,8 @@
             connection is lost.
         :keyword retry_policy: Retry configuration, this is the keywords
             supported by :meth:`~kombu.Connection.ensure`.
+        :keyword expiration: A TTL in seconds can be specified per message.
+            Default is no expiration.
         :keyword \*\*properties: Additional message properties, see AMQP spec.
 
         """
@@ -155,6 +157,8 @@
         if not isinstance(delivery_mode, numbers.Integral):
             delivery_mode = DELIVERY_MODES[delivery_mode]
         properties['delivery_mode'] = delivery_mode
+        if expiration is not None:
+            properties['expiration'] = str(int(expiration*1000))
 
         body, content_type, content_encoding = self._prepare(
             body, serializer, content_type, content_encoding,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/serialization.py 
new/kombu-3.0.25/kombu/serialization.py
--- old/kombu-3.0.24/kombu/serialization.py     2014-11-18 00:57:06.000000000 
+0100
+++ new/kombu-3.0.25/kombu/serialization.py     2015-04-17 15:49:28.000000000 
+0200
@@ -376,7 +376,7 @@
     except (ImportError, ValueError):
 
         def not_available(*args, **kwargs):
-            """In case a client receives a msgpack message, but yaml
+            """In case a client receives a msgpack message, but msgpack
             isn't installed."""
             raise SerializerNotInstalled(
                 'No decoder installed for msgpack. '
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/tests/transport/test_qpid.py 
new/kombu-3.0.25/kombu/tests/transport/test_qpid.py
--- old/kombu-3.0.24/kombu/tests/transport/test_qpid.py 2014-11-18 
00:57:06.000000000 +0100
+++ new/kombu-3.0.25/kombu/tests/transport/test_qpid.py 2015-04-17 
15:50:21.000000000 +0200
@@ -14,15 +14,15 @@
 from mock import call
 
 from kombu.five import Empty, keys, range, monotonic
-from kombu.transport.qpid import AuthenticationFailure, QoS, Message
-from kombu.transport.qpid import QpidMessagingExceptionHandler, Channel
-from kombu.transport.qpid import Connection, ReceiversMonitor, Transport
-from kombu.transport.qpid import ConnectionError
+from kombu.transport.qpid import (AuthenticationFailure, Channel, Connection,
+                                  ConnectionError, Message, NotFound, QoS,
+                                  ReceiversMonitor, Transport)
 from kombu.transport.virtual import Base64
 from kombu.tests.case import Case, Mock, case_no_pypy, case_no_python3
 from kombu.tests.case import patch
 from kombu.utils.compat import OrderedDict
 
+
 QPID_MODULE = 'kombu.transport.qpid'
 
 
@@ -73,8 +73,15 @@
             self.assertEqual(a[key], b[key])
 
 
-class MockException(Exception):
-    pass
+class QpidException(Exception):
+    """
+    An object used to mock Exceptions provided by qpid.messaging.exceptions
+    """
+
+    def __init__(self, code=None, text=None):
+        super(Exception, self).__init__(self)
+        self.code = code
+        self.text = text
 
 
 class BreakOutException(Exception):
@@ -83,44 +90,6 @@
 
 @case_no_python3
 @case_no_pypy
-class TestQpidMessagingExceptionHandler(Case):
-
-    allowed_string = 'object in use'
-    not_allowed_string = 'a different string'
-
-    def setUp(self):
-        """Create a mock ExceptionHandler for testing by this object."""
-        self.handler = QpidMessagingExceptionHandler(self.allowed_string)
-
-    def test_string_stored(self):
-        """Assert that the allowed_exception_string is stored correctly"""
-        handler_string = self.handler.allowed_exception_string
-        self.assertEqual(self.allowed_string, handler_string)
-
-    def test_exception_positive(self):
-        """Assert that an exception is silenced if it contains the
-        allowed_string text."""
-        exception_to_raise = Exception(self.allowed_string)
-
-        def exception_raise_fun():
-            raise exception_to_raise
-        decorated_fun = self.handler(exception_raise_fun)
-        decorated_fun()
-
-    def test_exception_negative(self):
-        """Assert that an exception that does not contain the
-        allowed_string text is properly raised."""
-        exception_to_raise = Exception(self.not_allowed_string)
-
-        def exception_raise_fun():
-            raise exception_to_raise
-        decorated_fun = self.handler(exception_raise_fun)
-        with self.assertRaises(Exception):
-            decorated_fun()
-
-
-@case_no_python3
-@case_no_pypy
 class TestQoS__init__(Case):
 
     def setUp(self):
@@ -328,7 +297,7 @@
 @case_no_pypy
 class TestConnectionInit(ExtraAssertionsMixin, ConnectionTestBase):
 
-    def test_connection__init__stores_connection_options(self):
+    def test_stores_connection_options(self):
         # ensure that only one mech was passed into connection. The other
         # options should all be passed through as-is
         modified_conn_opts = self.connection_options
@@ -337,67 +306,90 @@
             modified_conn_opts, self.conn.connection_options,
         )
 
-    def test_connection__init__variables(self):
+    def test_class_variables(self):
         self.assertIsInstance(self.conn.channels, list)
         self.assertIsInstance(self.conn._callbacks, dict)
 
-    def test_connection__init__establishes_connection(self):
+    def test_establishes_connection(self):
         modified_conn_opts = self.connection_options
         modified_conn_opts['sasl_mechanisms'] = 'PLAIN'
         self.mock_qpid_connection.establish.assert_called_with(
             **modified_conn_opts
         )
 
-    def test_connection__init__saves_established_connection(self):
+    def test_saves_established_connection(self):
         created_conn = self.mock_qpid_connection.establish.return_value
         self.assertIs(self.conn._qpid_conn, created_conn)
 
-    @patch(QPID_MODULE + '.ConnectionError', new=(MockException, ))
+    @patch(QPID_MODULE + '.ConnectionError', new=(QpidException, ))
     @patch(QPID_MODULE + '.sys.exc_info')
     @patch(QPID_MODULE + '.qpid')
-    def test_init_mutates_ConnError_by_message(self, mock_qpid, mock_exc_info):
-        my_conn_error = MockException()
-        my_conn_error.text = 'connection-forced: Authentication failed(320)'
+    def test_mutates_ConnError_by_message(self, mock_qpid, mock_exc_info):
+        text = 'connection-forced: Authentication failed(320)'
+        my_conn_error = QpidException(text=text)
         mock_qpid.messaging.Connection.establish.side_effect = my_conn_error
         mock_exc_info.return_value = 'a', 'b', None
         try:
             self.conn = Connection(**self.connection_options)
         except AuthenticationFailure as error:
             exc_info = sys.exc_info()
-            self.assertNotIsInstance(error, MockException)
+            self.assertNotIsInstance(error, QpidException)
             self.assertIs(exc_info[1], 'b')
             self.assertIsNone(exc_info[2])
         else:
             self.fail('ConnectionError type was not mutated correctly')
 
-    @patch(QPID_MODULE + '.ConnectionError', new=(MockException, ))
+    @patch(QPID_MODULE + '.ConnectionError', new=(QpidException, ))
     @patch(QPID_MODULE + '.sys.exc_info')
     @patch(QPID_MODULE + '.qpid')
-    def test__init_mutates_ConnError_by_code(self, mock_qpid, mock_exc_info):
-        my_conn_error = MockException()
-        my_conn_error.code = 320
-        my_conn_error.text = 'someothertext'
+    def test_mutates_ConnError_by_code(self, mock_qpid, mock_exc_info):
+        my_conn_error = QpidException(code=320, text='someothertext')
         mock_qpid.messaging.Connection.establish.side_effect = my_conn_error
         mock_exc_info.return_value = 'a', 'b', None
         try:
             self.conn = Connection(**self.connection_options)
         except AuthenticationFailure as error:
             exc_info = sys.exc_info()
-            self.assertNotIsInstance(error, MockException)
+            self.assertNotIsInstance(error, QpidException)
             self.assertIs(exc_info[1], 'b')
             self.assertIsNone(exc_info[2])
         else:
             self.fail('ConnectionError type was not mutated correctly')
 
-    @patch(QPID_MODULE + '.ConnectionError', new=(MockException, ))
+    @patch(QPID_MODULE + '.ConnectionError', new=(QpidException, ))
     @patch(QPID_MODULE + '.sys.exc_info')
     @patch(QPID_MODULE + '.qpid')
-    def test_init_unknown_connection_error(self, mock_qpid, mock_exc_info):
+    def test_connection__init__mutates_ConnError_by_message2(self, mock_qpid,
+                                                             mock_exc_info):
+        """
+        Test for PLAIN connection via python-saslwrapper, sans cyrus-sasl-plain
+
+        This test is specific for what is returned when we attempt to connect
+        with PLAIN mech and python-saslwrapper is installed, but
+        cyrus-sasl-plain is not installed.
+        """
+        my_conn_error = QpidException()
+        my_conn_error.text = 'Error in sasl_client_start (-4) SASL(-4): no '\
+                             'mechanism available'
+        mock_qpid.messaging.Connection.establish.side_effect = my_conn_error
+        mock_exc_info.return_value = ('a', 'b', None)
+        try:
+            self.conn = Connection(**self.connection_options)
+        except AuthenticationFailure as error:
+            exc_info = sys.exc_info()
+            self.assertTrue(not isinstance(error, QpidException))
+            self.assertTrue(exc_info[1] is 'b')
+            self.assertTrue(exc_info[2] is None)
+        else:
+            self.fail('ConnectionError type was not mutated correctly')
+
+    @patch(QPID_MODULE + '.ConnectionError', new=(QpidException, ))
+    @patch(QPID_MODULE + '.sys.exc_info')
+    @patch(QPID_MODULE + '.qpid')
+    def test_unknown_connection_error(self, mock_qpid, mock_exc_info):
         # If we get a connection error that we don't understand,
         # bubble it up as-is
-        my_conn_error = MockException()
-        my_conn_error.code = 999
-        my_conn_error.text = 'someothertext'
+        my_conn_error = QpidException(code=999, text='someothertext')
         mock_qpid.messaging.Connection.establish.side_effect = my_conn_error
         mock_exc_info.return_value = 'a', 'b', None
         try:
@@ -407,10 +399,10 @@
         else:
             self.fail('Connection should have thrown an exception')
 
-    @patch.object(Transport, 'channel_errors', new=(MockException, ))
+    @patch.object(Transport, 'channel_errors', new=(QpidException, ))
     @patch(QPID_MODULE + '.qpid')
     @patch(QPID_MODULE + '.ConnectionError', new=IOError)
-    def test_connection__init__non_qpid_error_raises(self, mock_qpid):
+    def test_non_qpid_error_raises(self, mock_qpid):
         mock_Qpid_Connection = mock_qpid.messaging.Connection
         my_conn_error = SyntaxError()
         my_conn_error.text = 'some non auth related error message'
@@ -420,7 +412,7 @@
 
     @patch(QPID_MODULE + '.qpid')
     @patch(QPID_MODULE + '.ConnectionError', new=IOError)
-    def test_connection__init__non_auth_conn_error_raises(self, mock_qpid):
+    def test_non_auth_conn_error_raises(self, mock_qpid):
         mock_Qpid_Connection = mock_qpid.messaging.Connection
         my_conn_error = IOError()
         my_conn_error.text = 'some non auth related error message'
@@ -449,6 +441,16 @@
 
 @case_no_python3
 @case_no_pypy
+class TestConnectionClose(ConnectionTestBase):
+
+    def test_connection_close(self):
+        self.conn._qpid_conn = Mock()
+        self.conn.close()
+        self.conn._qpid_conn.close.assert_called_once_with()
+
+
+@case_no_python3
+@case_no_pypy
 class TestConnectionCloseChannel(ConnectionTestBase):
 
     def setUp(self):
@@ -496,32 +498,37 @@
         super(TestChannelPurge, self).setUp()
         self.mock_queue = Mock()
 
-    def test_channel__purge_gets_queue(self):
+    def test_gets_queue(self):
         self.channel._purge(self.mock_queue)
         getQueue = self.mock_broker_agent.return_value.getQueue
         getQueue.assert_called_once_with(self.mock_queue)
 
-    def test_channel__purge_does_not_call_purge_if_message_count_is_zero(self):
+    def test_does_not_call_purge_if_message_count_is_zero(self):
         values = {'msgDepth': 0}
         queue_obj = self.mock_broker_agent.return_value.getQueue.return_value
         queue_obj.values = values
         self.channel._purge(self.mock_queue)
         self.assertFalse(queue_obj.purge.called)
 
-    def test_channel__purge_purges_all_messages_from_queue(self):
+    def test_purges_all_messages_from_queue(self):
         values = {'msgDepth': 5}
         queue_obj = self.mock_broker_agent.return_value.getQueue.return_value
         queue_obj.values = values
         self.channel._purge(self.mock_queue)
         queue_obj.purge.assert_called_with(5)
 
-    def test_channel__purge_returns_message_count(self):
+    def test_returns_message_count(self):
         values = {'msgDepth': 5}
         queue_obj = self.mock_broker_agent.return_value.getQueue.return_value
         queue_obj.values = values
         result = self.channel._purge(self.mock_queue)
         self.assertEqual(result, 5)
 
+    @patch(QPID_MODULE + '.NotFound', new=QpidException)
+    def test_raises_channel_error_if_queue_does_not_exist(self):
+        self.mock_broker_agent.return_value.getQueue.return_value = None
+        self.assertRaises(QpidException, self.channel._purge, self.mock_queue)
+
 
 @case_no_python3
 @case_no_pypy
@@ -857,38 +864,38 @@
         self.mock__delete.stop()
         super(TestChannelQueueDelete, self).tearDown()
 
-    def test_channel_queue_delete_checks_if_queue_exists(self):
+    def test_checks_if_queue_exists(self):
         self.channel.queue_delete(self.mock_queue)
         self.mock__has_queue.assert_called_once_with(self.mock_queue)
 
-    def test_channel_queue_delete_does_nothing_if_queue_does_not_exist(self):
+    def test_does_nothing_if_queue_does_not_exist(self):
         self.mock__has_queue.return_value = False
         self.channel.queue_delete(self.mock_queue)
         self.assertFalse(self.mock__delete.called)
 
-    def test_channel_queue_delete__not_empty_and_if_empty_True_no_delete(self):
+    def test_not_empty_and_if_empty_True_no_delete(self):
         self.mock__size.return_value = 1
         self.channel.queue_delete(self.mock_queue, if_empty=True)
         mock_broker = self.mock_broker_agent.return_value
         self.assertFalse(mock_broker.getQueue.called)
 
-    def test_channel_queue_delete_calls_get_queue(self):
+    def test_calls_get_queue(self):
         self.channel.queue_delete(self.mock_queue)
         getQueue = self.mock_broker_agent.return_value.getQueue
         getQueue.assert_called_once_with(self.mock_queue)
 
-    def test_channel_queue_delete_gets_queue_attribute(self):
+    def test_gets_queue_attribute(self):
         self.channel.queue_delete(self.mock_queue)
         queue_obj = self.mock_broker_agent.return_value.getQueue.return_value
         queue_obj.getAttributes.assert_called_once_with()
 
-    def test_channel_queue_delete__queue_in_use_and_if_unused_no_delete(self):
+    def test_queue_in_use_and_if_unused_no_delete(self):
         queue_obj = self.mock_broker_agent.return_value.getQueue.return_value
         queue_obj.getAttributes.return_value = {'consumerCount': 1}
         self.channel.queue_delete(self.mock_queue, if_unused=True)
         self.assertFalse(self.mock__delete.called)
 
-    def test_channel_queue_delete_calls__delete_with_queue(self):
+    def test_calls__delete_with_queue(self):
         self.channel.queue_delete(self.mock_queue)
         self.mock__delete.assert_called_once_with(self.mock_queue)
 
@@ -1462,7 +1469,8 @@
             self.monitor.run()
         mock_monitor_receivers.has_calls([call(), call()])
 
-    @patch.object(Transport, 'connection_errors', new=(MockException, ))
+    @patch.object(Transport, 'recoverable_connection_errors',
+                  new=(QpidException, ))
     @patch.object(ReceiversMonitor, 'monitor_receivers')
     @patch(QPID_MODULE + '.time.sleep')
     @patch(QPID_MODULE + '.logger')
@@ -1471,12 +1479,13 @@
     def test_receivers_monitor_exits_when_recoverable_exception_raised(
             self, mock_sys_exc_info, mock_os_write, mock_logger, mock_sleep,
             mock_monitor_receivers):
-        mock_monitor_receivers.side_effect = MockException()
+        mock_monitor_receivers.side_effect = QpidException()
         mock_sleep.side_effect = BreakOutException()
         self.monitor.run()
         self.assertFalse(mock_logger.error.called)
 
-    @patch.object(Transport, 'connection_errors', new=(MockException, ))
+    @patch.object(Transport, 'recoverable_connection_errors',
+                  new=(QpidException, ))
     @patch.object(ReceiversMonitor, 'monitor_receivers')
     @patch(QPID_MODULE + '.time.sleep')
     @patch(QPID_MODULE + '.logger')
@@ -1484,7 +1493,7 @@
     def test_receivers_monitor_saves_exception_when_recoverable_exc_raised(
             self, mock_os_write, mock_logger, mock_sleep,
             mock_monitor_receivers):
-        mock_monitor_receivers.side_effect = MockException()
+        mock_monitor_receivers.side_effect = QpidException()
         mock_sleep.side_effect = BreakOutException()
         self.monitor.run()
         self.assertIs(
@@ -1492,7 +1501,8 @@
             mock_monitor_receivers.side_effect,
         )
 
-    @patch.object(Transport, 'connection_errors', new=(MockException, ))
+    @patch.object(Transport, 'recoverable_connection_errors',
+                  new=(QpidException, ))
     @patch.object(ReceiversMonitor, 'monitor_receivers')
     @patch(QPID_MODULE + '.time.sleep')
     @patch(QPID_MODULE + '.logger')
@@ -1501,7 +1511,7 @@
     def test_receivers_monitor_writes_e_to_pipe_when_recoverable_exc_raised(
             self, mock_sys_exc_info, mock_os_write, mock_logger, mock_sleep,
             mock_monitor_receivers):
-        mock_monitor_receivers.side_effect = MockException()
+        mock_monitor_receivers.side_effect = QpidException()
         mock_sleep.side_effect = BreakOutException()
         self.monitor.run()
         mock_os_write.assert_called_once_with(self.mock_w, 'e')
@@ -1598,8 +1608,8 @@
         return mock_receiver
 
     def test_socket_timeout_raised_when_all_receivers_empty(self):
-        with patch(QPID_MODULE + '.QpidEmpty', new=MockException):
-            self.transport.session.next_receiver.side_effect = MockException()
+        with patch(QPID_MODULE + '.QpidEmpty', new=QpidException):
+            self.transport.session.next_receiver.side_effect = QpidException()
             with self.assertRaises(socket.timeout):
                 self.transport.drain_events(Mock())
 
@@ -1870,11 +1880,20 @@
         self.assertEqual('qpid', Transport.driver_type)
         self.assertEqual('qpid', Transport.driver_name)
 
-    def test_transport_channel_error_contains_qpid_ConnectionError(self):
-        self.assertIn(ConnectionError, Transport.connection_errors)
-
-    def test_transport_channel_error_contains_socket_error(self):
-        self.assertIn(select.error, Transport.connection_errors)
+    def test_transport_verify_recoverable_connection_errors(self):
+        connection_errors = Transport.recoverable_connection_errors
+        self.assertIn(ConnectionError, connection_errors)
+        self.assertIn(select.error, connection_errors)
+
+    def test_transport_verify_recoverable_channel_errors(self):
+        channel_errors = Transport.recoverable_channel_errors
+        self.assertIn(NotFound, channel_errors)
+
+    def test_transport_verify_pre_kombu_3_0_exception_labels(self):
+        self.assertEqual(Transport.recoverable_channel_errors,
+                         Transport.channel_errors)
+        self.assertEqual(Transport.recoverable_connection_errors,
+                         Transport.connection_errors)
 
 
 @case_no_python3
@@ -1951,29 +1970,29 @@
         self.patch_a.stop()
 
     @patch(QPID_MODULE + '.PY3', new=True)
-    def test_verify_runtime_env_raises_exception_for_Python3(self):
+    def test_raises_exception_for_Python3(self):
         with self.assertRaises(RuntimeError):
             self.verify_runtime_environment(self.transport)
 
     @patch('__builtin__.getattr')
-    def test_verify_runtime_env_raises_exc_for_PyPy(self, mock_getattr):
+    def test_raises_exc_for_PyPy(self, mock_getattr):
         mock_getattr.return_value = True
         with self.assertRaises(RuntimeError):
             self.verify_runtime_environment(self.transport)
 
     @patch(QPID_MODULE + '.dependency_is_none')
-    def test_verify_runtime_env_raises_exc_dep_missing(self, mock_dep_is_none):
+    def test_raises_exc_dep_missing(self, mock_dep_is_none):
         mock_dep_is_none.return_value = True
         with self.assertRaises(RuntimeError):
             self.verify_runtime_environment(self.transport)
 
     @patch(QPID_MODULE + '.dependency_is_none')
-    def test_runtime_env_calls_dependency_is_none(self, mock_dep_is_none):
+    def test_calls_dependency_is_none(self, mock_dep_is_none):
         mock_dep_is_none.return_value = False
         self.verify_runtime_environment(self.transport)
         self.assertTrue(mock_dep_is_none.called)
 
-    def test_verify_runtime_env_raises_no_exception(self):
+    def test_raises_no_exception(self):
         self.verify_runtime_environment(self.transport)
 
 
@@ -1987,16 +2006,11 @@
         self.mock_client = Mock()
 
     def test_close_connection(self):
-        """Test that close_connection calls close on each channel in the
-        list of channels on the connection object."""
+        """Test that close_connection calls close on the connection."""
         my_transport = Transport(self.mock_client)
         mock_connection = Mock()
-        mock_channel_1 = Mock()
-        mock_channel_2 = Mock()
-        mock_connection.channels = [mock_channel_1, mock_channel_2]
         my_transport.close_connection(mock_connection)
-        mock_channel_1.close.assert_called_with()
-        mock_channel_2.close.assert_called_with()
+        mock_connection.close.assert_called_once_with()
 
     def test_default_connection_params(self):
         """Test that the default_connection_params are correct"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/transport/librabbitmq.py 
new/kombu-3.0.25/kombu/transport/librabbitmq.py
--- old/kombu-3.0.24/kombu/transport/librabbitmq.py     2014-11-18 
00:57:06.000000000 +0100
+++ new/kombu-3.0.25/kombu/transport/librabbitmq.py     2015-04-17 
15:49:28.000000000 +0200
@@ -27,6 +27,7 @@
     so make sure you are using librabbitmq 1.5 when using rabbitmq > 3.3
 """
 DEFAULT_PORT = 5672
+DEFAULT_SSL_PORT = 5671
 
 NO_SSL_ERROR = """\
 ssl not supported by librabbitmq, please use pyamqp:// or stunnel\
@@ -71,6 +72,8 @@
     Connection = Connection
 
     default_port = DEFAULT_PORT
+    default_ssl_port = DEFAULT_SSL_PORT
+
     connection_errors = (
         base.Transport.connection_errors + (
             ConnectionError, socket.error, IOError, OSError)
@@ -86,6 +89,8 @@
     def __init__(self, client, **kwargs):
         self.client = client
         self.default_port = kwargs.get('default_port') or self.default_port
+        self.default_ssl_port = (kwargs.get('default_ssl_port') or
+                                 self.default_ssl_port)
         self.__reader = None
 
     def driver_version(self):
@@ -161,6 +166,11 @@
 
     @property
     def default_connection_params(self):
-        return {'userid': 'guest', 'password': 'guest',
-                'port': self.default_port,
-                'hostname': 'localhost', 'login_method': 'AMQPLAIN'}
+        return {
+            'userid': 'guest',
+            'password': 'guest',
+            'port': (self.default_ssl_port if self.client.ssl
+                     else self.default_port),
+            'hostname': 'localhost',
+            'login_method': 'AMQPLAIN',
+        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/transport/pyamqp.py 
new/kombu-3.0.25/kombu/transport/pyamqp.py
--- old/kombu-3.0.24/kombu/transport/pyamqp.py  2014-11-18 00:57:06.000000000 
+0100
+++ new/kombu-3.0.25/kombu/transport/pyamqp.py  2015-04-17 15:49:28.000000000 
+0200
@@ -16,6 +16,7 @@
 from . import base
 
 DEFAULT_PORT = 5672
+DEFAULT_SSL_PORT = 5671
 
 
 class Message(base.Message):
@@ -63,6 +64,7 @@
     Connection = Connection
 
     default_port = DEFAULT_PORT
+    default_ssl_port = DEFAULT_SSL_PORT
 
     # it's very annoying that pyamqp sometimes raises AttributeError
     # if the connection is lost, but nothing we can do about that here.
@@ -77,9 +79,11 @@
     supports_heartbeats = True
     supports_ev = True
 
-    def __init__(self, client, default_port=None, **kwargs):
+    def __init__(self, client,
+                 default_port=None, default_ssl_port=None, **kwargs):
         self.client = client
         self.default_port = default_port or self.default_port
+        self.default_ssl_port = default_ssl_port or self.default_ssl_port
 
     def driver_version(self):
         return amqp.__version__
@@ -138,9 +142,14 @@
 
     @property
     def default_connection_params(self):
-        return {'userid': 'guest', 'password': 'guest',
-                'port': self.default_port,
-                'hostname': 'localhost', 'login_method': 'AMQPLAIN'}
+        return {
+            'userid': 'guest',
+            'password': 'guest',
+            'port': (self.default_ssl_port if self.client.ssl
+                     else self.default_port),
+            'hostname': 'localhost',
+            'login_method': 'AMQPLAIN',
+        }
 
     def get_manager(self, *args, **kwargs):
         return get_manager(self.client, *args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/transport/qpid.py 
new/kombu-3.0.25/kombu/transport/qpid.py
--- old/kombu-3.0.24/kombu/transport/qpid.py    2014-11-18 00:57:06.000000000 
+0100
+++ new/kombu-3.0.25/kombu/transport/qpid.py    2015-04-17 15:49:28.000000000 
+0200
@@ -51,10 +51,11 @@
     qpidtoollibs = None     # noqa
 
 try:
-    from qpid.messaging.exceptions import ConnectionError
+    from qpid.messaging.exceptions import ConnectionError, NotFound
     from qpid.messaging.exceptions import Empty as QpidEmpty
 except ImportError:  # pragma: no cover
     ConnectionError = None
+    NotFound = None
     QpidEmpty = None
 
 try:
@@ -98,59 +99,6 @@
     pass
 
 
-class QpidMessagingExceptionHandler(object):
-    """An exception handling decorator that silences some exceptions.
-
-    An exception handling class designed to silence specific exceptions
-    that qpid.messaging raises as part of normal operation. qpid.messaging
-    exceptions require string parsing, and are not machine consumable.
-    This is designed to be used as a decorator, and accepts a whitelist
-    string as an argument.
-
-    Usage:
-    @QpidMessagingExceptionHandler('whitelist string goes here')
-
-    """
-
-    def __init__(self, allowed_exception_string):
-        """Instantiate a QpidMessagingExceptionHandler object.
-
-        :param allowed_exception_string: a string that, if present in the
-            exception message, will be silenced.
-        :type allowed_exception_string: str
-
-        """
-        self.allowed_exception_string = allowed_exception_string
-
-    def __call__(self, original_fun):
-        """The decorator method.
-
-        Method that wraps the actual function with exception silencing
-        functionality. Any exception that contains the string
-        self.allowed_exception_string in the message will be silenced.
-
-        :param original_fun: function that is automatically passed in
-        when this object is used as a decorator.
-        :type original_fun: function
-
-        :return: A function that decorates (wraps) the original function.
-        :rtype: function
-        """
-
-        def decorator(*args, **kwargs):
-            """A runtime-built function that will be returned which contains
-            a reference to the original function, and wraps a call to it in
-            a try/except block that can silence errors.
-            """
-            try:
-                return original_fun(*args, **kwargs)
-            except Exception as exc:
-                if self.allowed_exception_string not in str(exc):
-                    raise
-
-        return decorator
-
-
 class QoS(object):
     """A helper object for message prefetch and ACKing purposes.
 
@@ -417,6 +365,8 @@
 
         :return: The received message.
         :rtype: :class:`qpid.messaging.Message`
+        :raises: :class:`qpid.messaging.exceptions.Empty` if no
+                 message is available.
         """
         rx = self.transport.session.receiver(queue)
         try:
@@ -479,11 +429,14 @@
         """Purge all undelivered messages from a queue specified by name.
 
         An internal method to purge all undelivered messages from a queue
-        specified by name. The queue message depth is first checked,
-        and then the broker is asked to purge that number of messages. The
-        integer number of messages requested to be purged is returned. The
-        actual number of messages purged may be different than the
-        requested number of messages to purge (see below).
+        specified by name. If the queue does not exist a
+        :class:`qpid.messaging.exceptions.NotFound` exception is raised.
+
+        The queue message depth is first checked, and then the broker is
+        asked to purge that number of messages. The integer number of
+        messages requested to be purged is returned. The actual number of
+        messages purged may be different than the requested number of
+        messages to purge (see below).
 
         Sometimes delivered messages are asked to be purged, but are not.
         This case fails silently, which is the correct behavior when a
@@ -501,8 +454,14 @@
 
         :return: The number of messages requested to be purged.
         :rtype: int
+
+        :raises: :class:`qpid.messaging.exceptions.NotFound` if the queue
+                 being purged cannot be found.
         """
         queue_to_purge = self._broker.getQueue(queue)
+        if queue_to_purge is None:
+            error_text = "NOT_FOUND - no queue '{0}'".format(queue)
+            raise NotFound(code=404, text=error_text)
         message_count = queue_to_purge.values['msgDepth']
         if message_count > 0:
             queue_to_purge.purge(message_count)
@@ -677,7 +636,6 @@
                 return
             self._delete(queue)
 
-    @QpidMessagingExceptionHandler(OBJECT_ALREADY_EXISTS_STRING)
     def exchange_declare(self, exchange='', type='direct', durable=False,
                          **kwargs):
         """Create a new exchange.
@@ -704,7 +662,11 @@
         :type durable: bool
         """
         options = {'durable': durable}
-        self._broker.addExchange(type, exchange, options)
+        try:
+            self._broker.addExchange(type, exchange, options)
+        except Exception as exc:
+            if OBJECT_ALREADY_EXISTS_STRING not in str(exc):
+                raise exc
 
     def exchange_delete(self, exchange_name, **kwargs):
         """Delete an exchange specified by name
@@ -757,12 +719,12 @@
     def queue_purge(self, queue, **kwargs):
         """Remove all undelivered messages from queue.
 
-        Purge all undelivered messages from a queue specified by name. The
-        queue message depth is first checked, and then the broker is asked
-        to purge that number of messages. The integer number of messages
-        requested to be purged is returned. The actual number of messages
-        purged may be different than the requested number of messages to
-        purge.
+        Purge all undelivered messages from a queue specified by name. If the
+        queue does not exist an exception is raised. The queue message
+        depth is first checked, and then the broker is asked to purge that
+        number of messages. The integer number of messages requested to be
+        purged is returned. The actual number of messages purged may be
+        different than the requested number of messages to purge.
 
         Sometimes delivered messages are asked to be purged, but are not.
         This case fails silently, which is the correct behavior when a
@@ -780,6 +742,9 @@
 
         :return: The number of messages requested to be purged.
         :rtype: int
+
+        :raises: :class:`qpid.messaging.exceptions.NotFound` if the queue
+                 being purged cannot be found.
         """
         return self._purge(queue)
 
@@ -963,7 +928,7 @@
             self.connection._callbacks.pop(queue, None)
 
     def close(self):
-        """Close Channel and all associated messages.
+        """Cancel all associated messages and close the Channel.
 
         This cancels all consumers by calling :meth:`basic_cancel` for each
         known consumer_tag. It also closes the self._broker sessions. Closing
@@ -1271,14 +1236,20 @@
                 )
                 break
             except ConnectionError as conn_exc:
+                # if we get one of these errors, do not raise an exception.
+                # Raising will cause the connection to be retried. Instead,
+                # just continue on to the next mech.
                 coded_as_auth_failure = getattr(conn_exc, 'code', None) == 320
                 contains_auth_fail_text = \
                     'Authentication failed' in conn_exc.text
                 contains_mech_fail_text = \
                     'sasl negotiation failed: no mechanism agreed' \
                     in conn_exc.text
+                contains_mech_unavail_text = 'no mechanism available' \
+                    in conn_exc.text
                 if coded_as_auth_failure or \
-                        contains_auth_fail_text or contains_mech_fail_text:
+                        contains_auth_fail_text or contains_mech_fail_text or \
+                        contains_mech_unavail_text:
                     logger.debug(
                         'Unable to connect to qpid with SASL mechanism %s',
                         sasl_mech,
@@ -1301,6 +1272,14 @@
         """
         return self._qpid_conn
 
+    def close(self):
+        """Close the connection
+
+        Closing the connection will close all associated session, senders, or
+        receivers used by the Connection.
+        """
+        self._qpid_conn.close()
+
     def close_channel(self, channel):
         """Close a Channel.
 
@@ -1332,9 +1311,7 @@
     session.next_receiver() forever.
 
     The entry point of the thread is :meth:`run` which calls
-    :meth:`monitor_receivers` and catches and logs all exceptions raised.
-    After an exception is logged, the method sleeps for 10 seconds, and
-    re-enters :meth:`monitor_receivers`
+    :meth:`monitor_receivers`.
 
     The thread is designed to be daemonized, and will be forcefully killed
     when all non-daemon threads have already exited.
@@ -1357,27 +1334,20 @@
     def run(self):
         """Thread entry point for ReceiversMonitor
 
-        Calls :meth:`monitor_receivers` with a log-and-reenter behavior. This
-        guards against unexpected exceptions which could cause this thread to
-        exit unexpectedly.
-
-        If a recoverable error occurs, then the exception needs to be
-        propagated to the Main Thread where an exception handler can properly
-        handle it. An Exception is checked if it is recoverable, and if so,
-        it is stored as saved_exception on the self._session object. The
-        character 'e' is then written to the self.w_fd file descriptor
-        causing Main Thread to raise the saved exception. Once the Exception
-        info is saved and the file descriptor is written, this Thread
-        gracefully exits.
-
-        Typically recoverable errors are connection errors, and can be
-        recovered through a call to Transport.establish_connection which will
-        spawn a new ReceiversMonitor Thread.
+        Calls :meth:`monitor_receivers` with a log-and-reenter behavior for
+        non connection errors. This guards against unexpected exceptions
+        which could cause this thread to exit unexpectedly.
+
+        If a connection error occurs, the exception needs to be propagated
+        to MainThread where the kombu exception handler can properly handle
+        it. The exception is stored as saved_exception on the self._session
+        object. The character 'e' is then written to the self.w_fd file
+        descriptor and then this thread exits.
         """
         while True:
             try:
                 self.monitor_receivers()
-            except Transport.connection_errors as exc:
+            except Transport.recoverable_connection_errors as exc:
                 self._session.saved_exception = exc
                 os.write(self._w_fd, 'e')
                 break
@@ -1418,12 +1388,17 @@
     The Transport can create :class:`Channel` objects to communicate with the
     broker with using the :meth:`create_channel` method.
 
-    The Transport identifies recoverable errors, allowing for error recovery
-    when certain exceptions occur. These exception types are stored in the
-    Transport class attribute connection_errors. This adds support for Kombu
-    to retry an operation if a ConnectionError occurs. ConnectionErrors occur
-    when the Transport cannot communicate with the Qpid broker.
-
+    The Transport identifies recoverable connection errors and recoverable
+    channel errors according to the Kombu 3.0 interface. These exception are
+    listed as tuples and store in the Transport class attribute
+    `recoverable_connection_errors` and `recoverable_channel_errors`
+    respectively. Any exception raised that is not a member of one of these
+    tuples is considered non-recoverable. This allows Kombu support for
+    automatic retry of certain operations to function correctly.
+
+    For backwards compatibility to the pre Kombu 3.0 exception interface, the
+    recoverable errors are also listed as `connection_errors` and
+    `channel_errors`.
     """
 
     # Reference to the class that should be used as the Connection object
@@ -1442,11 +1417,25 @@
     driver_type = 'qpid'
     driver_name = 'qpid'
 
-    connection_errors = (
+    # Exceptions that can be recovered from, but where the connection must be
+    # closed and re-established first.
+    recoverable_connection_errors = (
         ConnectionError,
-        select.error
+        select.error,
+    )
+
+    # Exceptions that can be automatically recovered from without
+    # re-establishing the connection.
+    recoverable_channel_errors = (
+        NotFound,
     )
 
+    # Support the pre 3.0 Kombu exception labeling interface which treats
+    # connection_errors and channel_errors both as recoverable via a
+    # reconnect.
+    connection_errors = recoverable_connection_errors
+    channel_errors = recoverable_channel_errors
+
     def __init__(self, *args, **kwargs):
         """Instantiate a Transport object.
 
@@ -1509,10 +1498,10 @@
         ensuring that an accidental call to this method when no more messages
         will arrive will not cause indefinite blocking.
 
-        If the self.r file descriptor returns the character 'e', a
-        recoverable error occurred in the background thread, and this thread
-        should raise the saved exception. The exception is stored as
-        saved_exception on the session object.
+        If the self.r file descriptor receives the character 'e', an error
+        occurred in the background thread, and this thread should raise the
+        saved exception. The exception is stored as saved_exception on the
+        session object.
 
         Nothing is expected to be returned from :meth:`drain_events` because
         :meth:`drain_events` handles messages by calling callbacks that are
@@ -1639,18 +1628,13 @@
         return conn
 
     def close_connection(self, connection):
-        """Close the :class:`Connection` object, and all associated
-        :class:`Channel` objects.
-
-        Iterates through all :class:`Channel` objects associated with the
-        :class:`Connection`, pops them from the list of channels, and calls
-        :meth:Channel.close` on each.
+        """
+        Close the :class:`Connection` object.
 
-        :param connection: The Connection that should be closed
-        :type connection: Connection
+        :param connection: The Connection that should be closed.
+        :type connection: :class:`kombu.transport.qpid.Connection`
         """
-        for channel in connection.channels:
-                channel.close()
+        connection.close()
 
     def drain_events(self, connection, timeout=0, **kwargs):
         """Handle and call callbacks for all ready Transport messages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/transport/redis.py 
new/kombu-3.0.25/kombu/transport/redis.py
--- old/kombu-3.0.24/kombu/transport/redis.py   2014-11-18 00:57:06.000000000 
+0100
+++ new/kombu-3.0.25/kombu/transport/redis.py   2015-04-17 15:49:28.000000000 
+0200
@@ -88,7 +88,8 @@
             IOError,
             OSError,
             exceptions.ConnectionError,
-            exceptions.AuthenticationError)),
+            exceptions.AuthenticationError,
+            exceptions.TimeoutError)),
         (virtual.Transport.channel_errors + (
             DataError,
             exceptions.InvalidResponse,
@@ -781,11 +782,12 @@
                       'socket_timeout': self.socket_timeout}
         host = connparams['host']
         if '://' in host:
-            scheme, _, _, _, _, path, query = _parse_url(host)
+            scheme, _, _, _, password, path, query = _parse_url(host)
             if scheme == 'socket':
                 connparams.update({
                     'connection_class': redis.UnixDomainSocketConnection,
-                    'path': '/' + path}, **query)
+                    'path': '/' + path,
+                    'password': password}, **query)
             connparams.pop('host', None)
             connparams.pop('port', None)
         connparams['db'] = self._prepare_virtual_host(
@@ -795,7 +797,7 @@
         connection_cls = (
             connparams.get('connection_class') or
             redis.Connection
-            )
+        )
 
         class Connection(connection_cls):
             def disconnect(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu/utils/eventio.py 
new/kombu-3.0.25/kombu/utils/eventio.py
--- old/kombu-3.0.24/kombu/utils/eventio.py     2014-11-18 00:57:06.000000000 
+0100
+++ new/kombu-3.0.25/kombu/utils/eventio.py     2015-04-17 15:49:28.000000000 
+0200
@@ -86,7 +86,7 @@
         except (socket.error, ValueError, KeyError, TypeError):
             pass
         except (IOError, OSError) as exc:
-            if get_errno(exc) != errno.ENOENT:
+            if get_errno(exc) not in (errno.ENOENT, errno.EPERM):
                 raise
 
     def _poll(self, timeout):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kombu-3.0.24/kombu.egg-info/PKG-INFO 
new/kombu-3.0.25/kombu.egg-info/PKG-INFO
--- old/kombu-3.0.24/kombu.egg-info/PKG-INFO    2014-11-18 01:11:10.000000000 
+0100
+++ new/kombu-3.0.25/kombu.egg-info/PKG-INFO    2015-04-21 16:26:22.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: kombu
-Version: 3.0.24
+Version: 3.0.25
 Summary: Messaging library for Python
 Home-page: http://kombu.readthedocs.org
 Author: Ask Solem


Reply via email to