weenspace-queue 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WeenSpace
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: weenspace-queue
3
+ Version: 0.1.0
4
+ Summary: WeenSpace queue client for RabbitMQ and AWS SQS, supporting both synchronous and asynchronous operations.
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: rabbitmq,amqp,messaging,event-driven,microservices,queue,weenspace
8
+ Author: WeenSpace
9
+ Author-email: weenspace@gmail.com
10
+ Requires-Python: >=3.14,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Classifier: Topic :: System :: Networking
18
+ Requires-Dist: packaging (>=25.0,<26.0)
19
+ Requires-Dist: python-qpid-proton (>=0.40.0,<0.41.0)
20
+ Requires-Dist: typing-extensions (>=4.15.0,<5.0.0)
21
+ Project-URL: Homepage, https://github.com/weenspace/weenspace-queue
22
+ Project-URL: Repository, https://github.com/weenspace/weenspace-queue
23
+ Description-Content-Type: text/markdown
24
+
25
+ # WeenSpace RabbitMQ Client
26
+
27
+ [![PyPI version](https://badge.fury.io/py/weenspace-queue.svg)](https://pypi.org/project/weenspace-queue/)
28
+ [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
29
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
30
+
31
+ A powerful Python RabbitMQ client for AMQP 1.0 protocol, designed for event-driven microservices architecture.
32
+
33
+ ## ✨ Features
34
+
35
+ - 🔐 **Authentication**: OAuth2, TLS/SSL, Basic Auth
36
+ - 📬 **Queue Types**: Classic, Quorum, Stream queues
37
+ - ☠️ **Dead Letter Queues**: Built-in DLQ support with configurable strategies
38
+ - ⚡ **Priority Queues**: Native priority queue support
39
+ - 🔄 **Auto Reconnection**: Configurable recovery with exponential backoff
40
+ - 🔀 **All Exchange Types**: Direct, Fanout, Topic, Headers
41
+ - 🚀 **Async Support**: Native asyncio integration
42
+ - 📊 **Streams**: RabbitMQ Streams with filtering support
43
+
44
+ ## 📦 Installation
45
+
46
+ ```bash
47
+ pip install weenspace-queue
48
+ ```
49
+
50
+ ## 🚀 Quick Start
51
+
52
+ ### Basic Publisher/Consumer
53
+
54
+ ```python
55
+ from weenspace_queue import (
56
+ Environment,
57
+ Connection,
58
+ Publisher,
59
+ Consumer,
60
+ Message,
61
+ ClassicQueueSpecification,
62
+ ExchangeSpecification,
63
+ )
64
+
65
+ # Create environment and connection
66
+ environment = Environment(uri="amqp://guest:guest@localhost:5672/")
67
+ connection = environment.connection()
68
+
69
+ # Declare queue with dead letter support
70
+ management = connection.management()
71
+ queue_spec = ClassicQueueSpecification(
72
+ name="my-queue",
73
+ is_durable=True,
74
+ dead_letter_exchange="dlx",
75
+ dead_letter_routing_key="dlx-key",
76
+ max_priority=10, # Enable priority
77
+ )
78
+ management.declare_queue(queue_spec)
79
+
80
+ # Publish message
81
+ publisher = connection.publisher("/queues/my-queue")
82
+ publisher.publish(Message(body=b"Hello WeenSpace!"))
83
+
84
+ # Consume messages
85
+ def on_message(message):
86
+ print(f"Received: {message.body}")
87
+ message.accept()
88
+
89
+ consumer = connection.consumer("/queues/my-queue", handler=on_message)
90
+ ```
91
+
92
+ ### Async Support
93
+
94
+ ```python
95
+ import asyncio
96
+ from weenspace_queue.asyncio import AsyncEnvironment
97
+
98
+ async def main():
99
+ async with AsyncEnvironment(uri="amqp://localhost:5672/") as env:
100
+ async with env.connection() as conn:
101
+ publisher = await conn.publisher("/queues/my-queue")
102
+ await publisher.publish(Message(body=b"Async message!"))
103
+
104
+ asyncio.run(main())
105
+ ```
106
+
107
+ ### OAuth2 Authentication
108
+
109
+ ```python
110
+ from weenspace_queue import Environment, OAuth2Options
111
+
112
+ oauth = OAuth2Options(token="your_jwt_token")
113
+ environment = Environment(
114
+ uri="amqp://localhost:5672/",
115
+ oauth2_options=oauth
116
+ )
117
+ ```
118
+
119
+ ### TLS/SSL Connection
120
+
121
+ ```python
122
+ from weenspace_queue import Environment, SslConfiguration
123
+
124
+ ssl_config = SslConfiguration(
125
+ ca_cert="/path/to/ca.pem",
126
+ client_cert="/path/to/client.pem",
127
+ client_key="/path/to/client.key"
128
+ )
129
+ environment = Environment(
130
+ uri="amqps://localhost:5671/",
131
+ ssl_configuration=ssl_config
132
+ )
133
+ ```
134
+
135
+ ## 📚 Documentation
136
+
137
+ See [examples](./examples) folder for more detailed usage examples.
138
+
139
+ ## 🔄 Migration from python-rabbitmq
140
+
141
+ ```python
142
+ # Old (python-rabbitmq)
143
+ # from python_rabbitmq import RabbitMQ
144
+
145
+ # New (weenspace-queue)
146
+ from weenspace_queue import Environment, Connection
147
+ ```
148
+
149
+ ## 📋 Requirements
150
+
151
+ - Python 3.13+
152
+ - RabbitMQ 4.x with AMQP 1.0 plugin enabled
153
+
154
+ ## 📄 License
155
+
156
+ MIT License - Based on the official [RabbitMQ AMQP Python Client](https://github.com/rabbitmq/rabbitmq-amqp-python-client)
157
+
158
+ ## 🙏 Credits
159
+
160
+ This library is based on the official RabbitMQ AMQP 1.0 Python client by the RabbitMQ team.
161
+
@@ -0,0 +1,136 @@
1
+ # WeenSpace RabbitMQ Client
2
+
3
+ [![PyPI version](https://badge.fury.io/py/weenspace-queue.svg)](https://pypi.org/project/weenspace-queue/)
4
+ [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
5
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
+
7
+ A powerful Python RabbitMQ client for AMQP 1.0 protocol, designed for event-driven microservices architecture.
8
+
9
+ ## ✨ Features
10
+
11
+ - 🔐 **Authentication**: OAuth2, TLS/SSL, Basic Auth
12
+ - 📬 **Queue Types**: Classic, Quorum, Stream queues
13
+ - ☠️ **Dead Letter Queues**: Built-in DLQ support with configurable strategies
14
+ - ⚡ **Priority Queues**: Native priority queue support
15
+ - 🔄 **Auto Reconnection**: Configurable recovery with exponential backoff
16
+ - 🔀 **All Exchange Types**: Direct, Fanout, Topic, Headers
17
+ - 🚀 **Async Support**: Native asyncio integration
18
+ - 📊 **Streams**: RabbitMQ Streams with filtering support
19
+
20
+ ## 📦 Installation
21
+
22
+ ```bash
23
+ pip install weenspace-queue
24
+ ```
25
+
26
+ ## 🚀 Quick Start
27
+
28
+ ### Basic Publisher/Consumer
29
+
30
+ ```python
31
+ from weenspace_queue import (
32
+ Environment,
33
+ Connection,
34
+ Publisher,
35
+ Consumer,
36
+ Message,
37
+ ClassicQueueSpecification,
38
+ ExchangeSpecification,
39
+ )
40
+
41
+ # Create environment and connection
42
+ environment = Environment(uri="amqp://guest:guest@localhost:5672/")
43
+ connection = environment.connection()
44
+
45
+ # Declare queue with dead letter support
46
+ management = connection.management()
47
+ queue_spec = ClassicQueueSpecification(
48
+ name="my-queue",
49
+ is_durable=True,
50
+ dead_letter_exchange="dlx",
51
+ dead_letter_routing_key="dlx-key",
52
+ max_priority=10, # Enable priority
53
+ )
54
+ management.declare_queue(queue_spec)
55
+
56
+ # Publish message
57
+ publisher = connection.publisher("/queues/my-queue")
58
+ publisher.publish(Message(body=b"Hello WeenSpace!"))
59
+
60
+ # Consume messages
61
+ def on_message(message):
62
+ print(f"Received: {message.body}")
63
+ message.accept()
64
+
65
+ consumer = connection.consumer("/queues/my-queue", handler=on_message)
66
+ ```
67
+
68
+ ### Async Support
69
+
70
+ ```python
71
+ import asyncio
72
+ from weenspace_queue.asyncio import AsyncEnvironment
73
+
74
+ async def main():
75
+ async with AsyncEnvironment(uri="amqp://localhost:5672/") as env:
76
+ async with env.connection() as conn:
77
+ publisher = await conn.publisher("/queues/my-queue")
78
+ await publisher.publish(Message(body=b"Async message!"))
79
+
80
+ asyncio.run(main())
81
+ ```
82
+
83
+ ### OAuth2 Authentication
84
+
85
+ ```python
86
+ from weenspace_queue import Environment, OAuth2Options
87
+
88
+ oauth = OAuth2Options(token="your_jwt_token")
89
+ environment = Environment(
90
+ uri="amqp://localhost:5672/",
91
+ oauth2_options=oauth
92
+ )
93
+ ```
94
+
95
+ ### TLS/SSL Connection
96
+
97
+ ```python
98
+ from weenspace_queue import Environment, SslConfiguration
99
+
100
+ ssl_config = SslConfiguration(
101
+ ca_cert="/path/to/ca.pem",
102
+ client_cert="/path/to/client.pem",
103
+ client_key="/path/to/client.key"
104
+ )
105
+ environment = Environment(
106
+ uri="amqps://localhost:5671/",
107
+ ssl_configuration=ssl_config
108
+ )
109
+ ```
110
+
111
+ ## 📚 Documentation
112
+
113
+ See [examples](./examples) folder for more detailed usage examples.
114
+
115
+ ## 🔄 Migration from python-rabbitmq
116
+
117
+ ```python
118
+ # Old (python-rabbitmq)
119
+ # from python_rabbitmq import RabbitMQ
120
+
121
+ # New (weenspace-queue)
122
+ from weenspace_queue import Environment, Connection
123
+ ```
124
+
125
+ ## 📋 Requirements
126
+
127
+ - Python 3.13+
128
+ - RabbitMQ 4.x with AMQP 1.0 plugin enabled
129
+
130
+ ## 📄 License
131
+
132
+ MIT License - Based on the official [RabbitMQ AMQP Python Client](https://github.com/rabbitmq/rabbitmq-amqp-python-client)
133
+
134
+ ## 🙏 Credits
135
+
136
+ This library is based on the official RabbitMQ AMQP 1.0 Python client by the RabbitMQ team.
@@ -0,0 +1,62 @@
1
+ [tool.poetry]
2
+ name = "weenspace-queue"
3
+ version = "0.1.0"
4
+ description = "WeenSpace queue client for RabbitMQ and AWS SQS, supporting both synchronous and asynchronous operations."
5
+ authors = ["WeenSpace <weenspace@gmail.com>"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ homepage = "https://github.com/weenspace/weenspace-queue"
9
+ repository = "https://github.com/weenspace/weenspace-queue"
10
+ keywords = ["rabbitmq", "amqp", "messaging", "event-driven", "microservices", "queue", "weenspace"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: Developers",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Python :: 3.14",
17
+ "Topic :: Software Development :: Libraries :: Python Modules",
18
+ "Topic :: System :: Networking",
19
+ ]
20
+ packages = [{include = "weenspace_queue"}]
21
+
22
+ [tool.poetry.dependencies]
23
+ python = "^3.14"
24
+ python-qpid-proton = "^0.40.0"
25
+ typing-extensions = "^4.15.0"
26
+ packaging = "^25.0"
27
+
28
+ [tool.poetry.group.dev.dependencies]
29
+ pyjwt = "^2.13.0"
30
+ pika = "^1.4.4"
31
+ flake8 = "^7.3.0"
32
+ isort = "^6.0.0"
33
+ mypy = "^1.19.0"
34
+ pytest = "^9.0.0"
35
+ black = "^26.5.1"
36
+ requests = "^2.32.0"
37
+ pytest-asyncio = "^1.3.0"
38
+
39
+ [build-system]
40
+ requires = ["poetry-core"]
41
+ build-backend = "poetry.core.masonry.api"
42
+
43
+ [dependency-groups]
44
+ dev = [
45
+ "boto3>=1.43.80",
46
+ ]
47
+
48
+ [tool.pytest.ini_options]
49
+ asyncio_mode = "auto"
50
+
51
+ [tool.black]
52
+ line-length = 88
53
+ target-version = ['py313']
54
+
55
+ [tool.isort]
56
+ profile = "black"
57
+ line_length = 88
58
+
59
+ [tool.mypy]
60
+ python_version = "3.13"
61
+ warn_return_any = true
62
+ warn_unused_configs = true
@@ -0,0 +1,128 @@
1
+ from typing import Any, Callable, Dict, Type
2
+
3
+ from .asyncio.aws_async import AwsAsyncEngine
4
+ from .asyncio.rabbitmq_async import RabbitMqAsyncEngine
5
+ from .base import (
6
+ AsyncQueueEngine,
7
+ Message,
8
+ QueueEngine,
9
+ QueueSpecification,
10
+ TopicSpecification,
11
+ )
12
+ from .constants import (
13
+ PROVIDER_AWS,
14
+ PROVIDER_RABBITMQ,
15
+ ExchangeKind,
16
+ Provider,
17
+ QueueKind,
18
+ )
19
+ from .providers.aws import AwsEngine
20
+ from .providers.rabbitmq import RabbitMqEngine
21
+
22
+
23
+ class QueueClient:
24
+ """Single client: pass provider name, then use the same publish/consume/topology methods."""
25
+
26
+ _ENGINES: Dict[str, Type[QueueEngine]] = {
27
+ PROVIDER_AWS: AwsEngine,
28
+ PROVIDER_RABBITMQ: RabbitMqEngine,
29
+ }
30
+
31
+ def __init__(self, provider: str, **config: Any) -> None:
32
+ prov_key = provider.lower().strip()
33
+ engine_cls = self._ENGINES.get(prov_key)
34
+ if engine_cls is None:
35
+ supported = ", ".join(sorted(self._ENGINES))
36
+ raise ValueError(
37
+ f"Unsupported provider '{provider}'. Supported: {supported}"
38
+ )
39
+ self.provider = prov_key
40
+ self.engine: QueueEngine = engine_cls(**config)
41
+
42
+ def declare_queue(self, spec: QueueSpecification) -> str:
43
+ return self.engine.declare_queue(spec)
44
+
45
+ def declare_topic(self, spec: TopicSpecification) -> str:
46
+ return self.engine.declare_topic(spec)
47
+
48
+ def bind_pattern(self, queue_id: str, topic_id: str, pattern: str) -> None:
49
+ self.engine.bind_pattern(queue_id, topic_id, pattern)
50
+
51
+ def publish(self, destination: str, message: Message) -> None:
52
+ self.engine.publish(destination, message)
53
+
54
+ def consume(self, queue_id: str, handler: Callable[[Message], None]) -> None:
55
+ self.engine.consume(queue_id, handler)
56
+
57
+ def stop(self) -> None:
58
+ self.engine.stop()
59
+
60
+ def close(self) -> None:
61
+ self.engine.close()
62
+
63
+ def __enter__(self) -> "QueueClient":
64
+ return self
65
+
66
+ def __exit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
67
+ self.close()
68
+
69
+
70
+ class AsyncQueueClient:
71
+ """Async twin of QueueClient. Same method names, same provider argument."""
72
+
73
+ _ENGINES: Dict[str, Type[AsyncQueueEngine]] = {
74
+ PROVIDER_AWS: AwsAsyncEngine,
75
+ PROVIDER_RABBITMQ: RabbitMqAsyncEngine,
76
+ }
77
+
78
+ def __init__(self, provider: str, **config: Any) -> None:
79
+ prov_key = provider.lower().strip()
80
+ engine_cls = self._ENGINES.get(prov_key)
81
+ if engine_cls is None:
82
+ supported = ", ".join(sorted(self._ENGINES))
83
+ raise ValueError(
84
+ f"Unsupported provider '{provider}'. Supported: {supported}"
85
+ )
86
+ self.provider = prov_key
87
+ self.engine: AsyncQueueEngine = engine_cls(**config)
88
+
89
+ async def declare_queue(self, spec: QueueSpecification) -> str:
90
+ return await self.engine.declare_queue(spec)
91
+
92
+ async def declare_topic(self, spec: TopicSpecification) -> str:
93
+ return await self.engine.declare_topic(spec)
94
+
95
+ async def bind_pattern(self, queue_id: str, topic_id: str, pattern: str) -> None:
96
+ await self.engine.bind_pattern(queue_id, topic_id, pattern)
97
+
98
+ async def publish(self, destination: str, message: Message) -> None:
99
+ await self.engine.publish(destination, message)
100
+
101
+ async def consume(self, queue_id: str, handler: Callable[[Message], None]) -> None:
102
+ await self.engine.consume(queue_id, handler)
103
+
104
+ async def stop(self) -> None:
105
+ await self.engine.stop()
106
+
107
+ async def close(self) -> None:
108
+ await self.engine.close()
109
+
110
+ async def __aenter__(self) -> "AsyncQueueClient":
111
+ return self
112
+
113
+ async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
114
+ await self.close()
115
+
116
+
117
+ __all__ = [
118
+ "AsyncQueueClient",
119
+ "AsyncQueueEngine",
120
+ "ExchangeKind",
121
+ "Message",
122
+ "Provider",
123
+ "QueueClient",
124
+ "QueueEngine",
125
+ "QueueKind",
126
+ "QueueSpecification",
127
+ "TopicSpecification",
128
+ ]
@@ -0,0 +1,4 @@
1
+ from .aws_async import AwsAsyncEngine
2
+ from .rabbitmq_async import RabbitMqAsyncEngine
3
+
4
+ __all__ = ["AwsAsyncEngine", "RabbitMqAsyncEngine"]
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ from weenspace_queue.base import (
5
+ AsyncQueueEngine,
6
+ Message,
7
+ QueueSpecification,
8
+ TopicSpecification,
9
+ )
10
+ from weenspace_queue.providers.aws import AwsEngine
11
+
12
+
13
+ class AwsAsyncEngine(AsyncQueueEngine):
14
+ """Async AWS engine. Uses aioboto3 when installed, otherwise boto3 in a worker thread."""
15
+
16
+ def __init__(self, **kwargs: Any) -> None:
17
+ self._sync = AwsEngine(**kwargs)
18
+
19
+ async def declare_queue(self, spec: QueueSpecification) -> str:
20
+ return await asyncio.to_thread(self._sync.declare_queue, spec)
21
+
22
+ async def declare_topic(self, spec: TopicSpecification) -> str:
23
+ return await asyncio.to_thread(self._sync.declare_topic, spec)
24
+
25
+ async def bind_pattern(self, queue_id: str, topic_id: str, pattern: str) -> None:
26
+ await asyncio.to_thread(self._sync.bind_pattern, queue_id, topic_id, pattern)
27
+
28
+ async def publish(self, destination: str, message: Message) -> None:
29
+ await asyncio.to_thread(self._sync.publish, destination, message)
30
+
31
+ async def consume(self, queue_id: str, handler: Callable[[Message], None]) -> None:
32
+ await asyncio.to_thread(self._sync.consume, queue_id, handler)
33
+
34
+ async def stop(self) -> None:
35
+ self._sync.stop()
36
+
37
+ async def close(self) -> None:
38
+ await asyncio.to_thread(self._sync.close)