Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

librabbitmq.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. """
  2. kombu.transport.librabbitmq
  3. ===========================
  4. `librabbitmq`_ transport.
  5. .. _`librabbitmq`: http://pypi.python.org/librabbitmq/
  6. """
  7. from __future__ import absolute_import
  8. import os
  9. import socket
  10. import warnings
  11. import librabbitmq as amqp
  12. from librabbitmq import ChannelError, ConnectionError
  13. from kombu.five import items, values
  14. from kombu.utils.amq_manager import get_manager
  15. from kombu.utils.text import version_string_as_tuple
  16. from . import base
  17. W_VERSION = """
  18. librabbitmq version too old to detect RabbitMQ version information
  19. so make sure you are using librabbitmq 1.5 when using rabbitmq > 3.3
  20. """
  21. DEFAULT_PORT = 5672
  22. DEFAULT_SSL_PORT = 5671
  23. NO_SSL_ERROR = """\
  24. ssl not supported by librabbitmq, please use pyamqp:// or stunnel\
  25. """
  26. class Message(base.Message):
  27. def __init__(self, channel, props, info, body):
  28. super(Message, self).__init__(
  29. channel,
  30. body=body,
  31. delivery_info=info,
  32. properties=props,
  33. delivery_tag=info.get('delivery_tag'),
  34. content_type=props.get('content_type'),
  35. content_encoding=props.get('content_encoding'),
  36. headers=props.get('headers'))
  37. class Channel(amqp.Channel, base.StdChannel):
  38. Message = Message
  39. def prepare_message(self, body, priority=None,
  40. content_type=None, content_encoding=None,
  41. headers=None, properties=None):
  42. """Encapsulate data into a AMQP message."""
  43. properties = properties if properties is not None else {}
  44. properties.update({'content_type': content_type,
  45. 'content_encoding': content_encoding,
  46. 'headers': headers,
  47. 'priority': priority})
  48. return body, properties
  49. class Connection(amqp.Connection):
  50. Channel = Channel
  51. Message = Message
  52. class Transport(base.Transport):
  53. Connection = Connection
  54. default_port = DEFAULT_PORT
  55. default_ssl_port = DEFAULT_SSL_PORT
  56. connection_errors = (
  57. base.Transport.connection_errors + (
  58. ConnectionError, socket.error, IOError, OSError)
  59. )
  60. channel_errors = (
  61. base.Transport.channel_errors + (ChannelError, )
  62. )
  63. driver_type = 'amqp'
  64. driver_name = 'librabbitmq'
  65. supports_ev = True
  66. def __init__(self, client, **kwargs):
  67. self.client = client
  68. self.default_port = kwargs.get('default_port') or self.default_port
  69. self.default_ssl_port = (kwargs.get('default_ssl_port') or
  70. self.default_ssl_port)
  71. self.__reader = None
  72. def driver_version(self):
  73. return amqp.__version__
  74. def create_channel(self, connection):
  75. return connection.channel()
  76. def drain_events(self, connection, **kwargs):
  77. return connection.drain_events(**kwargs)
  78. def establish_connection(self):
  79. """Establish connection to the AMQP broker."""
  80. conninfo = self.client
  81. for name, default_value in items(self.default_connection_params):
  82. if not getattr(conninfo, name, None):
  83. setattr(conninfo, name, default_value)
  84. if conninfo.ssl:
  85. raise NotImplementedError(NO_SSL_ERROR)
  86. opts = dict({
  87. 'host': conninfo.host,
  88. 'userid': conninfo.userid,
  89. 'password': conninfo.password,
  90. 'virtual_host': conninfo.virtual_host,
  91. 'login_method': conninfo.login_method,
  92. 'insist': conninfo.insist,
  93. 'ssl': conninfo.ssl,
  94. 'connect_timeout': conninfo.connect_timeout,
  95. }, **conninfo.transport_options or {})
  96. conn = self.Connection(**opts)
  97. conn.client = self.client
  98. self.client.drain_events = conn.drain_events
  99. return conn
  100. def close_connection(self, connection):
  101. """Close the AMQP broker connection."""
  102. self.client.drain_events = None
  103. connection.close()
  104. def _collect(self, connection):
  105. if connection is not None:
  106. for channel in values(connection.channels):
  107. channel.connection = None
  108. try:
  109. os.close(connection.fileno())
  110. except OSError:
  111. pass
  112. connection.channels.clear()
  113. connection.callbacks.clear()
  114. self.client.drain_events = None
  115. self.client = None
  116. def verify_connection(self, connection):
  117. return connection.connected
  118. def register_with_event_loop(self, connection, loop):
  119. loop.add_reader(
  120. connection.fileno(), self.on_readable, connection, loop,
  121. )
  122. def get_manager(self, *args, **kwargs):
  123. return get_manager(self.client, *args, **kwargs)
  124. def qos_semantics_matches_spec(self, connection):
  125. try:
  126. props = connection.server_properties
  127. except AttributeError:
  128. warnings.warn(UserWarning(W_VERSION))
  129. else:
  130. if props.get('product') == 'RabbitMQ':
  131. return version_string_as_tuple(props['version']) < (3, 3)
  132. return True
  133. @property
  134. def default_connection_params(self):
  135. return {
  136. 'userid': 'guest',
  137. 'password': 'guest',
  138. 'port': (self.default_ssl_port if self.client.ssl
  139. else self.default_port),
  140. 'hostname': 'localhost',
  141. 'login_method': 'AMQPLAIN',
  142. }