cledar-sdk 2.0.2__py3-none-any.whl → 2.1.0__py3-none-any.whl

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.
Files changed (85) hide show
  1. cledar/__init__.py +1 -0
  2. cledar/kafka/README.md +239 -0
  3. cledar/kafka/__init__.py +42 -0
  4. cledar/kafka/clients/base.py +117 -0
  5. cledar/kafka/clients/consumer.py +138 -0
  6. cledar/kafka/clients/producer.py +97 -0
  7. cledar/kafka/config/schemas.py +262 -0
  8. cledar/kafka/exceptions.py +17 -0
  9. cledar/kafka/handlers/dead_letter.py +88 -0
  10. cledar/kafka/handlers/parser.py +83 -0
  11. cledar/kafka/logger.py +5 -0
  12. cledar/kafka/models/input.py +17 -0
  13. cledar/kafka/models/message.py +14 -0
  14. cledar/kafka/models/output.py +12 -0
  15. cledar/kafka/tests/.env.test.kafka +3 -0
  16. cledar/kafka/tests/README.md +216 -0
  17. cledar/kafka/tests/conftest.py +104 -0
  18. cledar/kafka/tests/integration/__init__.py +1 -0
  19. cledar/kafka/tests/integration/conftest.py +78 -0
  20. cledar/kafka/tests/integration/helpers.py +47 -0
  21. cledar/kafka/tests/integration/test_consumer_integration.py +375 -0
  22. cledar/kafka/tests/integration/test_integration.py +394 -0
  23. cledar/kafka/tests/integration/test_producer_consumer_interaction.py +388 -0
  24. cledar/kafka/tests/integration/test_producer_integration.py +217 -0
  25. cledar/kafka/tests/unit/__init__.py +1 -0
  26. cledar/kafka/tests/unit/test_base_kafka_client.py +391 -0
  27. cledar/kafka/tests/unit/test_config_validation.py +609 -0
  28. cledar/kafka/tests/unit/test_dead_letter_handler.py +443 -0
  29. cledar/kafka/tests/unit/test_error_handling.py +674 -0
  30. cledar/kafka/tests/unit/test_input_parser.py +310 -0
  31. cledar/kafka/tests/unit/test_input_parser_comprehensive.py +489 -0
  32. cledar/kafka/tests/unit/test_utils.py +25 -0
  33. cledar/kafka/tests/unit/test_utils_comprehensive.py +408 -0
  34. cledar/kafka/utils/callbacks.py +28 -0
  35. cledar/kafka/utils/messages.py +39 -0
  36. cledar/kafka/utils/topics.py +15 -0
  37. cledar/kserve/README.md +352 -0
  38. cledar/kserve/__init__.py +5 -0
  39. cledar/kserve/tests/__init__.py +0 -0
  40. cledar/kserve/tests/test_utils.py +64 -0
  41. cledar/kserve/utils.py +30 -0
  42. cledar/logging/README.md +53 -0
  43. cledar/logging/__init__.py +5 -0
  44. cledar/logging/tests/test_universal_plaintext_formatter.py +249 -0
  45. cledar/logging/universal_plaintext_formatter.py +99 -0
  46. cledar/monitoring/README.md +71 -0
  47. cledar/monitoring/__init__.py +5 -0
  48. cledar/monitoring/monitoring_server.py +156 -0
  49. cledar/monitoring/tests/integration/test_monitoring_server_int.py +162 -0
  50. cledar/monitoring/tests/test_monitoring_server.py +59 -0
  51. cledar/nonce/README.md +99 -0
  52. cledar/nonce/__init__.py +5 -0
  53. cledar/nonce/nonce_service.py +62 -0
  54. cledar/nonce/tests/__init__.py +0 -0
  55. cledar/nonce/tests/test_nonce_service.py +136 -0
  56. cledar/redis/README.md +536 -0
  57. cledar/redis/__init__.py +17 -0
  58. cledar/redis/async_example.py +112 -0
  59. cledar/redis/example.py +67 -0
  60. cledar/redis/exceptions.py +25 -0
  61. cledar/redis/logger.py +5 -0
  62. cledar/redis/model.py +14 -0
  63. cledar/redis/redis.py +764 -0
  64. cledar/redis/redis_config_store.py +333 -0
  65. cledar/redis/tests/test_async_integration_redis.py +158 -0
  66. cledar/redis/tests/test_async_redis_service.py +380 -0
  67. cledar/redis/tests/test_integration_redis.py +119 -0
  68. cledar/redis/tests/test_redis_service.py +319 -0
  69. cledar/storage/README.md +529 -0
  70. cledar/storage/__init__.py +6 -0
  71. cledar/storage/constants.py +5 -0
  72. cledar/storage/exceptions.py +79 -0
  73. cledar/storage/models.py +41 -0
  74. cledar/storage/object_storage.py +1274 -0
  75. cledar/storage/tests/conftest.py +18 -0
  76. cledar/storage/tests/test_abfs.py +164 -0
  77. cledar/storage/tests/test_integration_filesystem.py +359 -0
  78. cledar/storage/tests/test_integration_s3.py +453 -0
  79. cledar/storage/tests/test_local.py +384 -0
  80. cledar/storage/tests/test_s3.py +521 -0
  81. {cledar_sdk-2.0.2.dist-info → cledar_sdk-2.1.0.dist-info}/METADATA +1 -1
  82. cledar_sdk-2.1.0.dist-info/RECORD +84 -0
  83. cledar_sdk-2.0.2.dist-info/RECORD +0 -4
  84. {cledar_sdk-2.0.2.dist-info → cledar_sdk-2.1.0.dist-info}/WHEEL +0 -0
  85. {cledar_sdk-2.0.2.dist-info → cledar_sdk-2.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,521 @@
1
+ # mypy: disable-error-code=no-untyped-def
2
+ import io
3
+ from contextlib import contextmanager
4
+ from unittest.mock import MagicMock, patch
5
+
6
+ import pytest
7
+ from faker import Faker
8
+
9
+ from cledar.storage.exceptions import (
10
+ CheckFileExistenceError,
11
+ CopyFileError,
12
+ DeleteFileError,
13
+ DownloadFileError,
14
+ GetFileInfoError,
15
+ GetFileSizeError,
16
+ ListObjectsError,
17
+ MoveFileError,
18
+ ReadFileError,
19
+ RequiredBucketNotFoundError,
20
+ UploadBufferError,
21
+ UploadFileError,
22
+ )
23
+ from cledar.storage.models import ObjectStorageServiceConfig
24
+ from cledar.storage.object_storage import ObjectStorageService
25
+
26
+ fake = Faker()
27
+
28
+
29
+ @pytest.fixture(name="object_storage_service")
30
+ @patch("fsspec.filesystem")
31
+ def fixture_object_storage_service(
32
+ fsspec_client: MagicMock, object_storage_config: ObjectStorageServiceConfig
33
+ ) -> ObjectStorageService:
34
+ fsspec_client.return_value = MagicMock()
35
+ return ObjectStorageService(object_storage_config)
36
+
37
+
38
+ def test_upload_file_filesystem_with_bucket_key_should_use_s3(
39
+ object_storage_service: ObjectStorageService,
40
+ ) -> None:
41
+ """
42
+ Test that upload_file with bucket and key uses S3 client, not filesystem.
43
+ """
44
+ file_path = fake.file_path()
45
+ bucket_name = fake.name()
46
+ key = fake.name()
47
+
48
+ object_storage_service.client.put = MagicMock()
49
+
50
+ object_storage_service.upload_file(file_path=file_path, bucket=bucket_name, key=key)
51
+
52
+ object_storage_service.client.put.assert_called_once_with(
53
+ lpath=file_path, rpath=f"s3://{bucket_name}/{key}"
54
+ )
55
+
56
+
57
+ def test_read_file_filesystem_with_bucket_key_should_use_s3(
58
+ object_storage_service: ObjectStorageService,
59
+ ) -> None:
60
+ """
61
+ Test that read_file with bucket and key uses S3 client, not filesystem.
62
+ """
63
+ bucket_name = fake.name()
64
+ key = fake.name()
65
+ expected_content = fake.text().encode()
66
+
67
+ mock_file = MagicMock()
68
+ mock_file.read.return_value = expected_content
69
+
70
+ @contextmanager
71
+ def open_cm(*_args: object, **_kwargs: object):
72
+ yield mock_file
73
+
74
+ object_storage_service.client.open = MagicMock(
75
+ side_effect=lambda *a, **k: open_cm()
76
+ )
77
+
78
+ result = object_storage_service.read_file(bucket=bucket_name, key=key)
79
+
80
+ assert result == expected_content
81
+ object_storage_service.client.open.assert_called_once_with(
82
+ path=f"s3://{bucket_name}/{key}", mode="rb"
83
+ )
84
+
85
+
86
+ def test_upload_buffer_filesystem_with_bucket_key_should_use_s3(
87
+ object_storage_service: ObjectStorageService,
88
+ ) -> None:
89
+ """
90
+ Test that upload_buffer with bucket and key uses S3 client, not filesystem.
91
+ """
92
+ buffer_str = io.StringIO(fake.text())
93
+ buffer_bytes = io.BytesIO(buffer_str.getvalue().encode())
94
+ bucket_name = fake.name()
95
+ key = fake.name()
96
+
97
+ mock_file = MagicMock()
98
+ mock_file.write = MagicMock()
99
+
100
+ @contextmanager
101
+ def open_cm(*_args: object, **_kwargs: object):
102
+ yield mock_file
103
+
104
+ object_storage_service.client.open = MagicMock(
105
+ side_effect=lambda *a, **k: open_cm()
106
+ )
107
+
108
+ object_storage_service.upload_buffer(
109
+ buffer=buffer_bytes, bucket=bucket_name, key=key
110
+ )
111
+
112
+ object_storage_service.client.open.assert_called_once_with(
113
+ path=f"s3://{bucket_name}/{key}", mode="wb"
114
+ )
115
+ mock_file.write.assert_called_once_with(buffer_bytes.getbuffer())
116
+
117
+
118
+ def test_has_bucket_no_throw_true(object_storage_service: ObjectStorageService) -> None:
119
+ bucket_name = fake.name()
120
+ result = object_storage_service.has_bucket(bucket=bucket_name)
121
+
122
+ assert result is True
123
+
124
+
125
+ def test_has_bucket_no_throw_exists(
126
+ object_storage_service: ObjectStorageService,
127
+ ) -> None:
128
+ bucket_name = fake.name()
129
+ result = object_storage_service.has_bucket(bucket=bucket_name, throw=False)
130
+
131
+ assert result is True
132
+
133
+
134
+ def test_has_bucket_no_throw_not_exists(
135
+ object_storage_service: ObjectStorageService,
136
+ ) -> None:
137
+ bucket_name = fake.name()
138
+ object_storage_service.client.ls.side_effect = OSError("Connection failed")
139
+ result = object_storage_service.has_bucket(bucket=bucket_name)
140
+
141
+ assert result is False
142
+
143
+
144
+ def test_has_bucket_throw_not_exists(
145
+ object_storage_service: ObjectStorageService,
146
+ ) -> None:
147
+ bucket_name = fake.name()
148
+ object_storage_service.client.ls.side_effect = OSError("Connection failed")
149
+
150
+ with pytest.raises(RequiredBucketNotFoundError):
151
+ object_storage_service.has_bucket(bucket=bucket_name, throw=True)
152
+
153
+
154
+ def test_upload_buffer_exception(object_storage_service: ObjectStorageService) -> None:
155
+ buffer_str = io.StringIO(fake.text())
156
+ buffer_bytes = io.BytesIO(buffer_str.getvalue().encode())
157
+ bucket_name = fake.name()
158
+ key = fake.name()
159
+
160
+ class Writer:
161
+ def write(self, _b: bytes) -> None:
162
+ raise UploadBufferError
163
+
164
+ @contextmanager
165
+ def open_cm(*_args: object, **_kwargs: object):
166
+ yield Writer()
167
+
168
+ object_storage_service.client.open = MagicMock(
169
+ side_effect=lambda *a, **k: open_cm()
170
+ )
171
+
172
+ with pytest.raises(UploadBufferError):
173
+ object_storage_service.upload_buffer(
174
+ buffer=buffer_bytes, bucket=bucket_name, key=key
175
+ )
176
+ object_storage_service.client.open.assert_called_once()
177
+
178
+
179
+ def test_upload_file_exception(object_storage_service: ObjectStorageService) -> None:
180
+ file_path = fake.file_path()
181
+ bucket_name = fake.name()
182
+ key = fake.name()
183
+
184
+ object_storage_service.client.put.side_effect = OSError("Network error")
185
+
186
+ with pytest.raises(UploadFileError):
187
+ object_storage_service.upload_file(
188
+ file_path=file_path, bucket=bucket_name, key=key
189
+ )
190
+
191
+ object_storage_service.client.put.assert_called_once_with(
192
+ lpath=file_path, rpath=f"s3://{bucket_name}/{key}"
193
+ )
194
+
195
+
196
+ def test_read_file_exception(object_storage_service: ObjectStorageService) -> None:
197
+ bucket_name = fake.name()
198
+ key = fake.name()
199
+
200
+ object_storage_service.client.open.side_effect = ReadFileError
201
+
202
+ with pytest.raises(ReadFileError):
203
+ object_storage_service.read_file(bucket=bucket_name, key=key)
204
+ object_storage_service.client.open.assert_called_once()
205
+
206
+
207
+ def test_list_objects_recursive_s3(
208
+ object_storage_service: ObjectStorageService,
209
+ ) -> None:
210
+ bucket = fake.name()
211
+ prefix = "test/prefix"
212
+ mock_objects = [
213
+ f"s3://{bucket}/{prefix}/file1.txt",
214
+ f"s3://{bucket}/{prefix}/file2.txt",
215
+ f"s3://{bucket}/{prefix}/subfolder/file3.txt",
216
+ ]
217
+ object_storage_service.client.find.return_value = mock_objects
218
+
219
+ result = object_storage_service.list_objects(
220
+ bucket=bucket, prefix=prefix, recursive=True
221
+ )
222
+
223
+ assert len(result) == 3
224
+ assert f"{prefix}/file1.txt" in result
225
+ assert f"{prefix}/file2.txt" in result
226
+ assert f"{prefix}/subfolder/file3.txt" in result
227
+ object_storage_service.client.find.assert_called_once()
228
+
229
+
230
+ def test_list_objects_non_recursive_s3(
231
+ object_storage_service: ObjectStorageService,
232
+ ) -> None:
233
+ bucket = fake.name()
234
+ prefix = "test/prefix"
235
+ mock_objects = [
236
+ f"s3://{bucket}/{prefix}/file1.txt",
237
+ f"s3://{bucket}/{prefix}/file2.txt",
238
+ ]
239
+ object_storage_service.client.ls.return_value = mock_objects
240
+
241
+ result = object_storage_service.list_objects(
242
+ bucket=bucket, prefix=prefix, recursive=False
243
+ )
244
+
245
+ assert len(result) == 2
246
+ assert f"{prefix}/file1.txt" in result
247
+ assert f"{prefix}/file2.txt" in result
248
+ object_storage_service.client.ls.assert_called_once()
249
+
250
+
251
+ def test_list_objects_exception(object_storage_service: ObjectStorageService) -> None:
252
+ bucket = fake.name()
253
+ object_storage_service.client.find.side_effect = OSError("List failed")
254
+
255
+ with pytest.raises(ListObjectsError):
256
+ object_storage_service.list_objects(bucket=bucket)
257
+
258
+
259
+ def test_delete_file_s3(object_storage_service: ObjectStorageService) -> None:
260
+ bucket = fake.name()
261
+ key = "test/file.txt"
262
+
263
+ object_storage_service.delete_file(bucket=bucket, key=key)
264
+
265
+ object_storage_service.client.rm.assert_called_once_with(f"s3://{bucket}/{key}")
266
+
267
+
268
+ def test_delete_file_exception(object_storage_service: ObjectStorageService) -> None:
269
+ bucket = fake.name()
270
+ key = "test/file.txt"
271
+ object_storage_service.client.rm.side_effect = OSError("Delete failed")
272
+
273
+ with pytest.raises(DeleteFileError):
274
+ object_storage_service.delete_file(bucket=bucket, key=key)
275
+
276
+
277
+ def test_file_exists_true_s3(object_storage_service: ObjectStorageService) -> None:
278
+ bucket = fake.name()
279
+ key = "test/file.txt"
280
+ object_storage_service.client.exists.return_value = True
281
+
282
+ result = object_storage_service.file_exists(bucket=bucket, key=key)
283
+
284
+ assert result is True
285
+ object_storage_service.client.exists.assert_called_once_with(f"s3://{bucket}/{key}")
286
+
287
+
288
+ def test_file_exists_false_s3(object_storage_service: ObjectStorageService) -> None:
289
+ bucket = fake.name()
290
+ key = "test/file.txt"
291
+ object_storage_service.client.exists.return_value = False
292
+
293
+ result = object_storage_service.file_exists(bucket=bucket, key=key)
294
+
295
+ assert result is False
296
+ object_storage_service.client.exists.assert_called_once_with(f"s3://{bucket}/{key}")
297
+
298
+
299
+ def test_file_exists_exception(object_storage_service: ObjectStorageService) -> None:
300
+ bucket = fake.name()
301
+ key = "test/file.txt"
302
+ object_storage_service.client.exists.side_effect = OSError("Check failed")
303
+
304
+ with pytest.raises(CheckFileExistenceError):
305
+ object_storage_service.file_exists(bucket=bucket, key=key)
306
+
307
+
308
+ def test_download_file_s3(object_storage_service: ObjectStorageService) -> None:
309
+ bucket = fake.name()
310
+ key = "test/file.txt"
311
+ dest_path = "/tmp/downloaded_file.txt"
312
+
313
+ object_storage_service.download_file(dest_path, bucket=bucket, key=key)
314
+
315
+ object_storage_service.client.get.assert_called_once_with(
316
+ f"s3://{bucket}/{key}", dest_path
317
+ )
318
+
319
+
320
+ def test_download_file_retry_success(
321
+ object_storage_service: ObjectStorageService,
322
+ ) -> None:
323
+ bucket = fake.name()
324
+ key = "test/file.txt"
325
+ dest_path = "/tmp/downloaded_file.txt"
326
+
327
+ object_storage_service.client.get.side_effect = [
328
+ OSError("Network error"),
329
+ OSError("Network error"),
330
+ None,
331
+ ]
332
+
333
+ object_storage_service.download_file(dest_path, bucket=bucket, key=key, max_tries=3)
334
+
335
+ assert object_storage_service.client.get.call_count == 3
336
+
337
+
338
+ def test_download_file_exception_after_retries(
339
+ object_storage_service: ObjectStorageService,
340
+ ) -> None:
341
+ bucket = fake.name()
342
+ key = "test/file.txt"
343
+ dest_path = "/tmp/downloaded_file.txt"
344
+ object_storage_service.client.get.side_effect = OSError("Network error")
345
+
346
+ with pytest.raises(DownloadFileError):
347
+ object_storage_service.download_file(
348
+ dest_path, bucket=bucket, key=key, max_tries=3
349
+ )
350
+
351
+ assert object_storage_service.client.get.call_count == 3
352
+
353
+
354
+ def test_get_file_size_s3(object_storage_service: ObjectStorageService) -> None:
355
+ bucket = fake.name()
356
+ key = "test/file.txt"
357
+ expected_size = 1024
358
+ object_storage_service.client.info.return_value = {"size": expected_size}
359
+
360
+ result = object_storage_service.get_file_size(bucket=bucket, key=key)
361
+
362
+ assert result == expected_size
363
+ object_storage_service.client.info.assert_called_once_with(f"s3://{bucket}/{key}")
364
+
365
+
366
+ def test_get_file_size_exception(object_storage_service: ObjectStorageService) -> None:
367
+ bucket = fake.name()
368
+ key = "test/file.txt"
369
+ object_storage_service.client.info.side_effect = OSError("Info failed")
370
+
371
+ with pytest.raises(GetFileSizeError):
372
+ object_storage_service.get_file_size(bucket=bucket, key=key)
373
+
374
+
375
+ def test_get_file_info_s3(object_storage_service: ObjectStorageService) -> None:
376
+ bucket = fake.name()
377
+ key = "test/file.txt"
378
+ expected_info = {
379
+ "size": 1024,
380
+ "LastModified": "2025-01-01T00:00:00Z",
381
+ "ContentType": "text/plain",
382
+ }
383
+ object_storage_service.client.info.return_value = expected_info
384
+
385
+ result = object_storage_service.get_file_info(bucket=bucket, key=key)
386
+
387
+ assert result == expected_info
388
+ object_storage_service.client.info.assert_called_once_with(f"s3://{bucket}/{key}")
389
+
390
+
391
+ def test_get_file_info_exception(object_storage_service: ObjectStorageService) -> None:
392
+ bucket = fake.name()
393
+ key = "test/file.txt"
394
+ object_storage_service.client.info.side_effect = OSError("Info failed")
395
+
396
+ with pytest.raises(GetFileInfoError):
397
+ object_storage_service.get_file_info(bucket=bucket, key=key)
398
+
399
+
400
+ def test_copy_file_s3_to_s3(object_storage_service: ObjectStorageService) -> None:
401
+ source_bucket = fake.name()
402
+ source_key = "test/source.txt"
403
+ dest_bucket = fake.name()
404
+ dest_key = "test/destination.txt"
405
+
406
+ object_storage_service.copy_file(
407
+ source_bucket=source_bucket,
408
+ source_key=source_key,
409
+ dest_bucket=dest_bucket,
410
+ dest_key=dest_key,
411
+ )
412
+
413
+ object_storage_service.client.copy.assert_called_once_with(
414
+ f"s3://{source_bucket}/{source_key}", f"s3://{dest_bucket}/{dest_key}"
415
+ )
416
+
417
+
418
+ def test_copy_file_s3_to_local(object_storage_service: ObjectStorageService) -> None:
419
+ source_bucket = fake.name()
420
+ source_key = "test/source.txt"
421
+ dest_path = "/tmp/dest/file.txt"
422
+
423
+ object_storage_service.copy_file(
424
+ source_bucket=source_bucket, source_key=source_key, dest_path=dest_path
425
+ )
426
+
427
+ object_storage_service.client.copy.assert_called_once_with(
428
+ f"s3://{source_bucket}/{source_key}", dest_path
429
+ )
430
+
431
+
432
+ def test_copy_file_local_to_s3(object_storage_service: ObjectStorageService) -> None:
433
+ source_path = "/tmp/source/file.txt"
434
+ dest_bucket = fake.name()
435
+ dest_key = "test/destination.txt"
436
+
437
+ object_storage_service.copy_file(
438
+ source_path=source_path, dest_bucket=dest_bucket, dest_key=dest_key
439
+ )
440
+
441
+ object_storage_service.client.copy.assert_called_once_with(
442
+ source_path, f"s3://{dest_bucket}/{dest_key}"
443
+ )
444
+
445
+
446
+ def test_copy_file_exception(object_storage_service: ObjectStorageService) -> None:
447
+ source_bucket = fake.name()
448
+ source_key = "test/source.txt"
449
+ dest_bucket = fake.name()
450
+ dest_key = "test/destination.txt"
451
+ object_storage_service.client.copy.side_effect = OSError("Copy failed")
452
+
453
+ with pytest.raises(CopyFileError):
454
+ object_storage_service.copy_file(
455
+ source_bucket=source_bucket,
456
+ source_key=source_key,
457
+ dest_bucket=dest_bucket,
458
+ dest_key=dest_key,
459
+ )
460
+
461
+
462
+ def test_move_file_s3_to_s3(object_storage_service: ObjectStorageService) -> None:
463
+ source_bucket = fake.name()
464
+ source_key = "test/source.txt"
465
+ dest_bucket = fake.name()
466
+ dest_key = "test/destination.txt"
467
+
468
+ object_storage_service.move_file(
469
+ source_bucket=source_bucket,
470
+ source_key=source_key,
471
+ dest_bucket=dest_bucket,
472
+ dest_key=dest_key,
473
+ )
474
+
475
+ object_storage_service.client.move.assert_called_once_with(
476
+ f"s3://{source_bucket}/{source_key}", f"s3://{dest_bucket}/{dest_key}"
477
+ )
478
+
479
+
480
+ def test_move_file_s3_to_local(object_storage_service: ObjectStorageService) -> None:
481
+ source_bucket = fake.name()
482
+ source_key = "test/source.txt"
483
+ dest_path = "/tmp/dest/file.txt"
484
+
485
+ object_storage_service.move_file(
486
+ source_bucket=source_bucket, source_key=source_key, dest_path=dest_path
487
+ )
488
+
489
+ object_storage_service.client.move.assert_called_once_with(
490
+ f"s3://{source_bucket}/{source_key}", dest_path
491
+ )
492
+
493
+
494
+ def test_move_file_local_to_s3(object_storage_service: ObjectStorageService) -> None:
495
+ source_path = "/tmp/source/file.txt"
496
+ dest_bucket = fake.name()
497
+ dest_key = "test/destination.txt"
498
+
499
+ object_storage_service.move_file(
500
+ source_path=source_path, dest_bucket=dest_bucket, dest_key=dest_key
501
+ )
502
+
503
+ object_storage_service.client.move.assert_called_once_with(
504
+ source_path, f"s3://{dest_bucket}/{dest_key}"
505
+ )
506
+
507
+
508
+ def test_move_file_exception(object_storage_service: ObjectStorageService) -> None:
509
+ source_bucket = fake.name()
510
+ source_key = "test/source.txt"
511
+ dest_bucket = fake.name()
512
+ dest_key = "test/destination.txt"
513
+ object_storage_service.client.move.side_effect = OSError("Move failed")
514
+
515
+ with pytest.raises(MoveFileError):
516
+ object_storage_service.move_file(
517
+ source_bucket=source_bucket,
518
+ source_key=source_key,
519
+ dest_bucket=dest_bucket,
520
+ dest_key=dest_key,
521
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cledar-sdk
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: Cledar Python SDK
5
5
  Author: Cledar
6
6
  License-File: LICENSE
@@ -0,0 +1,84 @@
1
+ cledar/__init__.py,sha256=Jy-s9uaJ1j7S6zYV2BpIYs0Cv8fQ_X_yaajuzhlP5MM,69
2
+ cledar/kafka/README.md,sha256=5OTXFPulZdoc2fU9JGWEwYBXCSFdbkLWrGchXl8NiX4,6926
3
+ cledar/kafka/__init__.py,sha256=Jl-7GJWwTOWOXT0S6neSOnN5PEDuR6K5n4Q2cQSoGZU,1181
4
+ cledar/kafka/exceptions.py,sha256=mEWY63I5P1vBBfCmrXvRZIkNoK8ioNBkuJ02bdIG9RM,514
5
+ cledar/kafka/logger.py,sha256=y8FzRjpBxv23iRQ6TCn1m0oJ2EwR4ktVhrZEqmOD3B0,110
6
+ cledar/kafka/clients/base.py,sha256=lvjif2X9ZAgMkLv9sqWSFmEly_AlLEo4S3tdGe9-8IU,4309
7
+ cledar/kafka/clients/consumer.py,sha256=ColMEIOORfmBEdN9-bK-9i6xoy5Fxl8NadTbY3e7ldc,4306
8
+ cledar/kafka/clients/producer.py,sha256=LTho5tDfPnBf8luZM-VFnbzHXYTp4T9RUlXHsI6Uc9M,3089
9
+ cledar/kafka/config/schemas.py,sha256=nCe-icVBYn_ufZno6_pTZhyuNENQblgVW-r-RxScJiQ,8172
10
+ cledar/kafka/handlers/dead_letter.py,sha256=zjgaLgw6AOoWSMlwwDSPgiw8j3D4m1zUk4Ir0pRr5TQ,2624
11
+ cledar/kafka/handlers/parser.py,sha256=TucZq1LF6wtt9W9m4GFLwI9Z23f7QuDIiRrY3MgaIWQ,2345
12
+ cledar/kafka/models/input.py,sha256=a2BEhqvFA6uKS8my8BtFFJmAHIJPUHe4s9r2UBCY0x8,359
13
+ cledar/kafka/models/message.py,sha256=yrzDehU48Ny9OBAi1EW3GC3DnXk1D1KpGVm9Cl96pqU,261
14
+ cledar/kafka/models/output.py,sha256=t4VetHUvFL1WAC5-BXi9RJq_XPp9jW4X65X1vHzLDVs,287
15
+ cledar/kafka/tests/.env.test.kafka,sha256=7EUptc8_8o9_NJwaMFaZGI31_rDzh3y2edVwe6RrX3I,86
16
+ cledar/kafka/tests/README.md,sha256=ngkDIyHYw3S4ySrWCUrZJo0Lejl-LNi6tIiHBtv0sxA,7350
17
+ cledar/kafka/tests/conftest.py,sha256=S1HU1wD_fEk5QyXJAxGTgUb3rUiP_5TgrkHNAcApRvQ,3474
18
+ cledar/kafka/tests/integration/__init__.py,sha256=AydX6rUkcrtA5i3sbhBPuBN2WAPzUI06g3-mQpT7tVE,43
19
+ cledar/kafka/tests/integration/conftest.py,sha256=c4x_IBBsEP6Q5B3SAGUOZSjYv-QQn2ouVvXSv50yq_g,2533
20
+ cledar/kafka/tests/integration/helpers.py,sha256=jmYK2VhXfBKV2Eld1q47Keor-F8lXBLawzzWch4AuS0,1239
21
+ cledar/kafka/tests/integration/test_consumer_integration.py,sha256=MRPXCTn8akmEYgiYIsRsR63ABb-rIs_or0iyNPktdfE,10907
22
+ cledar/kafka/tests/integration/test_integration.py,sha256=XYbyOPOxycFds7NS_sBAj60AuiiceTSnQYGNB5AnWlk,11813
23
+ cledar/kafka/tests/integration/test_producer_consumer_interaction.py,sha256=Q6JcHAMMigrc7mVxjZhjyZRTbp3F4vfL_j6eOKIKWu8,11913
24
+ cledar/kafka/tests/integration/test_producer_integration.py,sha256=VW_QR5fKI3ifqs1siT5y3qZ3XneBStY0lB0reRSkO-I,6435
25
+ cledar/kafka/tests/unit/__init__.py,sha256=uiWL_3JORErRzHi12hW0-kFU36zdkl3MBg4_qtH6TM0,36
26
+ cledar/kafka/tests/unit/test_base_kafka_client.py,sha256=v7s-NiuQe5Yk9wtUteF8Kwty_6xR8iHdx3me2ENydUQ,13232
27
+ cledar/kafka/tests/unit/test_config_validation.py,sha256=HuKGuFtniqQ_yIAZp19cm4UjVLxbuJsW7zJ5Wm8bsnA,19969
28
+ cledar/kafka/tests/unit/test_dead_letter_handler.py,sha256=Co4fBcqHiCiNkuL19zQV5Cnx0Vrs7xERgld8FO-c1TE,13897
29
+ cledar/kafka/tests/unit/test_error_handling.py,sha256=BPYLX0TCVi0tOlB8luchEB1wCNCZ-CQpU4A2E8H27lg,22800
30
+ cledar/kafka/tests/unit/test_input_parser.py,sha256=RrU6zF9Xv33qbhY-5EEIMsxt9Uh7JoD7C3DoqkKcidU,11554
31
+ cledar/kafka/tests/unit/test_input_parser_comprehensive.py,sha256=9Yq_4WJ_c5MFNAW_eGH491u8xbLB0J7Z_45CSkmD7Bs,14097
32
+ cledar/kafka/tests/unit/test_utils.py,sha256=NKTbxYPiLd2D_hO_aJLlZ7MTS2MUCm7CWlAI6ZAtLFw,811
33
+ cledar/kafka/tests/unit/test_utils_comprehensive.py,sha256=elbV7Dmd1Ffhv7c14AsY08VSg40xRNixumPmtd2SCIA,14112
34
+ cledar/kafka/utils/callbacks.py,sha256=iGONhCLBMTq-wSr-mbmR1LzzGxl3UQnq3qspeeQ8WVY,802
35
+ cledar/kafka/utils/messages.py,sha256=FJREqi_na6opyYirXOxAxGdMhUKYj6q4-a-adoGqaMQ,981
36
+ cledar/kafka/utils/topics.py,sha256=xTJ7DYMpTOAU_wbjHXVj_Q5Zwvvo0VyDsmoHjSvFN0Q,366
37
+ cledar/kserve/README.md,sha256=HUMDLPI3wVpiY3pQk1pR-lWUEVYm1kFwmNkAdoH3dQo,8699
38
+ cledar/kserve/__init__.py,sha256=ywgdBuMNYGo5nb-3-klmxqERL--ZXZNNC8-FsostnV8,103
39
+ cledar/kserve/utils.py,sha256=m5EUSYhvCJibyBPkYUdbjxRqOJYvxGQZIu1Gm-NhwLg,966
40
+ cledar/kserve/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ cledar/kserve/tests/test_utils.py,sha256=V4u0p2erwUkFwajenxM1WzMRGRqYbSK1p96QqtfbApw,1677
42
+ cledar/logging/README.md,sha256=DIGwhCPugbeQ_tggXIVGi4NYkPZFtJcrO1RQksXxdPk,1798
43
+ cledar/logging/__init__.py,sha256=o3U2tMZAgjRrnoFo7NWyGOmr7-AtC7lvfdmsa1l-yLo,183
44
+ cledar/logging/universal_plaintext_formatter.py,sha256=SHv-dnliJMeKMfAQu11IoBqOozUkEdi_0KeqELPHDjc,3497
45
+ cledar/logging/tests/test_universal_plaintext_formatter.py,sha256=Oa7qeeFWd4inI6cznsNdK5gIOSk9xefAS1mfDHq3Xq8,8560
46
+ cledar/monitoring/README.md,sha256=UdcfEXK3IhCeBhYdrrV45DXh7FTAK72bXBmUDnqZY8E,2148
47
+ cledar/monitoring/__init__.py,sha256=RoRPgddmewqBiJifO6DJWhXrw0UyTFub79MSknmQB2Q,231
48
+ cledar/monitoring/monitoring_server.py,sha256=4LnM6BKoH8tKHP6o82ZqvWbL0oQzJ7qdKndr_IG3h2k,4707
49
+ cledar/monitoring/tests/test_monitoring_server.py,sha256=gxOvqaSkS0rTw_kCtXDcCa5v3KL2MCXRvrZDFx0U4v8,1625
50
+ cledar/monitoring/tests/integration/test_monitoring_server_int.py,sha256=DmpXLGpqK3pPWtpL1vn4JP4Hm7wyD96QukaQxUIuHGM,5323
51
+ cledar/nonce/README.md,sha256=fYhGWvn6zzF9xzjAZCUa1HtcfoM4PkgzfVeO-Rogado,3516
52
+ cledar/nonce/__init__.py,sha256=6-Q9vNTlhr4KKy547AW50DORhwIEnGUNSQ6ixvucTyo,137
53
+ cledar/nonce/nonce_service.py,sha256=dCTAcaeS6GlSxca7ExyLpClA2arqPa3pYu41j8v2atY,1760
54
+ cledar/nonce/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ cledar/nonce/tests/test_nonce_service.py,sha256=2lZXUKQnL-O_R_C8Sj4yrISIphsD4Xenr9DQhdCHo74,4046
56
+ cledar/redis/README.md,sha256=4s0Rkm_NccP9Idc5RIAoZm1XYyOOFHPP-JZdhlkqH6M,14608
57
+ cledar/redis/__init__.py,sha256=-o7zGvqx5pCYE8goqwlBRp_MqiM4g903mhI4srqsgrY,298
58
+ cledar/redis/async_example.py,sha256=aYWFqfdXXRwCtCTk1cYng76JSsQpjCi6F7heJfg7Fy8,3001
59
+ cledar/redis/example.py,sha256=J1R9Um4jd3MXp8lFftVbLZyorwg2Q_cKyh7sIRGhFj0,1757
60
+ cledar/redis/exceptions.py,sha256=C_5LJ9CsOT2VWqnX-eTmMgTzyT1AyIzjMvrpsSfOdn0,790
61
+ cledar/redis/logger.py,sha256=opRHMp546sjaFrlIOZ7OM6Jyc8OMR65GLenqnBBzu1I,110
62
+ cledar/redis/model.py,sha256=6smQWMMc9dFeronUX3ZiiSeB3Yo0UXWQfct-2SY-2eg,288
63
+ cledar/redis/redis.py,sha256=_2c5os0emK0kzw6Qk_BKnV0l1XJUmixfUbztU1GzlKg,26257
64
+ cledar/redis/redis_config_store.py,sha256=74sjPSozWl8Si488N0ulvlqgLG5xj-A9KAeMGaLiY5k,10915
65
+ cledar/redis/tests/test_async_integration_redis.py,sha256=DHwZusY6rdRHaOt_lPzmB4buq7GKH-4xTjSbiIWggFY,4981
66
+ cledar/redis/tests/test_async_redis_service.py,sha256=uxmpNQt-eCuS3MVW3Iw-zWKy_BykpmCAU6ab5BlClBE,12474
67
+ cledar/redis/tests/test_integration_redis.py,sha256=tZ5xfRD7PPnGxtdSqe8EXejTMCqC1l4Fe3LvKUhcBjM,3344
68
+ cledar/redis/tests/test_redis_service.py,sha256=e_VmKav9XXjv3100pgDD__1r62RR2MKxIRlsAxQWeyY,10248
69
+ cledar/storage/README.md,sha256=kg1PW0gi94YtFcZDegbV4AveqXPb9urLmGdT6nO1m1M,15588
70
+ cledar/storage/__init__.py,sha256=6L1KGGM10oMV3DgI5Va5Lo5VgMZICoa3jPFQwMqZORw,247
71
+ cledar/storage/constants.py,sha256=xBP7Rt-0DXmjWavsGBE19HavJnUEncs-5WXVqo1_Beo,136
72
+ cledar/storage/exceptions.py,sha256=4Y0VHQ6dLljOpfmHbv2qXFRmvGtBuCpBfyztNem0tU4,1514
73
+ cledar/storage/models.py,sha256=iSx5F2A8HGPQLVqChSKmlgrLi9siMi7PNP6HM2IaQtU,1185
74
+ cledar/storage/object_storage.py,sha256=4-nVC0AhSWEGzGL4biUqTGkhBSBQ0rzK2-afVusfmKs,44486
75
+ cledar/storage/tests/conftest.py,sha256=9-_Z_7LSrwnBDVcEPuPaW19BB1Fla1tWxUk96JOxMdA,459
76
+ cledar/storage/tests/test_abfs.py,sha256=2wp3EC9wSGvUxylECJuR65vBuE7JGRZ3PsbsVgHp608,5819
77
+ cledar/storage/tests/test_integration_filesystem.py,sha256=TERmSJrw043S99fYE3xgEOiww4KgyubTYkQAhCcPgcI,11171
78
+ cledar/storage/tests/test_integration_s3.py,sha256=yl85bSW-QcaxCL8GVcXE6XXZe8Mrk65JZZDtNaGma4Y,13611
79
+ cledar/storage/tests/test_local.py,sha256=ZT5EcBI7CzzviGJnadSTi8eSKOH9ntgk5UtmFG4GArU,11253
80
+ cledar/storage/tests/test_s3.py,sha256=_ZuER9IWJSN-MEkTg83iRLqw9WvECkSBYQUTg81Na8U,16352
81
+ cledar_sdk-2.1.0.dist-info/METADATA,sha256=MqePBmmW8SXfUGQ0lZO-3J1og8drgTYOFV2HV0PPuJ8,6733
82
+ cledar_sdk-2.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
83
+ cledar_sdk-2.1.0.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
84
+ cledar_sdk-2.1.0.dist-info/RECORD,,
@@ -1,4 +0,0 @@
1
- cledar_sdk-2.0.2.dist-info/METADATA,sha256=zgMfW6mDN3epSY--smCIdXlw0lkuR5ronZWfEEIB_cg,6733
2
- cledar_sdk-2.0.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
3
- cledar_sdk-2.0.2.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
4
- cledar_sdk-2.0.2.dist-info/RECORD,,