From 4133a705f34e98bece2d584b9acd0c9279a39634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <pmaslanka@smok.co> Date: Tue, 15 Oct 2024 15:57:59 +0000 Subject: [PATCH] fixes #2 --- coolamqp/__init__.py | 2 +- coolamqp/clustering/cluster.py | 7 ++++++ coolamqp/clustering/single.py | 4 +++ coolamqp/objects.py | 32 +++++++++++++++++++++++- coolamqp/uplink/connection/connection.py | 1 + coolamqp/uplink/handshake.py | 4 ++- docs/basics.rst | 8 ++++++ docs/conf.py | 2 +- tests/test_clustering/test_a.py | 5 +++- tests/test_clustering/test_things.py | 2 +- 10 files changed, 61 insertions(+), 6 deletions(-) diff --git a/coolamqp/__init__.py b/coolamqp/__init__.py index 955cb63..09e0822 100644 --- a/coolamqp/__init__.py +++ b/coolamqp/__init__.py @@ -1 +1 @@ -__version__ = '1.4.4a1' +__version__ = '1.5.0a1' diff --git a/coolamqp/clustering/cluster.py b/coolamqp/clustering/cluster.py index 80e5864..a3ec6e8 100644 --- a/coolamqp/clustering/cluster.py +++ b/coolamqp/clustering/cluster.py @@ -348,6 +348,13 @@ class Cluster(object): raise ConnectionDead( '[%s] Could not connect within %s seconds' % (self.name, timeout,)) + @property + def properties(self): + """ + Return a :class:`coolamqp.object.ServerProperties` if a connection was established + """ + return self.snr.properties + def shutdown(self, wait=True): # type: (bool) -> None """ Terminate all connections, release resources - finish the job. diff --git a/coolamqp/clustering/single.py b/coolamqp/clustering/single.py index cc86b45..1c856da 100644 --- a/coolamqp/clustering/single.py +++ b/coolamqp/clustering/single.py @@ -18,6 +18,10 @@ class SingleNodeReconnector(object): Connection to one node. It will do it's best to remain alive. """ + @property + def properties(self): + return self.connection.properties + def __init__(self, node_def, # type: coolamqp.objects.NodeDefinition attache_group, # type: coolamqp.attaches.AttacheGroup listener_thread, # type: coolamqp.uplink.ListenerThread diff --git a/coolamqp/objects.py b/coolamqp/objects.py index 675f741..eb6731d 100644 --- a/coolamqp/objects.py +++ b/coolamqp/objects.py @@ -10,7 +10,6 @@ import warnings import six -from coolamqp.framing.base import AMQPFrame from coolamqp.framing.definitions import \ BasicContentPropertyList as MessageProperties from coolamqp.framing.field_table import get_type_for @@ -232,6 +231,37 @@ class Exchange(object): Exchange.direct = Exchange() + +class ServerProperties(object): + """ + An object describing properties of the target server. + + :ivar version: tuple of (major version, minor version) + :ivar properties: dictionary of properties (key str, value any) + :ivar mechanisms: a list of strings, supported auth mechanisms + :ivar locales: locale in use + """ + + __slots__ = ('version', 'properties', 'mechanisms', 'locales') + + def __init__(self, data): + self.version = data.version_major, data.version_minor + self.properties = {} + for prop_name, prop_value in data.server_properties: + prop_name = toutf8(prop_name) + prop_value = prop_value[0] + if isinstance(prop_value, memoryview): + prop_value = prop_value.tobytes().decode('utf-8') + elif isinstance(prop_value, list): + prop_value = [toutf8(prop[0]) for prop in prop_value] + self.properties[prop_name] = prop_value + self.mechanisms = data.mechanisms.tobytes().decode('utf-8').split(' ') + self.locales = data.locales.tobytes().decode('utf-8') + + def __str__(self): + return '%s %s %s %s' % (self.version, repr(self.properties), self.mechanisms, self.locales) + + class Queue(object): """ This object represents a Queue that applications consume from or publish to. diff --git a/coolamqp/uplink/connection/connection.py b/coolamqp/uplink/connection/connection.py index bc157f1..0974f5c 100644 --- a/coolamqp/uplink/connection/connection.py +++ b/coolamqp/uplink/connection/connection.py @@ -119,6 +119,7 @@ class Connection(object): self.frame_max = None self.heartbeat = None self.extensions = [] + self.properties = None # To be filled in later self.listener_socket = None diff --git a/coolamqp/uplink/handshake.py b/coolamqp/uplink/handshake.py index acfb3b7..99d99bb 100644 --- a/coolamqp/uplink/handshake.py +++ b/coolamqp/uplink/handshake.py @@ -13,6 +13,8 @@ from coolamqp.framing.definitions import ConnectionStart, ConnectionStartOk, \ from coolamqp.framing.frames import AMQPMethodFrame from coolamqp.uplink.connection.states import ST_ONLINE from coolamqp.uplink.heartbeat import Heartbeater +from coolamqp.objects import ServerProperties + from coolamqp import __version__ PUBLISHER_CONFIRMS = b'publisher_confirms' @@ -100,7 +102,7 @@ class Handshaker(object): if label in SUPPORTED_EXTENSIONS: if fv[0]: self.connection.extensions.append(label) - + self.connection.properties = ServerProperties(payload) self.connection.watchdog(WATCHDOG_TIMEOUT, self.on_watchdog) self.connection.watch_for_method(0, ConnectionTune, self.on_connection_tune) diff --git a/docs/basics.rst b/docs/basics.rst index 81c42ac..1531b9b 100644 --- a/docs/basics.rst +++ b/docs/basics.rst @@ -34,3 +34,11 @@ Take care, as :class:`~coolamqp.objects.MessageProperties` will hash the keys found and store it within non-GCable memory. So each "variant" of message properties encountered will be compiled as a separate class. +Who am I talking to? +-------------------- + +:class:`coolamqp.clustering.Cluster` has a nice property, that will return None until the connection is established. +If it is, it will return something like this: + +.. autoclass:: coolamqp.objects.ServerProperties + :members: diff --git a/docs/conf.py b/docs/conf.py index 3c2a143..29896f7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,7 +48,7 @@ master_doc = 'index' # General information about the project. project = u'CoolAMQP' -copyright = u'2016-2020, SMOK sp. z o. o.' +copyright = u'2016-2024, SMOK sp. z o. o.' author = u'SMOK sp. z o. o.' # The version info for the project you're documenting, acts as replacement for diff --git a/tests/test_clustering/test_a.py b/tests/test_clustering/test_a.py index 8383c05..27f5d69 100644 --- a/tests/test_clustering/test_a.py +++ b/tests/test_clustering/test_a.py @@ -23,11 +23,14 @@ logging.basicConfig(level=logging.DEBUG) class TestA(unittest.TestCase): def setUp(self): self.c = Cluster([NODE]) - self.c.start() + self.c.start(timeout=20) def tearDown(self): self.c.shutdown() + def test_properties(self): + self.assertEqual(self.c.properties.properties['product'], 'RabbitMQ') + def test_queue_bind(self): queue = Queue('my-queue') exchange = Exchange('my-exchange', type='topic') diff --git a/tests/test_clustering/test_things.py b/tests/test_clustering/test_things.py index 98ee359..e49fa12 100644 --- a/tests/test_clustering/test_things.py +++ b/tests/test_clustering/test_things.py @@ -77,7 +77,7 @@ class TestConnecting(unittest.TestCase): def test_start_called_multiple_times(self): c = Cluster([NODE]) - c.start(wait=True) + c.start(wait=True, timeout=20) self.assertRaises(RuntimeError, lambda: c.start()) c.shutdown(wait=True) -- GitLab