hexkit 3.7.0__tar.gz → 3.8.1__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.
Files changed (56) hide show
  1. {hexkit-3.7.0/src/hexkit.egg-info → hexkit-3.8.1}/PKG-INFO +1 -1
  2. {hexkit-3.7.0 → hexkit-3.8.1}/pyproject.toml +3 -1
  3. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/objstorage.py +1 -1
  4. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/config.py +1 -1
  5. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/provider.py +20 -0
  6. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/testing/eventpub.py +1 -1
  7. {hexkit-3.7.0 → hexkit-3.8.1/src/hexkit.egg-info}/PKG-INFO +1 -1
  8. {hexkit-3.7.0 → hexkit-3.8.1}/LICENSE +0 -0
  9. {hexkit-3.7.0 → hexkit-3.8.1}/MANIFEST.in +0 -0
  10. {hexkit-3.7.0 → hexkit-3.8.1}/README.md +0 -0
  11. {hexkit-3.7.0 → hexkit-3.8.1}/setup.cfg +0 -0
  12. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/__init__.py +0 -0
  13. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/__main__.py +0 -0
  14. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/base.py +0 -0
  15. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/config.py +0 -0
  16. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/correlation.py +4 -4
  17. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/custom_types.py +0 -0
  18. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/log.py +0 -0
  19. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/__init__.py +0 -0
  20. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/dao.py +5 -5
  21. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/daopub.py +0 -0
  22. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/daosub.py +0 -0
  23. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/eventpub.py +0 -0
  24. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/protocols/eventsub.py +0 -0
  25. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/__init__.py +0 -0
  26. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/__init__.py +1 -1
  27. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/provider/__init__.py +2 -2
  28. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/provider/daosub.py +0 -0
  29. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/provider/eventpub.py +0 -0
  30. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/provider/eventsub.py +0 -0
  31. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/provider/utils.py +0 -0
  32. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/testcontainer.py +0 -0
  33. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/akafka/testutils.py +5 -5
  34. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/mongodb/__init__.py +0 -0
  35. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/mongodb/provider.py +0 -0
  36. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/mongodb/testutils.py +3 -3
  37. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/mongokafka/__init__.py +0 -0
  38. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/mongokafka/provider.py +0 -0
  39. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/mongokafka/testutils.py +0 -0
  40. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/__init__.py +0 -0
  41. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/test_files/__init__.py +0 -0
  42. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
  43. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
  44. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
  45. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
  46. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/testutils/__init__.py +13 -13
  47. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/testutils/_fixtures.py +8 -8
  48. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/testutils/_typical_workflow.py +0 -0
  49. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/s3/testutils/_utils.py +0 -0
  50. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/providers/testing/__init__.py +0 -0
  51. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/py.typed +0 -0
  52. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit/utils.py +0 -0
  53. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit.egg-info/SOURCES.txt +0 -0
  54. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit.egg-info/dependency_links.txt +0 -0
  55. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit.egg-info/requires.txt +0 -0
  56. {hexkit-3.7.0 → hexkit-3.8.1}/src/hexkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hexkit
3
- Version: 3.7.0
3
+ Version: 3.8.1
4
4
  Summary: A Toolkit for Building Microservices using the Hexagonal Architecture
5
5
  Author-email: "German Human Genome Phenome Archive (GHGA)" <contact@ghga.de>
6
6
  License: Apache 2.0
@@ -23,7 +23,7 @@ classifiers = [
23
23
  "Intended Audience :: Developers",
24
24
  ]
25
25
  name = "hexkit"
26
- version = "3.7.0"
26
+ version = "3.8.1"
27
27
  description = "A Toolkit for Building Microservices using the Hexagonal Architecture"
28
28
  dependencies = [
29
29
  "pydantic >=2, <3",
@@ -95,6 +95,7 @@ fixable = [
95
95
  "UP",
96
96
  "I",
97
97
  "D",
98
+ "RUF022",
98
99
  ]
99
100
  ignore = [
100
101
  "E111",
@@ -114,6 +115,7 @@ ignore = [
114
115
  "D206",
115
116
  "D300",
116
117
  "UP040",
118
+ "PLC0206",
117
119
  ]
118
120
  select = [
119
121
  "C90",
@@ -22,7 +22,7 @@ import re
22
22
  from abc import ABC, abstractmethod
23
23
  from typing import NamedTuple, Optional
24
24
 
25
- __all__ = ["PresignedPostURL", "ObjectStorageProtocol"]
25
+ __all__ = ["ObjectStorageProtocol", "PresignedPostURL"]
26
26
 
27
27
  DEFAULT_URL_EXPIRATION_PERIOD = 24 * 60 * 60 # default expiration time 24 hours
28
28
 
@@ -64,7 +64,7 @@ class KafkaConfig(BaseSettings):
64
64
  default="", description="Optional filename containing the client private key."
65
65
  )
66
66
  kafka_ssl_password: SecretStr = Field(
67
- default="",
67
+ default="", # type: ignore
68
68
  description="Optional password to be used for the client private key.",
69
69
  )
70
70
  generate_correlation_id: bool = Field(
@@ -22,6 +22,8 @@ Utilities for testing are located in `./testutils.py`.
22
22
  # ruff: noqa: PLR0913
23
23
 
24
24
  import asyncio
25
+ import logging
26
+ import re
25
27
  from functools import lru_cache
26
28
  from pathlib import Path
27
29
  from typing import Any, Optional
@@ -31,6 +33,7 @@ import botocore.client
31
33
  import botocore.config
32
34
  import botocore.configloader
33
35
  import botocore.exceptions
36
+ import botocore.handlers
34
37
  from boto3.s3.transfer import TransferConfig
35
38
  from pydantic import Field, SecretStr
36
39
  from pydantic_settings import BaseSettings
@@ -39,6 +42,10 @@ from hexkit.protocols.objstorage import ObjectStorageProtocol, PresignedPostURL
39
42
  from hexkit.utils import calc_part_size
40
43
 
41
44
  __all__ = ["ObjectStorageProtocol", "PresignedPostURL"]
45
+ # Allow colon character in bucket names to accommodate Ceph multi tenancy S3
46
+ botocore.handlers.VALID_BUCKET = re.compile(
47
+ r"^(?:[a-zA-Z0-9_]{1,191}:)?[a-z0-9\-]{3,63}$"
48
+ )
42
49
 
43
50
 
44
51
  class S3Config(BaseSettings):
@@ -116,6 +123,8 @@ def read_aws_config_ini(aws_config_ini: Path) -> botocore.config.Config:
116
123
  class S3ObjectStorage(ObjectStorageProtocol):
117
124
  """S3-based provider implementing the ObjectStorageProtocol."""
118
125
 
126
+ _re_bucket_id = botocore.handlers.VALID_BUCKET
127
+
119
128
  def __init__(
120
129
  self,
121
130
  *,
@@ -841,6 +850,17 @@ class S3ObjectStorage(ObjectStorageProtocol):
841
850
  bucket_id=dest_bucket_id, object_id=dest_object_id
842
851
  )
843
852
 
853
+ underway_operations = await self._list_multipart_upload_for_object(
854
+ bucket_id=dest_bucket_id, object_id=dest_object_id
855
+ )
856
+ if len(underway_operations) > 0:
857
+ logging.info(
858
+ "Upload or copy operation already exists for object id '%s' in bucket '%s'.",
859
+ dest_object_id,
860
+ dest_bucket_id,
861
+ )
862
+ return
863
+
844
864
  part_size = calc_part_size(file_size=file_size)
845
865
 
846
866
  transfer_config = TransferConfig(
@@ -26,7 +26,7 @@ from typing import NamedTuple, Optional
26
26
  from hexkit.custom_types import JsonObject
27
27
  from hexkit.protocols.eventpub import EventPublisherProtocol
28
28
 
29
- __all__ = ["InMemEventStore", "InMemEventPublisher", "TopicExhaustedError"]
29
+ __all__ = ["InMemEventPublisher", "InMemEventStore", "TopicExhaustedError"]
30
30
 
31
31
 
32
32
  class TopicExhaustedError(RuntimeError):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hexkit
3
- Version: 3.7.0
3
+ Version: 3.8.1
4
4
  Summary: A Toolkit for Building Microservices using the Hexagonal Architecture
5
5
  Author-email: "German Human Genome Phenome Archive (GHGA)" <contact@ghga.de>
6
6
  License: Apache 2.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -28,13 +28,13 @@ log = logging.getLogger(__name__)
28
28
  correlation_id_var: ContextVar[str] = ContextVar("correlation_id", default="")
29
29
 
30
30
  __all__ = [
31
- "set_correlation_id",
32
- "set_new_correlation_id",
31
+ "CorrelationIdContextError",
32
+ "InvalidCorrelationIdError",
33
33
  "get_correlation_id",
34
34
  "new_correlation_id",
35
+ "set_correlation_id",
36
+ "set_new_correlation_id",
35
37
  "validate_correlation_id",
36
- "CorrelationIdContextError",
37
- "InvalidCorrelationIdError",
38
38
  ]
39
39
 
40
40
 
File without changes
@@ -35,13 +35,13 @@ from typing_extensions import deprecated
35
35
  from hexkit.utils import FieldNotInModelError, validate_fields_in_model
36
36
 
37
37
  __all__ = [
38
- "ResourceNotFoundError",
39
- "ResourceAlreadyExistsError",
40
- "FindError",
41
- "MultipleHitsFoundError",
38
+ "DaoFactoryProtocol",
42
39
  "DaoNaturalId",
43
40
  "DaoSurrogateId",
44
- "DaoFactoryProtocol",
41
+ "FindError",
42
+ "MultipleHitsFoundError",
43
+ "ResourceAlreadyExistsError",
44
+ "ResourceNotFoundError",
45
45
  "uuid4_id_generator",
46
46
  ]
47
47
 
@@ -27,8 +27,8 @@ from .provider import (
27
27
  )
28
28
 
29
29
  __all__ = [
30
+ "KafkaConfig",
30
31
  "KafkaEventPublisher",
31
32
  "KafkaEventSubscriber",
32
- "KafkaConfig",
33
33
  "KafkaOutboxSubscriber",
34
34
  ]
@@ -29,10 +29,10 @@ from .eventsub import (
29
29
  )
30
30
 
31
31
  __all__ = [
32
+ "ConsumerEvent",
32
33
  "KafkaEventPublisher",
33
34
  "KafkaEventSubscriber",
34
- "ConsumerEvent",
35
+ "KafkaOutboxSubscriber",
35
36
  "get_header_value",
36
37
  "headers_as_dict",
37
- "KafkaOutboxSubscriber",
38
38
  ]
@@ -53,19 +53,19 @@ __all__ = [
53
53
  "EventBase",
54
54
  "EventRecorder",
55
55
  "ExpectedEvent",
56
- "RecordedEvent",
57
- "ValidationError",
58
56
  "KafkaConfig",
59
57
  "KafkaContainerFixture",
60
58
  "KafkaEventPublisher",
61
59
  "KafkaFixture",
62
- "get_kafka_container_fixture",
60
+ "RecordedEvent",
61
+ "ValidationError",
62
+ "clean_kafka_fixture",
63
63
  "get_clean_kafka_fixture",
64
+ "get_kafka_container_fixture",
64
65
  "get_persistent_kafka_fixture",
65
66
  "kafka_container_fixture",
66
- "clean_kafka_fixture",
67
- "persistent_kafka_fixture",
68
67
  "kafka_fixture",
68
+ "persistent_kafka_fixture",
69
69
  ]
70
70
 
71
71
 
@@ -41,13 +41,13 @@ __all__ = [
41
41
  "MongoDbContainerFixture",
42
42
  "MongoDbDaoFactory",
43
43
  "MongoDbFixture",
44
+ "clean_mongodb_fixture",
45
+ "get_clean_mongodb_fixture",
44
46
  "get_mongodb_container_fixture",
45
47
  "get_persistent_mongodb_fixture",
46
- "get_clean_mongodb_fixture",
47
48
  "mongodb_container_fixture",
48
- "clean_mongodb_fixture",
49
- "persistent_mongodb_fixture",
50
49
  "mongodb_fixture",
50
+ "persistent_mongodb_fixture",
51
51
  ]
52
52
 
53
53
 
@@ -60,35 +60,35 @@ __all__ = [
60
60
  "MEBIBYTE",
61
61
  "TEST_FILE_DIR",
62
62
  "TEST_FILE_PATHS",
63
+ "FederatedS3Fixture",
63
64
  "FileObject",
64
65
  "S3ContainerFixture",
65
66
  "S3Fixture",
67
+ "S3MultiContainerFixture",
66
68
  "calc_md5",
69
+ "check_part_size",
70
+ "clean_federated_s3_fixture",
67
71
  "clean_s3_fixture",
72
+ "download_and_check_test_file",
73
+ "federated_s3_fixture",
74
+ "get_clean_federated_s3_fixture",
68
75
  "get_clean_s3_fixture",
76
+ "get_persistent_federated_s3_fixture",
69
77
  "get_persistent_s3_fixture",
70
78
  "get_s3_container_fixture",
79
+ "get_s3_multi_container_fixture",
80
+ "multipart_upload_file",
81
+ "persistent_federated_s3_fixture",
71
82
  "persistent_s3_fixture",
72
83
  "populate_storage",
73
84
  "s3_container_fixture",
74
85
  "s3_fixture",
86
+ "s3_multi_container_fixture",
75
87
  "temp_file_object",
76
88
  "tmp_file",
77
- "upload_file",
78
89
  "typical_workflow",
79
- "check_part_size",
80
- "download_and_check_test_file",
81
- "multipart_upload_file",
90
+ "upload_file",
82
91
  "upload_part",
83
92
  "upload_part_of_size",
84
93
  "upload_part_via_url",
85
- "FederatedS3Fixture",
86
- "S3MultiContainerFixture",
87
- "clean_federated_s3_fixture",
88
- "federated_s3_fixture",
89
- "get_clean_federated_s3_fixture",
90
- "get_s3_multi_container_fixture",
91
- "get_persistent_federated_s3_fixture",
92
- "s3_multi_container_fixture",
93
- "persistent_federated_s3_fixture",
94
94
  ]
@@ -46,21 +46,21 @@ __all__ = [
46
46
  "MEBIBYTE",
47
47
  "TEST_FILE_DIR",
48
48
  "TEST_FILE_PATHS",
49
- "upload_file",
50
- "populate_storage",
51
- "calc_md5",
52
49
  "FileObject",
53
50
  "S3ContainerFixture",
54
- "get_s3_container_fixture",
55
- "s3_container_fixture",
56
51
  "S3Fixture",
52
+ "calc_md5",
53
+ "clean_s3_fixture",
54
+ "get_clean_s3_fixture",
57
55
  "get_persistent_s3_fixture",
56
+ "get_s3_container_fixture",
58
57
  "persistent_s3_fixture",
59
- "get_clean_s3_fixture",
60
- "clean_s3_fixture",
58
+ "populate_storage",
59
+ "s3_container_fixture",
61
60
  "s3_fixture",
62
- "tmp_file",
63
61
  "temp_file_object",
62
+ "tmp_file",
63
+ "upload_file",
64
64
  ]
65
65
 
66
66
 
File without changes
File without changes