pysmq 1.0.7__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.
pysmq-1.0.7/PKG-INFO ADDED
@@ -0,0 +1,262 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysmq
3
+ Version: 1.0.7
4
+ Summary: Python client for SuhaibMessageQueue
5
+ Author-email: Suhaib MessageQueue <example@example.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.7
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Topic :: System :: Networking
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: grpcio>=1.50.0
21
+ Requires-Dist: protobuf>=4.21.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: grpcio-tools>=1.50.0; extra == "dev"
24
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
25
+ Requires-Dist: black>=22.0.0; extra == "dev"
26
+ Requires-Dist: isort>=5.10.0; extra == "dev"
27
+ Requires-Dist: flake8>=5.0.0; extra == "dev"
28
+
29
+ # PySMQ: Python Client for SuhaibMessageQueue
30
+
31
+ This package provides a Python client for interacting with [SuhaibMessageQueue](https://github.com/Suhaibinator/SuhaibMessageQueue), a simple and efficient message queue service.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ # From PyPI (once published)
37
+ pip install pysmq
38
+
39
+ # From source
40
+ git clone https://github.com/Suhaibinator/SuhaibMessageQueue.git
41
+ cd SuhaibMessageQueue
42
+ pip install -e ./pysmq
43
+ ```
44
+
45
+ ## Dependencies
46
+
47
+ - Python 3.7+
48
+ - grpcio
49
+ - protobuf
50
+
51
+ ## Quick Start
52
+
53
+ ### Creating a client and publishing messages
54
+
55
+ ```python
56
+ from pysmq.client import Client
57
+
58
+ # Create a client
59
+ with Client(host="localhost", port=8097) as client:
60
+ # Create a topic
61
+ client.create_topic("my-topic")
62
+
63
+ # Publish a message
64
+ offset = client.produce("my-topic", b"Hello, SMQ!")
65
+ print(f"Message published at offset {offset}")
66
+ ```
67
+
68
+ ### Consuming messages
69
+
70
+ ```python
71
+ from pysmq.client import Client
72
+
73
+ # Create a client
74
+ with Client(host="localhost", port=8097) as client:
75
+ # Consume the latest message
76
+ message, offset = client.consume_latest("my-topic")
77
+ print(f"Latest message: {message.decode('utf-8')}, offset: {offset}")
78
+
79
+ # Consume the earliest message
80
+ message, offset = client.consume_earliest("my-topic")
81
+ print(f"Earliest message: {message.decode('utf-8')}, offset: {offset}")
82
+
83
+ # Consume a specific message
84
+ message, offset = client.consume("my-topic", 5) # offset 5
85
+ print(f"Message at offset 5: {message.decode('utf-8')}")
86
+ ```
87
+
88
+ ### Streaming messages
89
+
90
+ ```python
91
+ from pysmq.client import Client
92
+
93
+ # Create a client
94
+ with Client(host="localhost", port=8097) as client:
95
+ # Stream produce messages
96
+ messages = [b"Message 1", b"Message 2", b"Message 3"]
97
+ last_offset = client.stream_produce("my-topic", messages)
98
+ print(f"Last message published at offset {last_offset}")
99
+
100
+ # Stream consume messages (continuous)
101
+ for message, offset in client.stream_consume("my-topic", 0):
102
+ print(f"Received message: {message.decode('utf-8')}, offset: {offset}")
103
+ # Break the loop when needed
104
+ if offset >= 10:
105
+ break
106
+ ```
107
+
108
+ ### Secure Connection (mTLS)
109
+
110
+ ```python
111
+ from pysmq.client import Client
112
+ from pysmq.config import ClientTLSConfig
113
+
114
+ # Create TLS configuration
115
+ tls_config = ClientTLSConfig(
116
+ cert_file="/path/to/client.crt",
117
+ key_file="/path/to/client.key",
118
+ ca_file="/path/to/ca.crt"
119
+ )
120
+
121
+ # Create a secure client
122
+ with Client(host="localhost", port=8097, tls_config=tls_config) as client:
123
+ # Use the client as normal
124
+ client.create_topic("secure-topic")
125
+ offset = client.produce("secure-topic", b"Secure message")
126
+ print(f"Secure message published at offset {offset}")
127
+ ```
128
+
129
+ ## API Overview
130
+
131
+ ### Client
132
+
133
+ The `Client` class provides methods for interacting with the SMQ server.
134
+
135
+ ```python
136
+ # Constructor
137
+ client = Client(
138
+ host="localhost",
139
+ port=8097,
140
+ tls_config=None, # Optional: ClientTLSConfig for secure connections
141
+ max_send_message_size_mb=1024, # Optional: Maximum size of messages to send
142
+ max_receive_message_size_mb=1024 # Optional: Maximum size of messages to receive
143
+ )
144
+ ```
145
+
146
+ ### Topic Management
147
+
148
+ ```python
149
+ # Create a topic
150
+ client.create_topic(topic)
151
+ ```
152
+
153
+ ### Message Production
154
+
155
+ ```python
156
+ # Produce a single message
157
+ offset = client.produce(topic, message_bytes)
158
+
159
+ # Produce a stream of messages
160
+ last_offset = client.stream_produce(topic, messages_iterable)
161
+ ```
162
+
163
+ ### Message Consumption
164
+
165
+ ```python
166
+ # Consume a single message at a specific offset
167
+ message, offset = client.consume(topic, offset)
168
+
169
+ # Consume the earliest available message
170
+ message, offset = client.consume_earliest(topic)
171
+
172
+ # Consume the latest message
173
+ message, offset = client.consume_latest(topic)
174
+
175
+ # Stream consume messages (returns an iterator)
176
+ for message, offset in client.stream_consume(topic, start_offset):
177
+ # Process each message
178
+ pass
179
+ ```
180
+
181
+ ### Offset Management
182
+
183
+ ```python
184
+ # Get the latest offset for a topic
185
+ latest_offset = client.get_latest_offset(topic)
186
+
187
+ # Get the earliest available offset for a topic
188
+ earliest_offset = client.get_earliest_offset(topic)
189
+
190
+ # Delete all messages up to and including the specified offset
191
+ client.delete_until_offset(topic, offset)
192
+ ```
193
+
194
+ ### Bulk Operations
195
+
196
+ ```python
197
+ # Retrieve a batch of messages
198
+ response = client.bulk_retrieve(topic, start_offset, limit)
199
+ for message in response.messages:
200
+ # Process each message
201
+ message_bytes = message.message
202
+ message_offset = message.offset
203
+ ```
204
+
205
+ ### Connection Management
206
+
207
+ ```python
208
+ # Connect to the server (optional, happens automatically on first operation)
209
+ client.connect()
210
+
211
+ # Close the connection (or use 'with' statement)
212
+ client.close()
213
+ ```
214
+
215
+ ## Exception Handling
216
+
217
+ The client throws specific exceptions for different types of errors:
218
+
219
+ ```python
220
+ from pysmq.exceptions import (
221
+ SMQException, # Base exception for all SMQ errors
222
+ SMQConnectionError, # Connection issues
223
+ SMQAuthenticationError, # TLS/authentication issues
224
+ SMQProduceError, # Issues with producing messages
225
+ SMQConsumeError, # Issues with consuming messages
226
+ SMQTopicCreationError, # Issues with creating topics
227
+ SMQOffsetError, # Issues with offsets
228
+ SMQTimeoutError, # Timeout errors
229
+ )
230
+
231
+ try:
232
+ client.produce("my-topic", b"Hello")
233
+ except SMQProduceError as e:
234
+ print(f"Failed to produce message: {e}")
235
+ # Access the original error if needed
236
+ original_error = e.original_error
237
+ ```
238
+
239
+ ## Configuration
240
+
241
+ The client supports various configuration options:
242
+
243
+ ```python
244
+ from pysmq.config import ClientTLSConfig, ClientConfig
245
+
246
+ # Default timeout values can be accessed or modified
247
+ ClientConfig.DEFAULT_TIMEOUT = 60.0 # Default timeout for most operations
248
+ ClientConfig.DEFAULT_TOPIC_TIMEOUT = 2.0 # Default timeout for topic creation
249
+ ClientConfig.DEFAULT_DELETE_TIMEOUT = 2.0 # Default timeout for deletion operations
250
+ ```
251
+
252
+ ## Examples
253
+
254
+ For more detailed examples, see the [examples](examples/) directory:
255
+
256
+ - [Basic Publishing](examples/publish_example.py)
257
+ - [Message Consumption](examples/subscribe_example.py)
258
+ - [Secure Connection](examples/secure_connection_example.py)
259
+
260
+ ## License
261
+
262
+ This project is licensed under the MIT License - see the LICENSE file for details.
pysmq-1.0.7/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # PySMQ: Python Client for SuhaibMessageQueue
2
+
3
+ This package provides a Python client for interacting with [SuhaibMessageQueue](https://github.com/Suhaibinator/SuhaibMessageQueue), a simple and efficient message queue service.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # From PyPI (once published)
9
+ pip install pysmq
10
+
11
+ # From source
12
+ git clone https://github.com/Suhaibinator/SuhaibMessageQueue.git
13
+ cd SuhaibMessageQueue
14
+ pip install -e ./pysmq
15
+ ```
16
+
17
+ ## Dependencies
18
+
19
+ - Python 3.7+
20
+ - grpcio
21
+ - protobuf
22
+
23
+ ## Quick Start
24
+
25
+ ### Creating a client and publishing messages
26
+
27
+ ```python
28
+ from pysmq.client import Client
29
+
30
+ # Create a client
31
+ with Client(host="localhost", port=8097) as client:
32
+ # Create a topic
33
+ client.create_topic("my-topic")
34
+
35
+ # Publish a message
36
+ offset = client.produce("my-topic", b"Hello, SMQ!")
37
+ print(f"Message published at offset {offset}")
38
+ ```
39
+
40
+ ### Consuming messages
41
+
42
+ ```python
43
+ from pysmq.client import Client
44
+
45
+ # Create a client
46
+ with Client(host="localhost", port=8097) as client:
47
+ # Consume the latest message
48
+ message, offset = client.consume_latest("my-topic")
49
+ print(f"Latest message: {message.decode('utf-8')}, offset: {offset}")
50
+
51
+ # Consume the earliest message
52
+ message, offset = client.consume_earliest("my-topic")
53
+ print(f"Earliest message: {message.decode('utf-8')}, offset: {offset}")
54
+
55
+ # Consume a specific message
56
+ message, offset = client.consume("my-topic", 5) # offset 5
57
+ print(f"Message at offset 5: {message.decode('utf-8')}")
58
+ ```
59
+
60
+ ### Streaming messages
61
+
62
+ ```python
63
+ from pysmq.client import Client
64
+
65
+ # Create a client
66
+ with Client(host="localhost", port=8097) as client:
67
+ # Stream produce messages
68
+ messages = [b"Message 1", b"Message 2", b"Message 3"]
69
+ last_offset = client.stream_produce("my-topic", messages)
70
+ print(f"Last message published at offset {last_offset}")
71
+
72
+ # Stream consume messages (continuous)
73
+ for message, offset in client.stream_consume("my-topic", 0):
74
+ print(f"Received message: {message.decode('utf-8')}, offset: {offset}")
75
+ # Break the loop when needed
76
+ if offset >= 10:
77
+ break
78
+ ```
79
+
80
+ ### Secure Connection (mTLS)
81
+
82
+ ```python
83
+ from pysmq.client import Client
84
+ from pysmq.config import ClientTLSConfig
85
+
86
+ # Create TLS configuration
87
+ tls_config = ClientTLSConfig(
88
+ cert_file="/path/to/client.crt",
89
+ key_file="/path/to/client.key",
90
+ ca_file="/path/to/ca.crt"
91
+ )
92
+
93
+ # Create a secure client
94
+ with Client(host="localhost", port=8097, tls_config=tls_config) as client:
95
+ # Use the client as normal
96
+ client.create_topic("secure-topic")
97
+ offset = client.produce("secure-topic", b"Secure message")
98
+ print(f"Secure message published at offset {offset}")
99
+ ```
100
+
101
+ ## API Overview
102
+
103
+ ### Client
104
+
105
+ The `Client` class provides methods for interacting with the SMQ server.
106
+
107
+ ```python
108
+ # Constructor
109
+ client = Client(
110
+ host="localhost",
111
+ port=8097,
112
+ tls_config=None, # Optional: ClientTLSConfig for secure connections
113
+ max_send_message_size_mb=1024, # Optional: Maximum size of messages to send
114
+ max_receive_message_size_mb=1024 # Optional: Maximum size of messages to receive
115
+ )
116
+ ```
117
+
118
+ ### Topic Management
119
+
120
+ ```python
121
+ # Create a topic
122
+ client.create_topic(topic)
123
+ ```
124
+
125
+ ### Message Production
126
+
127
+ ```python
128
+ # Produce a single message
129
+ offset = client.produce(topic, message_bytes)
130
+
131
+ # Produce a stream of messages
132
+ last_offset = client.stream_produce(topic, messages_iterable)
133
+ ```
134
+
135
+ ### Message Consumption
136
+
137
+ ```python
138
+ # Consume a single message at a specific offset
139
+ message, offset = client.consume(topic, offset)
140
+
141
+ # Consume the earliest available message
142
+ message, offset = client.consume_earliest(topic)
143
+
144
+ # Consume the latest message
145
+ message, offset = client.consume_latest(topic)
146
+
147
+ # Stream consume messages (returns an iterator)
148
+ for message, offset in client.stream_consume(topic, start_offset):
149
+ # Process each message
150
+ pass
151
+ ```
152
+
153
+ ### Offset Management
154
+
155
+ ```python
156
+ # Get the latest offset for a topic
157
+ latest_offset = client.get_latest_offset(topic)
158
+
159
+ # Get the earliest available offset for a topic
160
+ earliest_offset = client.get_earliest_offset(topic)
161
+
162
+ # Delete all messages up to and including the specified offset
163
+ client.delete_until_offset(topic, offset)
164
+ ```
165
+
166
+ ### Bulk Operations
167
+
168
+ ```python
169
+ # Retrieve a batch of messages
170
+ response = client.bulk_retrieve(topic, start_offset, limit)
171
+ for message in response.messages:
172
+ # Process each message
173
+ message_bytes = message.message
174
+ message_offset = message.offset
175
+ ```
176
+
177
+ ### Connection Management
178
+
179
+ ```python
180
+ # Connect to the server (optional, happens automatically on first operation)
181
+ client.connect()
182
+
183
+ # Close the connection (or use 'with' statement)
184
+ client.close()
185
+ ```
186
+
187
+ ## Exception Handling
188
+
189
+ The client throws specific exceptions for different types of errors:
190
+
191
+ ```python
192
+ from pysmq.exceptions import (
193
+ SMQException, # Base exception for all SMQ errors
194
+ SMQConnectionError, # Connection issues
195
+ SMQAuthenticationError, # TLS/authentication issues
196
+ SMQProduceError, # Issues with producing messages
197
+ SMQConsumeError, # Issues with consuming messages
198
+ SMQTopicCreationError, # Issues with creating topics
199
+ SMQOffsetError, # Issues with offsets
200
+ SMQTimeoutError, # Timeout errors
201
+ )
202
+
203
+ try:
204
+ client.produce("my-topic", b"Hello")
205
+ except SMQProduceError as e:
206
+ print(f"Failed to produce message: {e}")
207
+ # Access the original error if needed
208
+ original_error = e.original_error
209
+ ```
210
+
211
+ ## Configuration
212
+
213
+ The client supports various configuration options:
214
+
215
+ ```python
216
+ from pysmq.config import ClientTLSConfig, ClientConfig
217
+
218
+ # Default timeout values can be accessed or modified
219
+ ClientConfig.DEFAULT_TIMEOUT = 60.0 # Default timeout for most operations
220
+ ClientConfig.DEFAULT_TOPIC_TIMEOUT = 2.0 # Default timeout for topic creation
221
+ ClientConfig.DEFAULT_DELETE_TIMEOUT = 2.0 # Default timeout for deletion operations
222
+ ```
223
+
224
+ ## Examples
225
+
226
+ For more detailed examples, see the [examples](examples/) directory:
227
+
228
+ - [Basic Publishing](examples/publish_example.py)
229
+ - [Message Consumption](examples/subscribe_example.py)
230
+ - [Secure Connection](examples/secure_connection_example.py)
231
+
232
+ ## License
233
+
234
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example showing how to publish messages to SMQ using the Python client.
4
+ """
5
+ import time
6
+ import json
7
+
8
+ from pysmq.client import Client
9
+ from pysmq.config import ClientTLSConfig
10
+
11
+
12
+ def main():
13
+ # Replace with actual server details
14
+ host = "localhost"
15
+ port = 8097
16
+
17
+ # Create a client with default settings (insecure connection)
18
+ with Client(host=host, port=port) as client:
19
+ # Connect to the server (this is optional but a good test)
20
+ print("Connecting to SMQ server...")
21
+ client.connect()
22
+ print("Connected!")
23
+
24
+ # Create a topic if it doesn't exist
25
+ topic = "example-topic"
26
+ try:
27
+ print(f"Creating topic '{topic}'...")
28
+ client.create_topic(topic)
29
+ print(f"Topic '{topic}' created successfully!")
30
+ except Exception as e:
31
+ # Topic may already exist, which is okay
32
+ print(f"Note: {e}")
33
+
34
+ # Publish a few messages
35
+ for i in range(5):
36
+ # Create a sample message (convert to bytes)
37
+ message = {
38
+ "id": i,
39
+ "timestamp": time.time(),
40
+ "content": f"Message #{i}",
41
+ }
42
+ message_bytes = json.dumps(message).encode('utf-8')
43
+
44
+ # Publish the message
45
+ print(f"Publishing message {i}...")
46
+ offset = client.produce(topic, message_bytes)
47
+ print(f"Message published at offset {offset}")
48
+
49
+ # Small delay between messages for demonstration
50
+ time.sleep(0.5)
51
+
52
+ print("All messages published successfully!")
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example showing how to establish a secure connection to the SMQ server using mTLS.
4
+ """
5
+ import json
6
+ import time
7
+ import os
8
+
9
+ from pysmq.client import Client
10
+ from pysmq.config import ClientTLSConfig
11
+ from pysmq.exceptions import SMQAuthenticationError, SMQConnectionError
12
+
13
+
14
+ def main():
15
+ # Replace with actual server details
16
+ host = "localhost"
17
+ port = 8097
18
+
19
+ # Replace with actual paths to your TLS certificate files
20
+ # These paths should point to your client certificate, client key,
21
+ # and CA certificate that signed the server's certificate
22
+ cert_file = os.environ.get("CLIENT_CERT", "/path/to/client.crt")
23
+ key_file = os.environ.get("CLIENT_KEY", "/path/to/client.key")
24
+ ca_file = os.environ.get("CA_CERT", "/path/to/ca.crt")
25
+
26
+ # Check if the certificate files exist
27
+ for file_path, file_name in [
28
+ (cert_file, "Client certificate"),
29
+ (key_file, "Client key"),
30
+ (ca_file, "CA certificate")
31
+ ]:
32
+ if not os.path.exists(file_path):
33
+ print(f"Warning: {file_name} file not found at {file_path}")
34
+ print("This example requires valid TLS certificates to work.")
35
+ print("You can set the paths via environment variables:")
36
+ print(" CLIENT_CERT: Path to client certificate file")
37
+ print(" CLIENT_KEY: Path to client key file")
38
+ print(" CA_CERT: Path to CA certificate file")
39
+ return
40
+
41
+ # Create the TLS configuration
42
+ tls_config = ClientTLSConfig(
43
+ cert_file=cert_file,
44
+ key_file=key_file,
45
+ ca_file=ca_file,
46
+ )
47
+
48
+ try:
49
+ print("Creating secure client with mTLS...")
50
+ # Create a client with mTLS configuration
51
+ with Client(host=host, port=port, tls_config=tls_config) as client:
52
+ # Connect to the server
53
+ print("Connecting to SMQ server securely...")
54
+ client.connect()
55
+ print("Connected securely!")
56
+
57
+ # Example: Create a topic
58
+ topic = "secure-example-topic"
59
+ try:
60
+ print(f"Creating topic '{topic}'...")
61
+ client.create_topic(topic)
62
+ print(f"Topic '{topic}' created successfully!")
63
+ except Exception as e:
64
+ # Topic may already exist, which is okay
65
+ print(f"Note: {e}")
66
+
67
+ # Example: Publish a message
68
+ message = {
69
+ "id": 1,
70
+ "timestamp": time.time(),
71
+ "content": "Secure message",
72
+ "secure": True,
73
+ }
74
+ message_bytes = json.dumps(message).encode('utf-8')
75
+
76
+ print("Publishing a secure message...")
77
+ offset = client.produce(topic, message_bytes)
78
+ print(f"Message published securely at offset {offset}")
79
+
80
+ # Example: Consume the message
81
+ print("Consuming the message...")
82
+ received_bytes, received_offset = client.consume(topic, offset)
83
+
84
+ # Decode and print the message
85
+ received_message = json.loads(received_bytes.decode('utf-8'))
86
+ print(f"Received secure message at offset {received_offset}:")
87
+ print(f" ID: {received_message.get('id')}")
88
+ print(f" Timestamp: {received_message.get('timestamp')}")
89
+ print(f" Content: {received_message.get('content')}")
90
+ print(f" Secure: {received_message.get('secure')}")
91
+
92
+ print("Secure connection example completed successfully!")
93
+
94
+ except SMQAuthenticationError as e:
95
+ print(f"TLS Authentication Error: {e}")
96
+ print("Make sure your certificates are correctly configured and valid.")
97
+ except SMQConnectionError as e:
98
+ print(f"Connection Error: {e}")
99
+ print("Make sure the server is running and configured for mTLS.")
100
+ except Exception as e:
101
+ print(f"Unexpected Error: {e}")
102
+
103
+
104
+ if __name__ == "__main__":
105
+ main()