Skip to content
Browse files

[bug 785856] Upgrade celery to v3.0.24.

* Updates celery to v3.0.24
* Updates django-celery to v3.0.23 (there is no v3.0.24 for django-celery)
* Adds amqp v1.4.2 replacing amqplib v1.0.2
* Small code changes to match the new API for celery
* Migration that adds missing tables for celery
  • Loading branch information...
1 parent e1cc7d3 commit f1f14c69846d22d81d4dcae2d4214eef05dee303 @rlr rlr committed
Showing with 5,794 additions and 3,026 deletions.
  1. +2 −2 kitsune/announcements/tasks.py
  2. +2 −2 kitsune/customercare/tasks.py
  3. +3 −3 kitsune/kadmin/admin.py
  4. +3 −3 kitsune/karma/actions.py
  5. +7 −7 kitsune/karma/tasks.py
  6. +2 −2 kitsune/kbadge/tasks.py
  7. +8 −5 kitsune/log_settings.py
  8. +2 −2 kitsune/messages/tasks.py
  9. +4 −4 kitsune/questions/tasks.py
  10. +5 −5 kitsune/search/tasks.py
  11. +1 −0 kitsune/settings.py
  12. +1 −1 kitsune/upload/tasks.py
  13. +6 −7 kitsune/wiki/tasks.py
  14. +4 −5 kitsune/wiki/tests/test_tasks.py
  15. +20 −0 migrations/235-add-missing-djcelery-tables.sql
  16. +1 −1 vendor/kitsune.pth
  17. +412 −0 vendor/packages/amqp/Changelog
  18. 0 vendor/packages/{amqplib → amqp}/LICENSE
  19. +6 −0 vendor/packages/amqp/MANIFEST.in
  20. +128 −0 vendor/packages/amqp/PKG-INFO
  21. +104 −0 vendor/packages/amqp/README.rst
  22. +128 −0 vendor/packages/amqp/amqp.egg-info/PKG-INFO
  23. +68 −0 vendor/packages/amqp/amqp.egg-info/SOURCES.txt
  24. 0 vendor/packages/{amqplib/pip-egg-info/amqplib.egg-info → amqp/amqp.egg-info}/dependency_links.txt
  25. 0 vendor/packages/{amqplib/amqplib/__init__.py → amqp/amqp.egg-info/not-zip-safe}
  26. +1 −0 vendor/packages/amqp/amqp.egg-info/top_level.txt
  27. +70 −0 vendor/packages/amqp/amqp/__init__.py
  28. +29 −60 vendor/packages/{amqplib/amqplib/client_0_8 → amqp/amqp}/abstract_channel.py
  29. +20 −28 vendor/packages/{amqplib/amqplib/client_0_8 → amqp/amqp}/basic_message.py
  30. +471 −628 vendor/packages/{amqplib/amqplib/client_0_8 → amqp/amqp}/channel.py
  31. +399 −237 vendor/packages/{amqplib/amqplib/client_0_8 → amqp/amqp}/connection.py
  32. +258 −0 vendor/packages/amqp/amqp/exceptions.py
  33. +188 −0 vendor/packages/amqp/amqp/five.py
  34. +80 −110 vendor/packages/{amqplib/amqplib/client_0_8 → amqp/amqp}/method_framing.py
  35. +13 −0 vendor/packages/amqp/amqp/protocol.py
  36. +189 −257 vendor/packages/{amqplib/amqplib/client_0_8 → amqp/amqp}/serialization.py
  37. +275 −0 vendor/packages/amqp/amqp/transport.py
  38. +102 −0 vendor/packages/amqp/amqp/utils.py
  39. +23 −15 vendor/packages/{amqplib → amqp}/demo/amqp_clock.py
  40. +83 −0 vendor/packages/amqp/demo/demo_receive.py
  41. +66 −0 vendor/packages/amqp/demo/demo_send.py
  42. 0 vendor/packages/amqp/docs/.static/.keep
  43. +4 −0 vendor/packages/amqp/docs/.templates/page.html
  44. +4 −0 vendor/packages/amqp/docs/.templates/sidebarintro.html
  45. +3 −0 vendor/packages/amqp/docs/.templates/sidebarlogo.html
  46. +81 −0 vendor/packages/amqp/docs/Makefile
  47. +92 −0 vendor/packages/amqp/docs/_ext/applyxrefs.py
  48. +173 −0 vendor/packages/amqp/docs/_ext/literals_to_xrefs.py
  49. +401 −0 vendor/packages/amqp/docs/_theme/celery/static/celery.css_t
  50. +5 −0 vendor/packages/amqp/docs/_theme/celery/theme.conf
  51. +412 −0 vendor/packages/amqp/docs/changelog.rst
  52. +127 −0 vendor/packages/amqp/docs/conf.py
  53. +96 −0 vendor/packages/amqp/docs/includes/intro.txt
  54. +22 −0 vendor/packages/amqp/docs/index.rst
  55. +11 −0 vendor/packages/amqp/docs/reference/amqp.abstract_channel.rst
  56. +11 −0 vendor/packages/amqp/docs/reference/amqp.basic_message.rst
  57. +11 −0 vendor/packages/amqp/docs/reference/amqp.channel.rst
  58. +11 −0 vendor/packages/amqp/docs/reference/amqp.connection.rst
  59. +11 −0 vendor/packages/amqp/docs/reference/amqp.exceptions.rst
  60. +11 −0 vendor/packages/amqp/docs/reference/amqp.five.rst
  61. +11 −0 vendor/packages/amqp/docs/reference/amqp.method_framing.rst
  62. +11 −0 vendor/packages/amqp/docs/reference/amqp.protocol.rst
  63. +11 −0 vendor/packages/amqp/docs/reference/amqp.serialization.rst
  64. +11 −0 vendor/packages/amqp/docs/reference/amqp.transport.rst
  65. +11 −0 vendor/packages/amqp/docs/reference/amqp.utils.rst
  66. +23 −0 vendor/packages/amqp/docs/reference/index.rst
  67. +5 −0 vendor/packages/amqp/docs/templates/readme.txt
  68. 0 vendor/packages/{amqplib/extras → amqp/extra}/README
  69. +68 −31 vendor/packages/{amqplib/extras → amqp/extra}/generate_skeleton_0_8.py
  70. +181 −0 vendor/packages/amqp/extra/release/bump_version.py
  71. +75 −0 vendor/packages/amqp/extra/release/sphinx-to-rst.py
  72. +76 −0 vendor/packages/amqp/extra/update_comments_from_spec.py
  73. +8 −13 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/run_all.py
  74. +44 −25 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/settings.py
  75. +32 −27 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/test_basic_message.py
  76. +103 −70 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/test_channel.py
  77. +12 −21 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/test_connection.py
  78. +10 −8 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/test_exceptions.py
  79. +79 −38 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/test_serialization.py
  80. +8 −7 vendor/packages/{amqplib/tests/client_0_8 → amqp/funtests}/test_with.py
  81. +128 −0 vendor/packages/amqp/pip-egg-info/amqp.egg-info/PKG-INFO
  82. +68 −0 vendor/packages/amqp/pip-egg-info/amqp.egg-info/SOURCES.txt
  83. 0 vendor/packages/{amqplib/amqplib.egg-info → amqp/pip-egg-info/amqp.egg-info}/dependency_links.txt
  84. +1 −0 vendor/packages/amqp/pip-egg-info/amqp.egg-info/not-zip-safe
  85. +1 −0 vendor/packages/amqp/pip-egg-info/amqp.egg-info/top_level.txt
  86. +2 −0 vendor/packages/amqp/requirements/docs.txt
  87. +5 −0 vendor/packages/amqp/requirements/pkgutils.txt
  88. +5 −0 vendor/packages/amqp/requirements/test.txt
  89. 0 vendor/packages/{amqplib → amqp}/setup.cfg
  90. +132 −0 vendor/packages/amqp/setup.py
  91. +0 −177 vendor/packages/amqplib/CHANGES
  92. +0 −5 vendor/packages/amqplib/INSTALL
  93. +0 −5 vendor/packages/amqplib/MANIFEST.in
  94. +0 −22 vendor/packages/amqplib/PKG-INFO
  95. +0 −10 vendor/packages/amqplib/README
  96. +0 −12 vendor/packages/amqplib/TODO
  97. +0 −22 vendor/packages/amqplib/amqplib.egg-info/PKG-INFO
  98. +0 −37 vendor/packages/amqplib/amqplib.egg-info/SOURCES.txt
  99. +0 −1 vendor/packages/amqplib/amqplib.egg-info/top_level.txt
  100. +0 −36 vendor/packages/amqplib/amqplib/client_0_8/__init__.py
  101. +0 −105 vendor/packages/amqplib/amqplib/client_0_8/exceptions.py
  102. +0 −281 vendor/packages/amqplib/amqplib/client_0_8/transport.py
  103. +0 −71 vendor/packages/amqplib/demo/demo_receive.py
  104. +0 −56 vendor/packages/amqplib/demo/demo_send.py
  105. +0 −55 vendor/packages/amqplib/docs/code_layout.txt
  106. +0 −225 vendor/packages/amqplib/docs/overview.txt
  107. +0 −5 vendor/packages/amqplib/pip-delete-this-directory.txt
  108. +0 −22 vendor/packages/amqplib/pip-egg-info/amqplib.egg-info/PKG-INFO
  109. +0 −37 vendor/packages/amqplib/pip-egg-info/amqplib.egg-info/SOURCES.txt
  110. +0 −1 vendor/packages/amqplib/pip-egg-info/amqplib.egg-info/top_level.txt
  111. +0 −48 vendor/packages/amqplib/setup.py
  112. +0 −166 vendor/packages/amqplib/tests/client_0_8/fake_redirect.py
  113. +1 −1 vendor/src/celery
  114. +1 −1 vendor/src/django-celery
  115. +1 −1 vendor/src/kombu
View
4 kitsune/announcements/tasks.py
@@ -3,14 +3,14 @@
from django.contrib.sites.models import Site
import bleach
-from celery.task import task
+from celery import task
from tower import ugettext as _
from kitsune.announcements.models import Announcement
from kitsune.sumo.email_utils import make_mail, safe_translation, send_messages
-@task
+@task()
def send_group_email(announcement_id):
"""Build and send the announcement emails to a group."""
try:
View
4 kitsune/customercare/tasks.py
@@ -1,12 +1,12 @@
from datetime import date
-from celery.task import task
+from celery import task
from kitsune.customercare.models import Reply
from kitsune.kbadge.utils import get_or_create_badge
-@task
+@task()
def maybe_award_badge(badge_template, year, user):
"""Award the specific badge to the user if they've earned it."""
badge = get_or_create_badge(badge_template, year)
View
6 kitsune/kadmin/admin.py
@@ -9,8 +9,8 @@
from django.template import RequestContext
from django.views import debug
-import celery.conf
import jinja2
+from celery import current_app
from redis import ConnectionError
from kitsune.sumo.redis_utils import redis_client
@@ -34,9 +34,9 @@ def settings(request):
def celery_settings(request):
"""Admin view that displays the celery configuration."""
capital = re.compile('^[A-Z]')
- settings = [key for key in dir(celery.conf) if capital.match(key)]
+ settings = [key for key in dir(current_app.conf) if capital.match(key)]
sorted_settings = [{'key': key, 'value': '*****' if 'password' in
- key.lower() else getattr(celery.conf, key)} for
+ key.lower() else getattr(current_app.conf, key)} for
key in sorted(settings)]
return render_to_response('kadmin/settings.html',
View
6 kitsune/karma/actions.py
@@ -2,7 +2,7 @@
from django.contrib.auth.models import User
-from celery.task import task
+from celery import task
from statsd import statsd
import waffle
@@ -67,12 +67,12 @@ def delete(self, async=True):
# Passing self below is required because the method is a @task
self._delete(self)
- @task
+ @task()
def _save(self, redis=None):
statsd.incr('karma.{t}'.format(t=self.action_type))
KarmaManager(redis).save_action(self)
- @task
+ @task()
def _delete(self):
statsd.incr('karma.delete.{t}'.format(t=self.action_type))
KarmaManager().delete_action(self)
View
14 kitsune/karma/tasks.py
@@ -1,4 +1,4 @@
-from celery.task import task
+from celery import task
import waffle
from kitsune.karma.cron import (
@@ -12,7 +12,7 @@
from kitsune.sumo.utils import chunked
-@task
+@task()
def init_karma():
"""Flushes the karma redis backend and populates with fresh data.
@@ -32,13 +32,13 @@ def init_karma():
_process_answer_vote_chunk.apply_async(args=[chunk])
-@task
+@task()
def update_top_contributors():
"""Updates the top contributor sorted sets."""
_update_top_contributors()
-@task
+@task()
def recalculate_karma_points():
"""Go through all karma action data and recalculate points."""
if not waffle.switch_is_active('karma'):
@@ -48,7 +48,7 @@ def recalculate_karma_points():
_process_recalculate_chunk.apply_async(args=[chunk])
-@task
+@task()
def _process_question_chunk(data):
"""Save karma data for a chunk of questions."""
redis = redis_client(name='karma')
@@ -68,7 +68,7 @@ def _process_question_chunk(data):
redis=redis)
-@task
+@task()
def _process_answer_vote_chunk(data):
"""Save karma data for a chunk of answer votes."""
redis = redis_client(name='karma')
@@ -82,7 +82,7 @@ def _process_answer_vote_chunk(data):
redis=redis)
-@task
+@task()
def _process_recalculate_chunk(data):
"""Recalculate karma points for a chunk of user ids."""
mgr = KarmaManager()
View
4 kitsune/kbadge/tasks.py
@@ -1,13 +1,13 @@
from django.conf import settings
from django.contrib.sites.models import Site
-from celery.task import task
+from celery import task
from tower import ugettext as _
from kitsune.sumo import email_utils
-@task
+@task()
def send_award_notification(award):
"""Sends the award notification email
View
13 kitsune/log_settings.py
@@ -3,8 +3,6 @@
from django.conf import settings
from django.utils.log import dictConfig
-import celery.conf
-import celery.log
config = {
'version': 1,
@@ -72,9 +70,14 @@
config['loggers']['django.request']['handlers'] = ['console']
config['root']['handlers'] = ['console']
else:
+ from celery import current_app
+ from celery.utils.log import LoggingProxy
+
task_log = logging.getLogger('k.celery')
- task_proxy = celery.log.LoggingProxy(task_log)
- celery.conf.CELERYD_LOG_FILE = task_proxy
- celery.conf.CELERYD_LOG_COLOR = False
+ task_proxy = LoggingProxy(task_log)
+ current_app.conf.update(
+ CELERYD_LOG_FILE=task_proxy,
+ CELERYD_LOG_COLOR=False
+ )
dictConfig(config)
View
4 kitsune/messages/tasks.py
@@ -4,7 +4,7 @@
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
-from celery.task import task
+from celery import task
from tower import ugettext as _
from kitsune.messages.models import InboxMessage
@@ -14,7 +14,7 @@
log = logging.getLogger('k.task')
-@task
+@task()
def email_private_message(inbox_message_id):
"""Send notification of a new private message."""
inbox_message = InboxMessage.objects.get(id=inbox_message_id)
View
8 kitsune/questions/tasks.py
@@ -8,7 +8,7 @@
# NOTE: This import is just so _fire_task gets registered with celery.
import tidings.events # noqa
-from celery.task import task
+from celery import task
from multidb.pinning import pin_this_thread, unpin_this_thread
from statsd import statsd
from zendesk import ZendeskError
@@ -116,7 +116,7 @@ def update_answer_pages(question):
i += 1
-@task
+@task()
def log_answer(answer):
pin_this_thread()
@@ -134,7 +134,7 @@ def log_answer(answer):
unpin_this_thread()
-@task
+@task()
def maybe_award_badge(badge_template, year, user):
"""Award the specific badge to the user if they've earned it."""
badge = get_or_create_badge(badge_template, year)
@@ -167,7 +167,7 @@ def __init__(self):
super(PickleableZendeskError, self).__init__(traceback.format_exc())
-@task
+@task()
def escalate_question(question_id):
"""Escalate a question to zendesk by submitting a ticket."""
from kitsune.questions.models import Question
View
10 kitsune/search/tasks.py
@@ -3,7 +3,7 @@
import sys
import traceback
-from celery.task import task
+from celery import task
from multidb.pinning import pin_this_thread, unpin_this_thread
from statsd import statsd
@@ -47,7 +47,7 @@ def __init__(self):
super(IndexingTaskError, self).__init__(traceback.format_exc())
-@task
+@task()
def reconcile_task(write_index, batch_id, mapping_type_name):
"""Reconciles the data in the index with what's in the db
@@ -85,7 +85,7 @@ def reconcile_task(write_index, batch_id, mapping_type_name):
rec.save()
-@task
+@task()
def index_chunk_task(write_index, batch_id, chunk):
"""Index a chunk of things.
@@ -146,7 +146,7 @@ def index_chunk_task(write_index, batch_id, chunk):
MAX_RETRIES = len(RETRY_TIMES)
-@task
+@task()
def index_task(cls, id_list, **kw):
"""Index documents specified by cls and ids"""
statsd.incr('search.tasks.index_task.%s' % cls.get_mapping_type_name())
@@ -182,7 +182,7 @@ def index_task(cls, id_list, **kw):
unpin_this_thread()
-@task
+@task()
def unindex_task(cls, id_list, **kw):
"""Unindex documents specified by cls and ids"""
statsd.incr('search.tasks.unindex_task.%s' % cls.get_mapping_type_name())
View
1 kitsune/settings.py
@@ -754,6 +754,7 @@ def read_only_mode(env):
CELERYD_LOG_LEVEL = logging.INFO
CELERYD_CONCURRENCY = 4
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True # Explode loudly during tests.
+CELERYD_HIJACK_ROOT_LOGGER = False
# Wiki rebuild settings
WIKI_REBUILD_TOKEN = 'sumo:wiki:full-rebuild'
View
2 kitsune/upload/tasks.py
@@ -6,7 +6,7 @@
from django.conf import settings
from django.core.files.base import ContentFile
-from celery.task import task
+from celery import task
from PIL import Image
log = logging.getLogger('k.task')
View
13 kitsune/wiki/tasks.py
@@ -9,8 +9,7 @@
from django.core.mail import mail_admins
from django.db import transaction
-import celery.conf
-from celery.task import task
+from celery import task
from multidb.pinning import pin_this_thread, unpin_this_thread
from statsd import statsd
from tower import ugettext as _
@@ -28,7 +27,7 @@
log = logging.getLogger('k.task')
-@task
+@task()
def send_reviewed_notification(revision, document, message):
"""Send notification of review to the revision creator."""
if revision.reviewer == revision.creator:
@@ -79,7 +78,7 @@ def _make_mail(locale, user):
email_utils.send_messages(msgs)
-@task
+@task()
def send_contributor_notification(based_on, revision, document, message):
"""Send notification of review to the contributors of revisions."""
@@ -137,7 +136,7 @@ def _make_mail(locale, user):
def schedule_rebuild_kb():
"""Try to schedule a KB rebuild, if we're allowed to."""
if (not waffle.switch_is_active('wiki-rebuild-on-demand') or
- celery.conf.ALWAYS_EAGER):
+ settings.CELERY_ALWAYS_EAGER):
return
if cache.get(settings.WIKI_REBUILD_TOKEN):
@@ -223,7 +222,7 @@ def _rebuild_kb_chunk(data):
unpin_this_thread() # Not all tasks need to do use the master.
-@task
+@task()
def maybe_award_badge(badge_template, year, user):
"""Award the specific badge to the user if they've earned it."""
badge = get_or_create_badge(badge_template, year)
@@ -252,7 +251,7 @@ def maybe_award_badge(badge_template, year, user):
return True
-@task
+@task()
def render_document_cascade(base):
"""Given a document, render it and all documents that may be affected."""
View
9 kitsune/wiki/tests/test_tasks.py
@@ -8,7 +8,6 @@
from django.core.cache import cache
import bleach
-import celery.conf
import mock
import waffle
from nose.tools import eq_
@@ -41,7 +40,7 @@
class RebuildTestCase(TestCase):
rf = RequestFactory()
- ALWAYS_EAGER = celery.conf.ALWAYS_EAGER
+ ALWAYS_EAGER = settings.CELERY_ALWAYS_EAGER
def setUp(self):
# create some random revisions.
@@ -54,12 +53,12 @@ def setUp(self):
# TODO: fix this crap
self.old_settings = copy(settings._wrapped.__dict__)
- celery.conf.ALWAYS_EAGER = True
+ settings.CELERY_ALWAYS_EAGER = True
def tearDown(self):
cache.delete(settings.WIKI_REBUILD_TOKEN)
settings._wrapped.__dict__ = self.old_settings
- celery.conf.ALWAYS_EAGER = self.ALWAYS_EAGER
+ settings.CELERY_ALWAYS_EAGER = self.ALWAYS_EAGER
@mock.patch.object(rebuild_kb, 'delay')
@mock.patch.object(waffle, 'switch_is_active')
@@ -73,7 +72,7 @@ def test_eager_queue(self, switch_is_active, delay):
@mock.patch.object(waffle, 'switch_is_active')
def test_task_queue(self, switch_is_active, delay):
switch_is_active.return_value = True
- celery.conf.ALWAYS_EAGER = False
+ settings.CELERY_ALWAYS_EAGER = False
schedule_rebuild_kb()
assert cache.get(settings.WIKI_REBUILD_TOKEN)
assert delay.called
View
20 migrations/235-add-missing-djcelery-tables.sql
@@ -0,0 +1,20 @@
+CREATE TABLE `celery_taskmeta` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `task_id` varchar(255) NOT NULL UNIQUE,
+ `status` varchar(50) NOT NULL,
+ `result` longtext,
+ `date_done` datetime NOT NULL,
+ `traceback` longtext,
+ `hidden` bool NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
+
+CREATE TABLE `celery_tasksetmeta` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `taskset_id` varchar(255) NOT NULL UNIQUE,
+ `result` longtext NOT NULL,
+ `date_done` datetime NOT NULL,
+ `hidden` bool NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
+
+CREATE INDEX `celery_taskmeta_2ff6b945` ON `celery_taskmeta` (`hidden`);
+CREATE INDEX `celery_tasksetmeta_2ff6b945` ON `celery_tasksetmeta` (`hidden`);
View
2 vendor/kitsune.pth
@@ -9,7 +9,7 @@ packages/python-dateutil
packages/pylint
packages/ipython
packages/pyflakes
-packages/amqplib
+packages/amqp
packages/django-taggit
packages/anyjson
packages/carrot
View
412 vendor/packages/amqp/Changelog
@@ -0,0 +1,412 @@
+Changes
+=======
+
+py-amqp is fork of amqplib used by Kombu containing additional features and improvements.
+The previous amqplib changelog is here:
+http://code.google.com/p/py-amqplib/source/browse/CHANGES
+
+.. _version-1.4.2:
+
+1.4.2
+=====
+:release-date: 2014-01-23 05:00 P.M UTC
+
+- Heartbeat negotiation would use heartbeat value from server even
+ if heartbeat disabled (Issue #31).
+
+.. _version-1.4.1:
+
+1.4.1
+=====
+:release-date: 2014-01-14 09:30 P.M UTC
+
+- Fixed error occurring when heartbeats disabled.
+
+.. _version-1.4.0:
+
+1.4.0
+=====
+:release-date: 2014-01-13 03: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
+=====
+:release-date: 2013-11-11 03:30 P.M UTC
+
+- SSLTransport: Now keeps read buffer if an exception is raised
+ (Issue #26).
+
+ Fix contributed by Tommie Gannert.
+
+.. _version-1.3.2:
+
+1.3.2
+=====
+:release-date: 2013-10-29 02:00 P.M UTC
+
+- Message.channel is now a channel object (not the channel id).
+
+- Bug in previous version caused the socket to be flagged as disconnected
+ at EAGAIN/EINTR.
+
+.. _version-1.3.1:
+
+1.3.1
+=====
+:release-date: 2013-10-24 04:00 P.M UTC
+
+- Now implements Connection.connected (Issue #22).
+
+- Fixed bug where ``str(AMQPError)`` did not return string.
+
+.. _version-1.3.0:
+
+1.3.0
+=====
+:release-date: 2013-09-04 02:39 P.M UTC
+
+- Now sets ``Message.channel`` on delivery (Issue #12)
+
+ amqplib used to make the channel object available
+ as ``Message.delivery_info['channel']``, but this was removed
+ in py-amqp. librabbitmq sets ``Message.channel``,
+ which is a more reasonable solution in our opinion as that
+ keeps the delivery info intact.
+
+- New option to wait for publish confirmations (Issue #3)
+
+ There is now a new Connection ``confirm_publish`` that will
+ force any ``basic_publish`` call to wait for confirmation.
+
+ Enabling publisher confirms like this degrades performance
+ considerably, but can be suitable for some applications
+ and now it's possible by configuration.
+
+- ``queue_declare`` now returns named tuple of type
+ :class:`~amqp.protocol.basic_declare_ok_t`.
+
+ Supporting fields: ``queue``, ``message_count``, and
+ ``consumer_count``.
+
+- Contents of ``Channel.returned_messages`` is now named tuples.
+
+ Supporting fields: ``reply_code``, ``reply_text``, ``exchange``,
+ ``routing_key``, and ``message``.
+
+- Sockets now set to close on exec using the ``FD_CLOEXEC`` flag.
+
+ Currently only supported on platforms supporting this flag,
+ which does not include Windows.
+
+ Contributed by Tommie Gannert.
+
+.. _version-1.2.1:
+
+1.2.1
+=====
+:release-date: 2013-08-16 05:30 P.M UTC
+
+- Adds promise type: :meth:`amqp.utils.promise`
+
+- Merges fixes from 1.0.x
+
+.. _version-1.2.0:
+
+1.2.0
+=====
+:release-date: 2012-11-12 04:00 P.M UTC
+
+- New exception hierarchy:
+
+ - :class:`~amqp.AMQPError`
+ - :class:`~amqp.ConnectionError`
+ - :class:`~amqp.RecoverableConnectionError`
+ - :class:`~amqp.ConsumerCancelled`
+ - :class:`~amqp.ConnectionForced`
+ - :class:`~amqp.ResourceError`
+ - :class:`~IrrecoverableConnectionError`
+ - :class:`~amqp.ChannelNotOpen`
+ - :class:`~amqp.FrameError`
+ - :class:`~amqp.FrameSyntaxError`
+ - :class:`~amqp.InvalidCommand`
+ - :class:`~amqp.InvalidPath`
+ - :class:`~amqp.NotAllowed`
+ - :class:`~amqp.UnexpectedFrame`
+ - :class:`~amqp.AMQPNotImplementedError`
+ - :class:`~amqp.InternalError`
+ - :class:`~amqp.ChannelError`
+ - :class:`~RecoverableChannelError`
+ - :class:`~amqp.ContentTooLarge`
+ - :class:`~amqp.NoConsumers`
+ - :class:`~amqp.ResourceLocked`
+ - :class:`~IrrecoverableChannelError`
+ - :class:`~amqp.AccessRefused`
+ - :class:`~amqp.NotFound`
+ - :class:`~amqp.PreconditionFailed`
+
+
+.. _version-1.1.0:
+
+1.1.0
+=====
+:release-date: 2012-11-08 10:36 P.M UTC
+
+- No longer supports Python 2.5
+
+- Fixed receiving of float table values.
+
+- Now Supports Python 3 and Python 2.6+ in the same source code.
+
+- Python 3 related fixes.
+
+.. _version-1.0.13:
+
+1.0.13
+======
+:release-date: 2013-07-31 04:00 P.M BST
+
+- Fixed problems with the SSL transport (Issue #15).
+
+ Fix contributed by Adrien Guinet.
+
+- Small optimizations
+
+.. _version-1.0.12:
+
+1.0.12
+======
+:release-date: 2013-06-25 02:00 P.M BST
+
+- Fixed another Python 3 compatibility problem.
+
+.. _version-1.0.11:
+
+1.0.11
+======
+:release-date: 2013-04-11 06:00 P.M BST
+
+- Fixed Python 3 incompatibility in ``amqp/transport.py``.
+
+.. _version-1.0.10:
+
+1.0.10
+======
+:release-date: 2013-03-21 03:30 P.M UTC
+
+- Fixed Python 3 incompatibility in ``amqp/serialization.py``.
+ (Issue #11).
+
+.. _version-1.0.9:
+
+1.0.9
+=====
+:release-date: 2013-03-08 10:40 A.M UTC
+
+- Publisher ack callbacks should now work after typo fix (Issue #9).
+
+- ``channel(explicit_id)`` will now claim that id from the array
+ of unused channel ids.
+
+- Fixes Jython compatibility.
+
+.. _version-1.0.8:
+
+1.0.8
+=====
+:release-date: 2013-02-08 01:00 P.M UTC
+
+- Fixed SyntaxError on Python 2.5
+
+.. _version-1.0.7:
+
+1.0.7
+=====
+:release-date: 2013-02-08 01:00 P.M UTC
+
+- Workaround for bug on some Python 2.5 installations where (2**32) is 0.
+
+- Can now serialize the ARRAY type.
+
+ Contributed by Adam Wentz.
+
+- Fixed tuple format bug in exception (Issue #4).
+
+.. _version-1.0.6:
+
+1.0.6
+=====
+:release-date: 2012-11-29 01:14 P.M UTC
+
+- ``Channel.close`` is now ignored if the connection attribute is None.
+
+.. _version-1.0.5:
+
+1.0.5
+=====
+:release-date: 2012-11-21 04:00 P.M UTC
+
+- ``Channel.basic_cancel`` is now ignored if the channel was already closed.
+
+- ``Channel.events`` is now a dict of sets::
+
+ >>> channel.events['basic_return'].add(on_basic_return)
+ >>> channel.events['basic_return'].discard(on_basic_return)
+
+.. _version-1.0.4:
+
+1.0.4
+=====
+:release-date: 2012-11-13 04:00 P.M UTC
+
+- Fixes Python 2.5 support
+
+.. _version-1.0.3:
+
+1.0.3
+=====
+:release-date: 2012-11-12 04:00 P.M UTC
+
+- Now can also handle float in headers/tables when receiving messages.
+
+- Now uses :class:`array.array` to keep track of unused channel ids.
+
+- The :data:`~amqp.exceptions.METHOD_NAME_MAP` has been updated for
+ amqp/0.9.1 and Rabbit extensions.
+
+- Removed a bunch of accidentally included images.
+
+.. _version-1.0.2:
+
+1.0.2
+=====
+:release-date: 2012-11-06 05:00 P.M UTC
+
+- Now supports float values in headers/tables.
+
+.. _version-1.0.1:
+
+1.0.1
+=====
+:release-date: 2012-11-05 01:00 P.M UTC
+
+- Connection errors no longer includes :exc:`AttributeError`.
+
+- Fixed problem with using the SSL transport in a non-blocking context.
+
+ Fix contributed by Mher Movsisyan.
+
+
+.. _version-1.0.0:
+
+1.0.0
+=====
+:release-date: 2012-11-05 01:00 P.M UTC
+
+- Channels are now restored on channel error, so that the connection does not
+ have to closed.
+
+.. _version-0.9.4:
+
+Version 0.9.4
+=============
+
+- Adds support for ``exchange_bind`` and ``exchange_unbind``.
+
+ Contributed by Rumyana Neykova
+
+- Fixed bugs in funtests and demo scripts.
+
+ Contributed by Rumyana Neykova
+
+.. _version-0.9.3:
+
+Version 0.9.3
+=============
+
+- Fixed bug that could cause the consumer to crash when reading
+ large message payloads asynchronously.
+
+- Serialization error messages now include the invalid value.
+
+.. _version-0.9.2:
+
+Version 0.9.2
+=============
+
+- Consumer cancel notification support was broken (Issue #1)
+
+ Fix contributed by Andrew Grangaard
+
+.. _version-0.9.1:
+
+Version 0.9.1
+=============
+
+- Supports draining events from multiple channels (``Connection.drain_events``)
+- Support for timeouts
+- Support for heartbeats
+ - ``Connection.heartbeat_tick(rate=2)`` must called at regular intervals
+ (half of the heartbeat value if rate is 2).
+ - Or some other scheme by using ``Connection.send_heartbeat``.
+- Supports RabbitMQ extensions:
+ - Consumer Cancel Notifications
+ - by default a cancel results in ``ChannelError`` being raised
+ - but not if a ``on_cancel`` callback is passed to ``basic_consume``.
+ - Publisher confirms
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+- Support for ``basic_return``
+- Uses AMQP 0-9-1 instead of 0-8.
+ - ``Channel.access_request`` and ``ticket`` arguments to methods
+ **removed**.
+ - Supports the ``arguments`` argument to ``basic_consume``.
+ - ``internal`` argument to ``exchange_declare`` removed.
+ - ``auto_delete`` argument to ``exchange_declare`` deprecated
+ - ``insist`` argument to ``Connection`` removed.
+ - ``Channel.alerts`` has been removed.
+ - Support for ``Channel.basic_recover_async``.
+ - ``Channel.basic_recover`` deprecated.
+- Exceptions renamed to have idiomatic names:
+ - ``AMQPException`` -> ``AMQPError``
+ - ``AMQPConnectionException`` -> ConnectionError``
+ - ``AMQPChannelException`` -> ChannelError``
+ - ``Connection.known_hosts`` removed.
+ - ``Connection`` no longer supports redirects.
+ - ``exchange`` argument to ``queue_bind`` can now be empty
+ to use the "default exchange".
+- Adds ``Connection.is_alive`` that tries to detect
+ whether the connection can still be used.
+- Adds ``Connection.connection_errors`` and ``.channel_errors``,
+ a list of recoverable errors.
+- Exposes the underlying socket as ``Connection.sock``.
+- Adds ``Channel.no_ack_consumers`` to keep track of consumer tags
+ that set the no_ack flag.
+- Slightly better at error recovery
View
0 vendor/packages/amqplib/LICENSE → vendor/packages/amqp/LICENSE
File renamed without changes.
View
6 vendor/packages/amqp/MANIFEST.in
@@ -0,0 +1,6 @@
+include README.rst Changelog LICENSE
+recursive-include docs *
+recursive-include demo *.py
+recursive-include extra README *.py
+recursive-include funtests *.py
+recursive-include requirements *.txt
View
128 vendor/packages/amqp/PKG-INFO
@@ -0,0 +1,128 @@
+Metadata-Version: 1.1
+Name: amqp
+Version: 1.4.2
+Summary: Low-level AMQP client for Python (fork of amqplib)
+Home-page: http://github.com/celery/py-amqp
+Author: Ask Solem
+Author-email: pyamqp@celeryproject.org
+License: LGPL
+Description: =====================================================================
+ Python AMQP 0.9.1 client library
+ =====================================================================
+
+ :Version: 1.4.2
+ :Web: http://amqp.readthedocs.org/
+ :Download: http://pypi.python.org/pypi/amqp/
+ :Source: http://github.com/celery/py-amqp/
+ :Keywords: amqp, rabbitmq
+
+ About
+ =====
+
+ This is a fork of amqplib_ which was originally written by Barry Pederson.
+ It is maintained by the Celery_ project, and used by `kombu`_ as a pure python
+ alternative when `librabbitmq`_ is not available.
+
+ This library should be API compatible with `librabbitmq`_.
+
+ .. _amqplib: http://pypi.python.org/pypi/amqplib
+ .. _Celery: http://celeryproject.org/
+ .. _kombu: http://kombu.readthedocs.org/
+ .. _librabbitmq: http://pypi.python.org/pypi/librabbitmq
+
+ Differences from `amqplib`_
+ ===========================
+
+ - Supports draining events from multiple channels (``Connection.drain_events``)
+ - Support for timeouts
+ - Channels are restored after channel error, instead of having to close the
+ connection.
+ - Support for heartbeats
+
+ - ``Connection.heartbeat_tick(rate=2)`` must called at regular intervals
+ (half of the heartbeat value if rate is 2).
+ - Or some other scheme by using ``Connection.send_heartbeat``.
+ - Supports RabbitMQ extensions:
+ - Consumer Cancel Notifications
+ - by default a cancel results in ``ChannelError`` being raised
+ - but not if a ``on_cancel`` callback is passed to ``basic_consume``.
+ - Publisher confirms
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+ - Exchange-to-exchange bindings: ``exchange_bind`` / ``exchange_unbind``.
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+ - Support for ``basic_return``
+ - Uses AMQP 0-9-1 instead of 0-8.
+ - ``Channel.access_request`` and ``ticket`` arguments to methods
+ **removed**.
+ - Supports the ``arguments`` argument to ``basic_consume``.
+ - ``internal`` argument to ``exchange_declare`` removed.
+ - ``auto_delete`` argument to ``exchange_declare`` deprecated
+ - ``insist`` argument to ``Connection`` removed.
+ - ``Channel.alerts`` has been removed.
+ - Support for ``Channel.basic_recover_async``.
+ - ``Channel.basic_recover`` deprecated.
+ - Exceptions renamed to have idiomatic names:
+ - ``AMQPException`` -> ``AMQPError``
+ - ``AMQPConnectionException`` -> ConnectionError``
+ - ``AMQPChannelException`` -> ChannelError``
+ - ``Connection.known_hosts`` removed.
+ - ``Connection`` no longer supports redirects.
+ - ``exchange`` argument to ``queue_bind`` can now be empty
+ to use the "default exchange".
+ - Adds ``Connection.is_alive`` that tries to detect
+ whether the connection can still be used.
+ - Adds ``Connection.connection_errors`` and ``.channel_errors``,
+ a list of recoverable errors.
+ - Exposes the underlying socket as ``Connection.sock``.
+ - Adds ``Channel.no_ack_consumers`` to keep track of consumer tags
+ that set the no_ack flag.
+ - Slightly better at error recovery
+
+ Further
+ =======
+
+ - Differences between AMQP 0.8 and 0.9.1
+
+ http://www.rabbitmq.com/amqp-0-8-to-0-9-1.html
+
+ - AMQP 0.9.1 Quick Reference
+
+ http://www.rabbitmq.com/amqp-0-9-1-quickref.html
+
+ - RabbitMQ Extensions
+
+ http://www.rabbitmq.com/extensions.html
+
+ - For more information about AMQP, visit
+
+ http://www.amqp.org
+
+ - For other Python client libraries see:
+
+ 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
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.0
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
View
104 vendor/packages/amqp/README.rst
@@ -0,0 +1,104 @@
+=====================================================================
+ Python AMQP 0.9.1 client library
+=====================================================================
+
+:Version: 1.4.2
+:Web: http://amqp.readthedocs.org/
+:Download: http://pypi.python.org/pypi/amqp/
+:Source: http://github.com/celery/py-amqp/
+:Keywords: amqp, rabbitmq
+
+About
+=====
+
+This is a fork of amqplib_ which was originally written by Barry Pederson.
+It is maintained by the Celery_ project, and used by `kombu`_ as a pure python
+alternative when `librabbitmq`_ is not available.
+
+This library should be API compatible with `librabbitmq`_.
+
+.. _amqplib: http://pypi.python.org/pypi/amqplib
+.. _Celery: http://celeryproject.org/
+.. _kombu: http://kombu.readthedocs.org/
+.. _librabbitmq: http://pypi.python.org/pypi/librabbitmq
+
+Differences from `amqplib`_
+===========================
+
+- Supports draining events from multiple channels (``Connection.drain_events``)
+- Support for timeouts
+- Channels are restored after channel error, instead of having to close the
+ connection.
+- Support for heartbeats
+
+ - ``Connection.heartbeat_tick(rate=2)`` must called at regular intervals
+ (half of the heartbeat value if rate is 2).
+ - Or some other scheme by using ``Connection.send_heartbeat``.
+- Supports RabbitMQ extensions:
+ - Consumer Cancel Notifications
+ - by default a cancel results in ``ChannelError`` being raised
+ - but not if a ``on_cancel`` callback is passed to ``basic_consume``.
+ - Publisher confirms
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+ - Exchange-to-exchange bindings: ``exchange_bind`` / ``exchange_unbind``.
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+- Support for ``basic_return``
+- Uses AMQP 0-9-1 instead of 0-8.
+ - ``Channel.access_request`` and ``ticket`` arguments to methods
+ **removed**.
+ - Supports the ``arguments`` argument to ``basic_consume``.
+ - ``internal`` argument to ``exchange_declare`` removed.
+ - ``auto_delete`` argument to ``exchange_declare`` deprecated
+ - ``insist`` argument to ``Connection`` removed.
+ - ``Channel.alerts`` has been removed.
+ - Support for ``Channel.basic_recover_async``.
+ - ``Channel.basic_recover`` deprecated.
+- Exceptions renamed to have idiomatic names:
+ - ``AMQPException`` -> ``AMQPError``
+ - ``AMQPConnectionException`` -> ConnectionError``
+ - ``AMQPChannelException`` -> ChannelError``
+ - ``Connection.known_hosts`` removed.
+ - ``Connection`` no longer supports redirects.
+ - ``exchange`` argument to ``queue_bind`` can now be empty
+ to use the "default exchange".
+- Adds ``Connection.is_alive`` that tries to detect
+ whether the connection can still be used.
+- Adds ``Connection.connection_errors`` and ``.channel_errors``,
+ a list of recoverable errors.
+- Exposes the underlying socket as ``Connection.sock``.
+- Adds ``Channel.no_ack_consumers`` to keep track of consumer tags
+ that set the no_ack flag.
+- Slightly better at error recovery
+
+Further
+=======
+
+- Differences between AMQP 0.8 and 0.9.1
+
+ http://www.rabbitmq.com/amqp-0-8-to-0-9-1.html
+
+- AMQP 0.9.1 Quick Reference
+
+ http://www.rabbitmq.com/amqp-0-9-1-quickref.html
+
+- RabbitMQ Extensions
+
+ http://www.rabbitmq.com/extensions.html
+
+- For more information about AMQP, visit
+
+ http://www.amqp.org
+
+- For other Python client libraries see:
+
+ 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
View
128 vendor/packages/amqp/amqp.egg-info/PKG-INFO
@@ -0,0 +1,128 @@
+Metadata-Version: 1.1
+Name: amqp
+Version: 1.4.2
+Summary: Low-level AMQP client for Python (fork of amqplib)
+Home-page: http://github.com/celery/py-amqp
+Author: Ask Solem
+Author-email: pyamqp@celeryproject.org
+License: LGPL
+Description: =====================================================================
+ Python AMQP 0.9.1 client library
+ =====================================================================
+
+ :Version: 1.4.2
+ :Web: http://amqp.readthedocs.org/
+ :Download: http://pypi.python.org/pypi/amqp/
+ :Source: http://github.com/celery/py-amqp/
+ :Keywords: amqp, rabbitmq
+
+ About
+ =====
+
+ This is a fork of amqplib_ which was originally written by Barry Pederson.
+ It is maintained by the Celery_ project, and used by `kombu`_ as a pure python
+ alternative when `librabbitmq`_ is not available.
+
+ This library should be API compatible with `librabbitmq`_.
+
+ .. _amqplib: http://pypi.python.org/pypi/amqplib
+ .. _Celery: http://celeryproject.org/
+ .. _kombu: http://kombu.readthedocs.org/
+ .. _librabbitmq: http://pypi.python.org/pypi/librabbitmq
+
+ Differences from `amqplib`_
+ ===========================
+
+ - Supports draining events from multiple channels (``Connection.drain_events``)
+ - Support for timeouts
+ - Channels are restored after channel error, instead of having to close the
+ connection.
+ - Support for heartbeats
+
+ - ``Connection.heartbeat_tick(rate=2)`` must called at regular intervals
+ (half of the heartbeat value if rate is 2).
+ - Or some other scheme by using ``Connection.send_heartbeat``.
+ - Supports RabbitMQ extensions:
+ - Consumer Cancel Notifications
+ - by default a cancel results in ``ChannelError`` being raised
+ - but not if a ``on_cancel`` callback is passed to ``basic_consume``.
+ - Publisher confirms
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+ - Exchange-to-exchange bindings: ``exchange_bind`` / ``exchange_unbind``.
+ - ``Channel.confirm_select()`` enables publisher confirms.
+ - ``Channel.events['basic_ack'].append(my_callback)`` adds a callback
+ to be called when a message is confirmed. This callback is then
+ called with the signature ``(delivery_tag, multiple)``.
+ - Support for ``basic_return``
+ - Uses AMQP 0-9-1 instead of 0-8.
+ - ``Channel.access_request`` and ``ticket`` arguments to methods
+ **removed**.
+ - Supports the ``arguments`` argument to ``basic_consume``.
+ - ``internal`` argument to ``exchange_declare`` removed.
+ - ``auto_delete`` argument to ``exchange_declare`` deprecated
+ - ``insist`` argument to ``Connection`` removed.
+ - ``Channel.alerts`` has been removed.
+ - Support for ``Channel.basic_recover_async``.
+ - ``Channel.basic_recover`` deprecated.
+ - Exceptions renamed to have idiomatic names:
+ - ``AMQPException`` -> ``AMQPError``
+ - ``AMQPConnectionException`` -> ConnectionError``
+ - ``AMQPChannelException`` -> ChannelError``
+ - ``Connection.known_hosts`` removed.
+ - ``Connection`` no longer supports redirects.
+ - ``exchange`` argument to ``queue_bind`` can now be empty
+ to use the "default exchange".
+ - Adds ``Connection.is_alive`` that tries to detect
+ whether the connection can still be used.
+ - Adds ``Connection.connection_errors`` and ``.channel_errors``,
+ a list of recoverable errors.
+ - Exposes the underlying socket as ``Connection.sock``.
+ - Adds ``Channel.no_ack_consumers`` to keep track of consumer tags
+ that set the no_ack flag.
+ - Slightly better at error recovery
+
+ Further
+ =======
+
+ - Differences between AMQP 0.8 and 0.9.1
+
+ http://www.rabbitmq.com/amqp-0-8-to-0-9-1.html
+
+ - AMQP 0.9.1 Quick Reference
+
+ http://www.rabbitmq.com/amqp-0-9-1-quickref.html
+
+ - RabbitMQ Extensions
+
+ http://www.rabbitmq.com/extensions.html
+
+ - For more information about AMQP, visit
+
+ http://www.amqp.org
+
+ - For other Python client libraries see:
+
+ 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
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.0
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
View
68 vendor/packages/amqp/amqp.egg-info/SOURCES.txt
@@ -0,0 +1,68 @@
+Changelog
+LICENSE
+MANIFEST.in
+README.rst
+setup.py
+amqp/__init__.py
+amqp/abstract_channel.py
+amqp/basic_message.py
+amqp/channel.py
+amqp/connection.py
+amqp/exceptions.py
+amqp/five.py
+amqp/method_framing.py
+amqp/protocol.py
+amqp/serialization.py
+amqp/transport.py
+amqp/utils.py
+amqp.egg-info/PKG-INFO
+amqp.egg-info/SOURCES.txt
+amqp.egg-info/dependency_links.txt
+amqp.egg-info/not-zip-safe
+amqp.egg-info/top_level.txt
+demo/amqp_clock.py
+demo/demo_receive.py
+demo/demo_send.py
+docs/Makefile
+docs/changelog.rst
+docs/conf.py
+docs/index.rst
+docs/.static/.keep
+docs/.templates/page.html
+docs/.templates/sidebarintro.html
+docs/.templates/sidebarlogo.html
+docs/_ext/applyxrefs.py
+docs/_ext/literals_to_xrefs.py
+docs/_theme/celery/theme.conf
+docs/_theme/celery/static/celery.css_t
+docs/includes/.intro.txt.swp
+docs/includes/intro.txt
+docs/reference/amqp.abstract_channel.rst
+docs/reference/amqp.basic_message.rst
+docs/reference/amqp.channel.rst
+docs/reference/amqp.connection.rst
+docs/reference/amqp.exceptions.rst
+docs/reference/amqp.five.rst
+docs/reference/amqp.method_framing.rst
+docs/reference/amqp.protocol.rst
+docs/reference/amqp.serialization.rst
+docs/reference/amqp.transport.rst
+docs/reference/amqp.utils.rst
+docs/reference/index.rst
+docs/templates/readme.txt
+extra/README
+extra/generate_skeleton_0_8.py
+extra/update_comments_from_spec.py
+extra/release/bump_version.py
+extra/release/sphinx-to-rst.py
+funtests/run_all.py
+funtests/settings.py
+funtests/test_basic_message.py
+funtests/test_channel.py
+funtests/test_connection.py
+funtests/test_exceptions.py
+funtests/test_serialization.py
+funtests/test_with.py
+requirements/docs.txt
+requirements/pkgutils.txt
+requirements/test.txt
View
0 ...nfo/amqplib.egg-info/dependency_links.txt → ...s/amqp/amqp.egg-info/dependency_links.txt
File renamed without changes.
View
0 vendor/packages/amqplib/amqplib/__init__.py → .../packages/amqp/amqp.egg-info/not-zip-safe
File renamed without changes.
View
1 vendor/packages/amqp/amqp.egg-info/top_level.txt
@@ -0,0 +1 @@
+amqp
View
70 vendor/packages/amqp/amqp/__init__.py
@@ -0,0 +1,70 @@
+"""Low-level AMQP client for Python (fork of amqplib)"""
+# Copyright (C) 2007-2008 Barry Pederson <bp@barryp.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+from __future__ import absolute_import
+
+VERSION = (1, 4, 2)
+__version__ = '.'.join(map(str, VERSION[0:3])) + ''.join(VERSION[3:])
+__author__ = 'Barry Pederson'
+__maintainer__ = 'Ask Solem'
+__contact__ = 'pyamqp@celeryproject.org'
+__homepage__ = 'http://github.com/celery/py-amqp'
+__docformat__ = 'restructuredtext'
+
+# -eof meta-
+
+#
+# Pull in the public items from the various sub-modules
+#
+from .basic_message import Message # noqa
+from .channel import Channel # noqa
+from .connection import Connection # noqa
+from .exceptions import ( # noqa
+ AMQPError,
+ ConnectionError,
+ RecoverableConnectionError,
+ IrrecoverableConnectionError,
+ ChannelError,
+ RecoverableChannelError,
+ IrrecoverableChannelError,
+ ConsumerCancelled,
+ ContentTooLarge,
+ NoConsumers,
+ ConnectionForced,
+ InvalidPath,
+ AccessRefused,
+ NotFound,
+ ResourceLocked,
+ PreconditionFailed,
+ FrameError,
+ FrameSyntaxError,
+ InvalidCommand,
+ ChannelNotOpen,
+ UnexpectedFrame,
+ ResourceError,
+ NotAllowed,
+ AMQPNotImplementedError,
+ InternalError,
+ error_for_code,
+ __all__ as _all_exceptions,
+)
+from .utils import promise # noqa
+
+__all__ = [
+ 'Connection',
+ 'Channel',
+ 'Message',
+] + _all_exceptions
View
89 ...ib/amqplib/client_0_8/abstract_channel.py → ...or/packages/amqp/amqp/abstract_channel.py
@@ -1,8 +1,5 @@
-"""
-Code common to Connection and Channel objects.
-
-"""
-# Copyright (C) 2007-2008 Barry Pederson <bp@barryp.org>
+"""Code common to Connection and Channel objects."""
+# Copyright (C) 2007-2008 Barry Pederson <bp@barryp.org>)
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -17,23 +14,16 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+from __future__ import absolute_import
-from serialization import AMQPWriter
-
-try:
- bytes
-except NameError:
- # Python 2.5 and lower
- bytes = str
+from .exceptions import AMQPNotImplementedError, RecoverableConnectionError
+from .serialization import AMQPWriter
-__all__ = [
- 'AbstractChannel',
- ]
+__all__ = ['AbstractChannel']
class AbstractChannel(object):
- """
- Superclass for both the Connection, which is treated
+ """Superclass for both the Connection, which is treated
as channel 0, and other user-created Channel objects.
The subclasses must have a _METHOD_MAP class property, mapping
@@ -44,81 +34,60 @@ def __init__(self, connection, channel_id):
self.connection = connection
self.channel_id = channel_id
connection.channels[channel_id] = self
- self.method_queue = [] # Higher level queue for methods
+ self.method_queue = [] # Higher level queue for methods
self.auto_decode = False
-
def __enter__(self):
- """
- Support for Python >= 2.5 'with' statements.
-
- """
return self
-
- def __exit__(self, type, value, traceback):
- """
- Support for Python >= 2.5 'with' statements.
-
- """
+ def __exit__(self, *exc_info):
self.close()
-
def _send_method(self, method_sig, args=bytes(), content=None):
- """
- Send a method for our channel.
+ """Send a method for our channel."""
+ conn = self.connection
+ if conn is None:
+ raise RecoverableConnectionError('connection already closed')
- """
if isinstance(args, AMQPWriter):
args = args.getvalue()
- self.connection.method_writer.write_method(self.channel_id,
- method_sig, args, content)
-
+ conn.method_writer.write_method(
+ self.channel_id, method_sig, args, content,
+ )
def close(self):
- """
- Close this Channel or Connection
-
- """
+ """Close this Channel or Connection"""
raise NotImplementedError('Must be overriden in subclass')
-
-
def wait(self, allowed_methods=None):
- """
- Wait for a method that matches our allowed_methods parameter (the
- default value of None means match any method), and dispatch to it.
-
- """
+ """Wait for a method that matches our allowed_methods parameter (the
+ default value of None means match any method), and dispatch to it."""
method_sig, args, content = self.connection._wait_method(
self.channel_id, allowed_methods)
return self.dispatch_method(method_sig, args, content)
-
def dispatch_method(self, method_sig, args, content):
- if content \
- and self.auto_decode \
- and hasattr(content, 'content_encoding'):
+ if content and \
+ self.auto_decode and \
+ hasattr(content, 'content_encoding'):
try:
content.body = content.body.decode(content.content_encoding)
except Exception:
pass
- amqp_method = self._METHOD_MAP.get(method_sig, None)
-
- if amqp_method is None:
- raise Exception('Unknown AMQP method (%d, %d)' % method_sig)
+ try:
+ amqp_method = self._METHOD_MAP[method_sig]
+ except KeyError:
+ raise AMQPNotImplementedError(
+ 'Unknown AMQP method {0!r}'.format(method_sig))
if content is None:
return amqp_method(self, args)
else:
return amqp_method(self, args, content)
-
- #
- # Placeholder, the concrete implementations will have to
- # supply their own versions of _METHOD_MAP
- #
+ #: Placeholder, the concrete implementations will have to
+ #: supply their own versions of _METHOD_MAP
_METHOD_MAP = {}
View
48 ...qplib/amqplib/client_0_8/basic_message.py → vendor/packages/amqp/amqp/basic_message.py
@@ -1,7 +1,4 @@
-"""
-Messages for AMQP
-
-"""
+"""Messages for AMQP"""
# Copyright (C) 2007-2008 Barry Pederson <bp@barryp.org>
#
# This library is free software; you can redistribute it and/or
@@ -17,25 +14,19 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+from __future__ import absolute_import
+from .serialization import GenericContent
-from serialization import GenericContent
-
-__all__ = [
- 'Message',
- ]
+__all__ = ['Message']
class Message(GenericContent):
- """
- A Message for use with the Channnel.basic_* methods.
-
- """
- #
- # Instances of this class have these attributes, which
- # are passed back and forth as message properties between
- # client and server
- #
+ """A Message for use with the Channnel.basic_* methods."""
+
+ #: Instances of this class have these attributes, which
+ #: are passed back and forth as message properties between
+ #: client and server
PROPERTIES = [
('content_type', 'shortstr'),
('content_encoding', 'shortstr'),
@@ -51,11 +42,10 @@ class Message(GenericContent):
('user_id', 'shortstr'),
('app_id', 'shortstr'),
('cluster_id', 'shortstr')
- ]
+ ]
- def __init__(self, body='', children=None, **properties):
- """
- Expected arg types
+ def __init__(self, body='', children=None, channel=None, **properties):
+ """Expected arg types
body: string
children: (not supported)
@@ -108,7 +98,7 @@ def __init__(self, body='', children=None, **properties):
Unicode bodies are encoded according to the 'content_encoding'
argument. If that's None, it's set to 'UTF-8' automatically.
- example:
+ example::
msg = Message('hello world',
content_type='text/plain',
@@ -117,16 +107,18 @@ def __init__(self, body='', children=None, **properties):
"""
super(Message, self).__init__(**properties)
self.body = body
-
+ self.channel = channel
def __eq__(self, other):
- """
- Check if the properties and bodies of this Message and another
+ """Check if the properties and bodies of this Message and another
Message are the same.
Received messages may contain a 'delivery_info' attribute,
which isn't compared.
"""
- return super(Message, self).__eq__(other) \
- and hasattr(other, 'body') and (self.body == other.body)
+ try:
+ return (super(Message, self).__eq__(other) and
+ self.body == other.body)
+ except AttributeError:
+ return NotImplemented
View
1,099 ...ges/amqplib/amqplib/client_0_8/channel.py → vendor/packages/amqp/amqp/channel.py
471 additions, 628 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
636 .../amqplib/amqplib/client_0_8/connection.py → vendor/packages/amqp/amqp/connection.py
@@ -1,7 +1,4 @@
-"""
-AMQP 0-8 Connections
-
-"""
+"""AMQP Connections"""
# Copyright (C) 2007-2008 Barry Pederson <bp@barryp.org>
#
# This library is free software; you can redistribute it and/or
@@ -17,66 +14,100 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+from __future__ import absolute_import
import logging
-
-from abstract_channel import AbstractChannel
-from channel import Channel
-from exceptions import *
-from method_framing import MethodReader, MethodWriter
-from serialization import AMQPReader, AMQPWriter
-from transport import create_transport
-
-__all__ = [
- 'Connection',
- ]
+import socket
+
+from array import array
+try:
+ from ssl import SSLError
+except ImportError:
+ class SSLError(Exception): # noqa
+ pass
+
+from . import __version__
+from .abstract_channel import AbstractChannel
+from .channel import Channel
+from .exceptions import (
+ AMQPNotImplementedError, ChannelError, ResourceError,
+ ConnectionForced, ConnectionError, error_for_code,
+ RecoverableConnectionError, RecoverableChannelError,
+)
+from .five import items, range, values, monotonic
+from .method_framing import MethodReader, MethodWriter
+from .serialization import AMQPWriter
+from .transport import create_transport
+
+HAS_MSG_PEEK = hasattr(socket, 'MSG_PEEK')
+
+START_DEBUG_FMT = """
+Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s
+""".strip()
+
+__all__ = ['Connection']
#
# Client property info that gets sent to the server on connection startup
#
LIBRARY_PROPERTIES = {
- 'library': 'Python amqplib',
- 'library_version': '1.0.2',
- }
+ 'product': 'py-amqp',
+ 'product_version': __version__,
+ 'capabilities': {},
+}
-AMQP_LOGGER = logging.getLogger('amqplib')
+AMQP_LOGGER = logging.getLogger('amqp')
class Connection(AbstractChannel):
- """
- The connection class provides methods for a client to establish a
+ """The connection class provides methods for a client to establish a
network connection to a server, and for both peers to operate the
connection thereafter.
- GRAMMAR:
+ GRAMMAR::
connection = open-connection *use-connection close-connection
open-connection = C:protocol-header
S:START C:START-OK
*challenge
S:TUNE C:TUNE-OK
- C:OPEN S:OPEN-OK | S:REDIRECT
+ C:OPEN S:OPEN-OK
challenge = S:SECURE C:SECURE-OK
use-connection = *channel
close-connection = C:CLOSE S:CLOSE-OK
/ S:CLOSE C:CLOSE-OK
"""
- def __init__(self,
- host='localhost',
- userid='guest',
- password='guest',
- login_method='AMQPLAIN',
- login_response=None,
- virtual_host='/',
- locale='en_US',
- client_properties=None,
- ssl=False,
- insist=False,
- connect_timeout=None,
- **kwargs):
- """
- Create a connection to the specified host, which should be
+ 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
+
+ def __init__(self, host='localhost', userid='guest', password='guest',
+ login_method='AMQPLAIN', login_response=None,
+ virtual_host='/', locale='en_US', client_properties=None,
+ ssl=False, connect_timeout=None, channel_max=None,
+ frame_max=None, heartbeat=0, on_blocked=None,
+ on_unblocked=None, confirm_publish=False, **kwargs):
+ """Create a connection to the specified host, which should be
a 'host[:port]', such as 'localhost', or '1.2.3.4:5672'
(defaults to 'localhost', if a port is not specified then
5672 is used)
@@ -89,98 +120,102 @@ def __init__(self,
requiring certain certificates.
"""
+ channel_max = channel_max or 65535
+ frame_max = frame_max or 131072
if (login_response is None) \
- and (userid is not None) \
- and (password is not None):
+ and (userid is not None) \
+ and (password is not None):
login_response = AMQPWriter()
login_response.write_table({'LOGIN': userid, 'PASSWORD': password})
- login_response = login_response.getvalue()[4:] #Skip the length
- #at the beginning
+ login_response = login_response.getvalue()[4:] # Skip the length
+ # at the beginning
- d = {}
- d.update(LIBRARY_PROPERTIES)
- if client_properties:
- d.update(client_properties)
+ d = dict(LIBRARY_PROPERTIES, **client_properties or {})
+ self._method_override = {(60, 50): self._dispatch_basic_return}
- self.known_hosts = ''
+ self.channels = {}
+ # The connection object itself is treated as channel 0
+ super(Connection, self).__init__(self, 0)
- while True:
- self.channels = {}
- # The connection object itself is treated as channel 0
- super(Connection, self).__init__(self, 0)
+ self.transport = None
- self.transport = None
+ # Properties set in the Tune method
+ self.channel_max = channel_max
+ self.frame_max = frame_max
+ self.client_heartbeat = heartbeat
- # Properties set in the Tune method
- self.channel_max = 65535
- self.frame_max = 131072
- self.heartbeat = 0
+ self.confirm_publish = confirm_publish
- # Properties set in the Start method
- self.version_major = 0
- self.version_minor = 0
- self.server_properties = {}
- self.mechanisms = []
- self.locales = []
+ # Callbacks
+ self.on_blocked = on_blocked
+ self.on_unblocked = on_unblocked
- # Let the transport.py module setup the actual
- # socket connection to the broker.
- #
- self.transport = create_transport(host, connect_timeout, ssl)
+ self._avail_channel_ids = array('H', range(self.channel_max, 0, -1))
- self.method_reader = MethodReader(self.transport)
- self.method_writer = MethodWriter(self.transport, self.frame_max)
+ # Properties set in the Start method
+ self.version_major = 0
+ self.version_minor = 0
+ self.server_properties = {}
+ self.mechanisms = []
+ self.locales = []
- self.wait(allowed_methods=[
- (10, 10), # start
- ])
+ # Let the transport.py module setup the actual
+ # socket connection to the broker.
+ #
+ self.transport = create_transport(host, connect_timeout, ssl)
- self._x_start_ok(d, login_method, login_response, locale)
+ self.method_reader = MethodReader(self.transport)
+ self.method_writer = MethodWriter(self.transport, self.frame_max)
- self._wait_tune_ok = True
- while self._wait_tune_ok:
- self.wait(allowed_methods=[
- (10, 20), # secure
- (10, 30), # tune
- ])
+ self.wait(allowed_methods=[
+ (10, 10), # start
+ ])
- host = self._x_open(virtual_host, insist=insist)
- if host is None:
- # we weren't redirected
- return
-
- # we were redirected, close the socket, loop and try again
- try:
- self.close()
- except Exception:
- pass
+ self._x_start_ok(d, login_method, login_response, locale)
+ self._wait_tune_ok = True
+ while self._wait_tune_ok:
+ self.wait(allowed_methods=[
+ (10, 20), # secure
+ (10, 30), # tune
+ ])
- def _do_close(self):
- self.transport.close()
- self.transport = None
+ return self._x_open(virtual_host)
- temp_list = [x for x in self.channels.values() if x is not self]
- for ch in temp_list:
- ch._do_close()
+ @property
+ def connected(self):
+ return self.transport and self.transport.connected
- self.connection = self.channels = None
+ def _do_close(self):
+ try:
+ self.transport.close()
+ temp_list = [x for x in values(self.channels) if x is not self]
+ for ch in temp_list:
+ ch._do_close()
+ except socket.error:
+ pass # connection already closed on the other end
+ finally:
+ self.transport = self.connection = self.channels = None
def _get_free_channel_id(self):
- for i in xrange(1, self.channel_max+1):
- if i not in self.channels:
- return i
- raise AMQPException('No free channel ids, current=%d, channel_max=%d'
- % (len(self.channels), self.channel_max))
-
+ try:
+ return self._avail_channel_ids.pop()
+ except IndexError:
+ raise ResourceError(
+ 'No free channel ids, current={0}, channel_max={1}'.format(
+ len(self.channels), self.channel_max), (20, 10))
+
+ def _claim_channel_id(self, channel_id):
+ try:
+ return self._avail_channel_ids.remove(channel_id)
+ except ValueError:
+ raise ConnectionError(
+ 'Channel %r already open' % (channel_id, ))
def _wait_method(self, channel_id, allowed_methods):
- """
- Wait for a method from the server destined for
- a particular channel.
-
- """
+ """Wait for a method from the server destined for
+ a particular channel."""
#
# Check the channel's deferred methods
#
@@ -189,22 +224,22 @@ def _wait_method(self, channel_id, allowed_methods):
for queued_method in method_queue:
method_sig = queued_method[0]
if (allowed_methods is None) \
- or (method_sig in allowed_methods) \
- or (method_sig == (20, 40)):
+ or (method_sig in allowed_methods) \
+ or (method_sig == (20, 40)):
method_queue.remove(queued_method)
return queued_method
#
# Nothing queued, need to wait for a method from the peer
#
- while True:
+ while 1:
channel, method_sig, args, content = \
self.method_reader.read_method()
- if (channel == channel_id) \
- and ((allowed_methods is None) \
- or (method_sig in allowed_methods) \
- or (method_sig == (20, 40))):
+ if channel == channel_id and (
+ allowed_methods is None or
+ method_sig in allowed_methods or
+ method_sig == (20, 40)):
return method_sig, args, content
#
@@ -212,42 +247,153 @@ def _wait_method(self, channel_id, allowed_methods):
# immediately rather than being queued, even if they're not
# one of the 'allowed_methods' we're looking for.
#
- if (channel != 0) and (method_sig in Channel._IMMEDIATE_METHODS):
- self.channels[channel].dispatch_method(method_sig, args, content)
+ if channel and method_sig in self.Channel._IMMEDIATE_METHODS:
+ self.channels[channel].dispatch_method(
+ method_sig, args, content,
+ )
continue
#
# Not the channel and/or method we were looking for. Queue
# this method for later
#
- self.channels[channel].method_queue.append((method_sig, args, content))
+ self.channels[channel].method_queue.append(
+ (method_sig, args, content),
+ )
#
# If we just queued up a method for channel 0 (the Connection
# itself) it's probably a close method in reaction to some
# error, so deal with it right away.
#
- if channel == 0:
+ if not channel:
self.wait()
-
def channel(self, channel_id=None):
- """
- Fetch a Channel object identified by the numeric channel_id, or
- create that object if it doesn't already exist.
-
- """
- if channel_id in self.channels:
+ """Fetch a Channel object identified by the numeric channel_id, or
+ create that object if it doesn't already exist."""
+ try:
return self.channels[channel_id]
+ except KeyError:
+ return self.Channel(self, channel_id)
+
+ def is_alive(self):
+ if HAS_MSG_PEEK:
+ sock = self.sock
+ prev = sock.gettimeout()
+ sock.settimeout(0.0001)
+ try:
+ sock.recv(1, socket.MSG_PEEK)
+ except socket.timeout:
+ pass
+ except socket.error:
+ return False
+ finally:
+ sock.settimeout(prev)
+ return True
+
+ def drain_events(self, timeout=None):
+ """Wait for an event on a channel."""
+ chanmap = self.channels
+ chanid, method_sig, args, content = self._wait_multiple(
+ chanmap, None, timeout=timeout,