julee 0.1.2__py3-none-any.whl → 0.1.3__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 (155) hide show
  1. julee/api/app.py +9 -8
  2. julee/api/dependencies.py +15 -15
  3. julee/api/requests.py +10 -9
  4. julee/api/responses.py +2 -1
  5. julee/api/routers/__init__.py +5 -5
  6. julee/api/routers/assembly_specifications.py +5 -4
  7. julee/api/routers/documents.py +1 -1
  8. julee/api/routers/knowledge_service_configs.py +4 -3
  9. julee/api/routers/knowledge_service_queries.py +7 -6
  10. julee/api/routers/system.py +4 -3
  11. julee/api/routers/workflows.py +4 -5
  12. julee/api/services/system_initialization.py +6 -6
  13. julee/api/tests/routers/test_assembly_specifications.py +4 -3
  14. julee/api/tests/routers/test_documents.py +5 -4
  15. julee/api/tests/routers/test_knowledge_service_configs.py +7 -6
  16. julee/api/tests/routers/test_knowledge_service_queries.py +4 -3
  17. julee/api/tests/routers/test_system.py +5 -4
  18. julee/api/tests/routers/test_workflows.py +5 -4
  19. julee/api/tests/test_app.py +5 -4
  20. julee/api/tests/test_dependencies.py +3 -2
  21. julee/api/tests/test_requests.py +2 -1
  22. julee/contrib/__init__.py +15 -0
  23. julee/contrib/polling/__init__.py +47 -0
  24. julee/contrib/polling/domain/__init__.py +17 -0
  25. julee/contrib/polling/domain/models/__init__.py +13 -0
  26. julee/contrib/polling/domain/models/polling_config.py +39 -0
  27. julee/contrib/polling/domain/services/__init__.py +11 -0
  28. julee/contrib/polling/domain/services/poller.py +39 -0
  29. julee/contrib/polling/infrastructure/__init__.py +15 -0
  30. julee/contrib/polling/infrastructure/services/__init__.py +12 -0
  31. julee/contrib/polling/infrastructure/services/polling/__init__.py +12 -0
  32. julee/contrib/polling/infrastructure/services/polling/http/__init__.py +12 -0
  33. julee/contrib/polling/infrastructure/services/polling/http/http_poller_service.py +80 -0
  34. julee/contrib/polling/infrastructure/temporal/__init__.py +20 -0
  35. julee/contrib/polling/infrastructure/temporal/activities.py +42 -0
  36. julee/contrib/polling/infrastructure/temporal/activity_names.py +20 -0
  37. julee/contrib/polling/infrastructure/temporal/proxies.py +45 -0
  38. julee/contrib/polling/tests/__init__.py +6 -0
  39. julee/contrib/polling/tests/unit/__init__.py +6 -0
  40. julee/contrib/polling/tests/unit/infrastructure/__init__.py +7 -0
  41. julee/contrib/polling/tests/unit/infrastructure/services/__init__.py +6 -0
  42. julee/contrib/polling/tests/unit/infrastructure/services/polling/__init__.py +6 -0
  43. julee/contrib/polling/tests/unit/infrastructure/services/polling/http/__init__.py +7 -0
  44. julee/contrib/polling/tests/unit/infrastructure/services/polling/http/test_http_poller_service.py +163 -0
  45. julee/docs/__init__.py +5 -0
  46. julee/docs/sphinx_hcd/__init__.py +82 -0
  47. julee/docs/sphinx_hcd/accelerators.py +1078 -0
  48. julee/docs/sphinx_hcd/apps.py +499 -0
  49. julee/docs/sphinx_hcd/config.py +148 -0
  50. julee/docs/sphinx_hcd/epics.py +448 -0
  51. julee/docs/sphinx_hcd/integrations.py +306 -0
  52. julee/docs/sphinx_hcd/journeys.py +783 -0
  53. julee/docs/sphinx_hcd/personas.py +435 -0
  54. julee/docs/sphinx_hcd/stories.py +932 -0
  55. julee/docs/sphinx_hcd/utils.py +180 -0
  56. julee/domain/models/__init__.py +5 -6
  57. julee/domain/models/assembly/assembly.py +7 -7
  58. julee/domain/models/assembly/tests/factories.py +2 -1
  59. julee/domain/models/assembly/tests/test_assembly.py +16 -13
  60. julee/domain/models/assembly_specification/assembly_specification.py +11 -10
  61. julee/domain/models/assembly_specification/knowledge_service_query.py +7 -6
  62. julee/domain/models/assembly_specification/tests/factories.py +2 -1
  63. julee/domain/models/assembly_specification/tests/test_assembly_specification.py +9 -6
  64. julee/domain/models/assembly_specification/tests/test_knowledge_service_query.py +3 -1
  65. julee/domain/models/custom_fields/content_stream.py +3 -2
  66. julee/domain/models/custom_fields/tests/test_custom_fields.py +2 -1
  67. julee/domain/models/document/document.py +12 -10
  68. julee/domain/models/document/tests/factories.py +3 -2
  69. julee/domain/models/document/tests/test_document.py +6 -3
  70. julee/domain/models/knowledge_service_config/knowledge_service_config.py +4 -4
  71. julee/domain/models/policy/__init__.py +4 -4
  72. julee/domain/models/policy/document_policy_validation.py +17 -17
  73. julee/domain/models/policy/policy.py +10 -10
  74. julee/domain/models/policy/tests/factories.py +2 -1
  75. julee/domain/models/policy/tests/test_document_policy_validation.py +3 -1
  76. julee/domain/models/policy/tests/test_policy.py +2 -1
  77. julee/domain/repositories/__init__.py +3 -3
  78. julee/domain/repositories/assembly.py +3 -1
  79. julee/domain/repositories/assembly_specification.py +2 -0
  80. julee/domain/repositories/base.py +5 -4
  81. julee/domain/repositories/document.py +3 -1
  82. julee/domain/repositories/document_policy_validation.py +3 -1
  83. julee/domain/repositories/knowledge_service_config.py +2 -0
  84. julee/domain/repositories/knowledge_service_query.py +1 -0
  85. julee/domain/repositories/policy.py +3 -1
  86. julee/domain/use_cases/decorators.py +3 -2
  87. julee/domain/use_cases/extract_assemble_data.py +13 -12
  88. julee/domain/use_cases/initialize_system_data.py +13 -13
  89. julee/domain/use_cases/tests/test_extract_assemble_data.py +10 -10
  90. julee/domain/use_cases/tests/test_initialize_system_data.py +2 -2
  91. julee/domain/use_cases/tests/test_validate_document.py +11 -11
  92. julee/domain/use_cases/validate_document.py +14 -14
  93. julee/maintenance/__init__.py +1 -0
  94. julee/maintenance/release.py +188 -0
  95. julee/repositories/memory/assembly.py +6 -5
  96. julee/repositories/memory/assembly_specification.py +8 -9
  97. julee/repositories/memory/base.py +12 -11
  98. julee/repositories/memory/document.py +8 -7
  99. julee/repositories/memory/document_policy_validation.py +7 -6
  100. julee/repositories/memory/knowledge_service_config.py +8 -7
  101. julee/repositories/memory/knowledge_service_query.py +8 -7
  102. julee/repositories/memory/policy.py +6 -5
  103. julee/repositories/memory/tests/test_document.py +6 -4
  104. julee/repositories/memory/tests/test_document_policy_validation.py +2 -1
  105. julee/repositories/memory/tests/test_policy.py +2 -1
  106. julee/repositories/minio/assembly.py +4 -4
  107. julee/repositories/minio/assembly_specification.py +6 -8
  108. julee/repositories/minio/client.py +22 -25
  109. julee/repositories/minio/document.py +11 -11
  110. julee/repositories/minio/document_policy_validation.py +5 -5
  111. julee/repositories/minio/knowledge_service_config.py +6 -6
  112. julee/repositories/minio/knowledge_service_query.py +6 -9
  113. julee/repositories/minio/policy.py +4 -4
  114. julee/repositories/minio/tests/fake_client.py +11 -9
  115. julee/repositories/minio/tests/test_assembly.py +3 -1
  116. julee/repositories/minio/tests/test_assembly_specification.py +2 -1
  117. julee/repositories/minio/tests/test_client_protocol.py +5 -5
  118. julee/repositories/minio/tests/test_document.py +7 -6
  119. julee/repositories/minio/tests/test_document_policy_validation.py +3 -1
  120. julee/repositories/minio/tests/test_knowledge_service_config.py +4 -2
  121. julee/repositories/minio/tests/test_knowledge_service_query.py +3 -2
  122. julee/repositories/minio/tests/test_policy.py +3 -1
  123. julee/repositories/temporal/activities.py +5 -5
  124. julee/repositories/temporal/proxies.py +5 -5
  125. julee/services/knowledge_service/__init__.py +1 -2
  126. julee/services/knowledge_service/anthropic/knowledge_service.py +8 -7
  127. julee/services/knowledge_service/anthropic/tests/test_knowledge_service.py +11 -10
  128. julee/services/knowledge_service/factory.py +8 -8
  129. julee/services/knowledge_service/knowledge_service.py +12 -14
  130. julee/services/knowledge_service/memory/knowledge_service.py +13 -12
  131. julee/services/knowledge_service/memory/test_knowledge_service.py +10 -7
  132. julee/services/knowledge_service/test_factory.py +11 -10
  133. julee/services/temporal/activities.py +10 -10
  134. julee/services/temporal/proxies.py +2 -2
  135. julee/util/domain.py +6 -6
  136. julee/util/repos/minio/file_storage.py +8 -9
  137. julee/util/repos/temporal/client_proxies/file_storage.py +3 -4
  138. julee/util/repos/temporal/data_converter.py +6 -6
  139. julee/util/repos/temporal/minio_file_storage.py +1 -1
  140. julee/util/repos/temporal/proxies/file_storage.py +2 -3
  141. julee/util/repositories.py +4 -3
  142. julee/util/temporal/decorators.py +20 -18
  143. julee/util/tests/test_decorators.py +13 -15
  144. julee/util/validation/repository.py +3 -3
  145. julee/util/validation/type_guards.py +12 -11
  146. julee/worker.py +9 -8
  147. julee/workflows/__init__.py +2 -2
  148. julee/workflows/extract_assemble.py +2 -1
  149. julee/workflows/validate_document.py +3 -2
  150. {julee-0.1.2.dist-info → julee-0.1.3.dist-info}/METADATA +2 -1
  151. julee-0.1.3.dist-info/RECORD +197 -0
  152. julee-0.1.2.dist-info/RECORD +0 -161
  153. {julee-0.1.2.dist-info → julee-0.1.3.dist-info}/WHEEL +0 -0
  154. {julee-0.1.2.dist-info → julee-0.1.3.dist-info}/licenses/LICENSE +0 -0
  155. {julee-0.1.2.dist-info → julee-0.1.3.dist-info}/top_level.txt +0 -0
@@ -13,12 +13,13 @@ All operations are still async to maintain interface compatibility.
13
13
  """
14
14
 
15
15
  import logging
16
- from typing import Optional, Dict, Any, List
16
+ from typing import Any
17
17
 
18
18
  from julee.domain.models.policy import DocumentPolicyValidation
19
19
  from julee.domain.repositories.document_policy_validation import (
20
20
  DocumentPolicyValidationRepository,
21
21
  )
22
+
22
23
  from .base import MemoryRepositoryMixin
23
24
 
24
25
  logger = logging.getLogger(__name__)
@@ -41,11 +42,11 @@ class MemoryDocumentPolicyValidationRepository(
41
42
  """Initialize repository with empty in-memory storage."""
42
43
  self.logger = logger
43
44
  self.entity_name = "DocumentPolicyValidation"
44
- self.storage_dict: Dict[str, DocumentPolicyValidation] = {}
45
+ self.storage_dict: dict[str, DocumentPolicyValidation] = {}
45
46
 
46
47
  logger.debug("Initializing MemoryDocumentPolicyValidationRepository")
47
48
 
48
- async def get(self, validation_id: str) -> Optional[DocumentPolicyValidation]:
49
+ async def get(self, validation_id: str) -> DocumentPolicyValidation | None:
49
50
  """Retrieve a document policy validation by ID.
50
51
 
51
52
  Args:
@@ -73,8 +74,8 @@ class MemoryDocumentPolicyValidationRepository(
73
74
  return self.generate_entity_id("validation")
74
75
 
75
76
  async def get_many(
76
- self, validation_ids: List[str]
77
- ) -> Dict[str, Optional[DocumentPolicyValidation]]:
77
+ self, validation_ids: list[str]
78
+ ) -> dict[str, DocumentPolicyValidation | None]:
78
79
  """Retrieve multiple document policy validations by ID.
79
80
 
80
81
  Args:
@@ -87,7 +88,7 @@ class MemoryDocumentPolicyValidationRepository(
87
88
  return self.get_many_entities(validation_ids)
88
89
 
89
90
  def _add_entity_specific_log_data(
90
- self, entity: DocumentPolicyValidation, log_data: Dict[str, Any]
91
+ self, entity: DocumentPolicyValidation, log_data: dict[str, Any]
91
92
  ) -> None:
92
93
  """Add validation-specific data to log entries."""
93
94
  super()._add_entity_specific_log_data(entity, log_data)
@@ -14,7 +14,7 @@ interface compatibility.
14
14
  """
15
15
 
16
16
  import logging
17
- from typing import Optional, Dict, Any, List
17
+ from typing import Any
18
18
 
19
19
  from julee.domain.models.knowledge_service_config import (
20
20
  KnowledgeServiceConfig,
@@ -22,6 +22,7 @@ from julee.domain.models.knowledge_service_config import (
22
22
  from julee.domain.repositories.knowledge_service_config import (
23
23
  KnowledgeServiceConfigRepository,
24
24
  )
25
+
25
26
  from .base import MemoryRepositoryMixin
26
27
 
27
28
  logger = logging.getLogger(__name__)
@@ -48,11 +49,11 @@ class MemoryKnowledgeServiceConfigRepository(
48
49
  """Initialize repository with empty in-memory storage."""
49
50
  self.logger = logger
50
51
  self.entity_name = "KnowledgeServiceConfig"
51
- self.storage_dict: Dict[str, KnowledgeServiceConfig] = {}
52
+ self.storage_dict: dict[str, KnowledgeServiceConfig] = {}
52
53
 
53
54
  logger.debug("Initializing MemoryKnowledgeServiceConfigRepository")
54
55
 
55
- async def get(self, knowledge_service_id: str) -> Optional[KnowledgeServiceConfig]:
56
+ async def get(self, knowledge_service_id: str) -> KnowledgeServiceConfig | None:
56
57
  """Retrieve a knowledge service configuration by ID.
57
58
 
58
59
  Args:
@@ -80,8 +81,8 @@ class MemoryKnowledgeServiceConfigRepository(
80
81
  return self.generate_entity_id("ks")
81
82
 
82
83
  async def get_many(
83
- self, knowledge_service_ids: List[str]
84
- ) -> Dict[str, Optional[KnowledgeServiceConfig]]:
84
+ self, knowledge_service_ids: list[str]
85
+ ) -> dict[str, KnowledgeServiceConfig | None]:
85
86
  """Retrieve multiple knowledge service configs by ID.
86
87
 
87
88
  Args:
@@ -94,7 +95,7 @@ class MemoryKnowledgeServiceConfigRepository(
94
95
  """
95
96
  return self.get_many_entities(knowledge_service_ids)
96
97
 
97
- async def list_all(self) -> List[KnowledgeServiceConfig]:
98
+ async def list_all(self) -> list[KnowledgeServiceConfig]:
98
99
  """List all knowledge service configurations.
99
100
 
100
101
  Returns:
@@ -116,7 +117,7 @@ class MemoryKnowledgeServiceConfigRepository(
116
117
  return configs
117
118
 
118
119
  def _add_entity_specific_log_data(
119
- self, entity: KnowledgeServiceConfig, log_data: Dict[str, Any]
120
+ self, entity: KnowledgeServiceConfig, log_data: dict[str, Any]
120
121
  ) -> None:
121
122
  """Add knowledge service config-specific data to log entries."""
122
123
  super()._add_entity_specific_log_data(entity, log_data)
@@ -13,7 +13,7 @@ should be avoided.
13
13
  """
14
14
 
15
15
  import logging
16
- from typing import Dict, Optional, Any, List
16
+ from typing import Any
17
17
 
18
18
  from julee.domain.models.assembly_specification import (
19
19
  KnowledgeServiceQuery,
@@ -21,6 +21,7 @@ from julee.domain.models.assembly_specification import (
21
21
  from julee.domain.repositories.knowledge_service_query import (
22
22
  KnowledgeServiceQueryRepository,
23
23
  )
24
+
24
25
  from .base import MemoryRepositoryMixin
25
26
 
26
27
  logger = logging.getLogger(__name__)
@@ -47,11 +48,11 @@ class MemoryKnowledgeServiceQueryRepository(
47
48
  """Initialize repository with empty in-memory storage."""
48
49
  self.logger = logger
49
50
  self.entity_name = "KnowledgeServiceQuery"
50
- self.storage_dict: Dict[str, KnowledgeServiceQuery] = {}
51
+ self.storage_dict: dict[str, KnowledgeServiceQuery] = {}
51
52
 
52
53
  logger.debug("Initializing MemoryKnowledgeServiceQueryRepository")
53
54
 
54
- async def get(self, query_id: str) -> Optional[KnowledgeServiceQuery]:
55
+ async def get(self, query_id: str) -> KnowledgeServiceQuery | None:
55
56
  """Retrieve a knowledge service query by ID.
56
57
 
57
58
  Args:
@@ -71,8 +72,8 @@ class MemoryKnowledgeServiceQueryRepository(
71
72
  self.save_entity(query, "query_id")
72
73
 
73
74
  async def get_many(
74
- self, query_ids: List[str]
75
- ) -> Dict[str, Optional[KnowledgeServiceQuery]]:
75
+ self, query_ids: list[str]
76
+ ) -> dict[str, KnowledgeServiceQuery | None]:
76
77
  """Retrieve multiple knowledge service queries by ID.
77
78
 
78
79
  Args:
@@ -92,7 +93,7 @@ class MemoryKnowledgeServiceQueryRepository(
92
93
  """
93
94
  return self.generate_entity_id("query")
94
95
 
95
- async def list_all(self) -> List[KnowledgeServiceQuery]:
96
+ async def list_all(self) -> list[KnowledgeServiceQuery]:
96
97
  """List all knowledge service queries.
97
98
 
98
99
  Returns:
@@ -113,7 +114,7 @@ class MemoryKnowledgeServiceQueryRepository(
113
114
  return entities
114
115
 
115
116
  def _add_entity_specific_log_data(
116
- self, entity: KnowledgeServiceQuery, log_data: Dict[str, Any]
117
+ self, entity: KnowledgeServiceQuery, log_data: dict[str, Any]
117
118
  ) -> None:
118
119
  """Add knowledge service query-specific data to log entries."""
119
120
  super()._add_entity_specific_log_data(entity, log_data)
@@ -12,10 +12,11 @@ All operations are still async to maintain interface compatibility.
12
12
  """
13
13
 
14
14
  import logging
15
- from typing import Optional, Dict, Any, List
15
+ from typing import Any
16
16
 
17
17
  from julee.domain.models.policy import Policy
18
18
  from julee.domain.repositories.policy import PolicyRepository
19
+
19
20
  from .base import MemoryRepositoryMixin
20
21
 
21
22
  logger = logging.getLogger(__name__)
@@ -34,11 +35,11 @@ class MemoryPolicyRepository(PolicyRepository, MemoryRepositoryMixin[Policy]):
34
35
  """Initialize repository with empty in-memory storage."""
35
36
  self.logger = logger
36
37
  self.entity_name = "Policy"
37
- self.storage_dict: Dict[str, Policy] = {}
38
+ self.storage_dict: dict[str, Policy] = {}
38
39
 
39
40
  logger.debug("Initializing MemoryPolicyRepository")
40
41
 
41
- async def get(self, policy_id: str) -> Optional[Policy]:
42
+ async def get(self, policy_id: str) -> Policy | None:
42
43
  """Retrieve a policy by ID.
43
44
 
44
45
  Args:
@@ -65,7 +66,7 @@ class MemoryPolicyRepository(PolicyRepository, MemoryRepositoryMixin[Policy]):
65
66
  """
66
67
  return self.generate_entity_id("policy")
67
68
 
68
- async def get_many(self, policy_ids: List[str]) -> Dict[str, Optional[Policy]]:
69
+ async def get_many(self, policy_ids: list[str]) -> dict[str, Policy | None]:
69
70
  """Retrieve multiple policies by ID.
70
71
 
71
72
  Args:
@@ -77,7 +78,7 @@ class MemoryPolicyRepository(PolicyRepository, MemoryRepositoryMixin[Policy]):
77
78
  return self.get_many_entities(policy_ids)
78
79
 
79
80
  def _add_entity_specific_log_data(
80
- self, entity: Policy, log_data: Dict[str, Any]
81
+ self, entity: Policy, log_data: dict[str, Any]
81
82
  ) -> None:
82
83
  """Add policy-specific data to log entries."""
83
84
  super()._add_entity_specific_log_data(entity, log_data)
@@ -7,14 +7,16 @@ idempotency, error handling, and content operations including content_string.
7
7
  """
8
8
 
9
9
  import io
10
+
10
11
  import pytest
11
- from julee.repositories.memory.document import (
12
- MemoryDocumentRepository,
13
- )
14
- from julee.domain.models.document import Document, DocumentStatus
12
+
15
13
  from julee.domain.models.custom_fields.content_stream import (
16
14
  ContentStream,
17
15
  )
16
+ from julee.domain.models.document import Document, DocumentStatus
17
+ from julee.repositories.memory.document import (
18
+ MemoryDocumentRepository,
19
+ )
18
20
 
19
21
 
20
22
  @pytest.fixture
@@ -6,10 +6,11 @@ repository implementation, focusing on functionality specific to this
6
6
  repository that differs from the inherited mixins.
7
7
  """
8
8
 
9
- import pytest
10
9
  from datetime import datetime, timezone
11
10
  from typing import Any
12
11
 
12
+ import pytest
13
+
13
14
  from julee.domain.models.policy import (
14
15
  DocumentPolicyValidation,
15
16
  DocumentPolicyValidationStatus,
@@ -6,9 +6,10 @@ repository implementation, following the testing patterns established in the
6
6
  project.
7
7
  """
8
8
 
9
- import pytest
10
9
  from datetime import datetime, timezone
11
10
 
11
+ import pytest
12
+
12
13
  from julee.domain.models.policy import Policy, PolicyStatus
13
14
  from julee.repositories.memory.policy import MemoryPolicyRepository
14
15
 
@@ -11,10 +11,10 @@ the large payload handling pattern from the architectural guidelines.
11
11
  """
12
12
 
13
13
  import logging
14
- from typing import Optional, List, Dict
15
14
 
16
15
  from julee.domain.models.assembly import Assembly
17
16
  from julee.domain.repositories.assembly import AssemblyRepository
17
+
18
18
  from .client import MinioClient, MinioRepositoryMixin
19
19
 
20
20
 
@@ -37,7 +37,7 @@ class MinioAssemblyRepository(AssemblyRepository, MinioRepositoryMixin):
37
37
  self.assembly_bucket = "assemblies"
38
38
  self.ensure_buckets_exist([self.assembly_bucket])
39
39
 
40
- async def get(self, assembly_id: str) -> Optional[Assembly]:
40
+ async def get(self, assembly_id: str) -> Assembly | None:
41
41
  """Retrieve an assembly by ID."""
42
42
  # Get the assembly using mixin methods
43
43
  assembly = self.get_json_object(
@@ -69,7 +69,7 @@ class MinioAssemblyRepository(AssemblyRepository, MinioRepositoryMixin):
69
69
  },
70
70
  )
71
71
 
72
- async def get_many(self, assembly_ids: List[str]) -> Dict[str, Optional[Assembly]]:
72
+ async def get_many(self, assembly_ids: list[str]) -> dict[str, Assembly | None]:
73
73
  """Retrieve multiple assemblies by ID.
74
74
 
75
75
  Args:
@@ -92,7 +92,7 @@ class MinioAssemblyRepository(AssemblyRepository, MinioRepositoryMixin):
92
92
  )
93
93
 
94
94
  # Convert object names back to assembly IDs for the result
95
- result: Dict[str, Optional[Assembly]] = {}
95
+ result: dict[str, Assembly | None] = {}
96
96
  for assembly_id in assembly_ids:
97
97
  result[assembly_id] = object_results[assembly_id]
98
98
 
@@ -14,7 +14,6 @@ schema and query mappings.
14
14
  """
15
15
 
16
16
  import logging
17
- from typing import Optional, List, Dict
18
17
 
19
18
  from julee.domain.models.assembly_specification import (
20
19
  AssemblySpecification,
@@ -22,6 +21,7 @@ from julee.domain.models.assembly_specification import (
22
21
  from julee.domain.repositories.assembly_specification import (
23
22
  AssemblySpecificationRepository,
24
23
  )
24
+
25
25
  from .client import MinioClient, MinioRepositoryMixin
26
26
 
27
27
 
@@ -48,9 +48,7 @@ class MinioAssemblySpecificationRepository(
48
48
  self.specifications_bucket = "assembly-specifications"
49
49
  self.ensure_buckets_exist(self.specifications_bucket)
50
50
 
51
- async def get(
52
- self, assembly_specification_id: str
53
- ) -> Optional[AssemblySpecification]:
51
+ async def get(self, assembly_specification_id: str) -> AssemblySpecification | None:
54
52
  """Retrieve an assembly specification by ID."""
55
53
  object_name = f"spec/{assembly_specification_id}"
56
54
 
@@ -87,8 +85,8 @@ class MinioAssemblySpecificationRepository(
87
85
  )
88
86
 
89
87
  async def get_many(
90
- self, assembly_specification_ids: List[str]
91
- ) -> Dict[str, Optional[AssemblySpecification]]:
88
+ self, assembly_specification_ids: list[str]
89
+ ) -> dict[str, AssemblySpecification | None]:
92
90
  """Retrieve multiple assembly specifications by ID.
93
91
 
94
92
  Args:
@@ -113,7 +111,7 @@ class MinioAssemblySpecificationRepository(
113
111
  )
114
112
 
115
113
  # Convert object names back to specification IDs for the result
116
- result: Dict[str, Optional[AssemblySpecification]] = {}
114
+ result: dict[str, AssemblySpecification | None] = {}
117
115
  for i, spec_id in enumerate(assembly_specification_ids):
118
116
  object_name = object_names[i]
119
117
  result[spec_id] = object_results[object_name]
@@ -124,7 +122,7 @@ class MinioAssemblySpecificationRepository(
124
122
  """Generate a unique assembly specification identifier."""
125
123
  return self.generate_id_with_prefix("spec")
126
124
 
127
- async def list_all(self) -> List[AssemblySpecification]:
125
+ async def list_all(self) -> list[AssemblySpecification]:
128
126
  """List all assembly specifications.
129
127
 
130
128
  Returns:
@@ -15,21 +15,18 @@ import io
15
15
  import json
16
16
  from datetime import datetime, timezone
17
17
  from typing import (
18
- Protocol,
19
18
  Any,
20
- Dict,
21
- Optional,
22
- runtime_checkable,
23
- List,
24
- Union,
25
- TypeVar,
26
19
  BinaryIO,
20
+ Protocol,
21
+ TypeVar,
22
+ runtime_checkable,
27
23
  )
28
- from urllib3.response import BaseHTTPResponse
29
- from minio.datatypes import Object
24
+
30
25
  from minio.api import ObjectWriteResult
26
+ from minio.datatypes import Object
31
27
  from minio.error import S3Error # type: ignore[import-untyped]
32
28
  from pydantic import BaseModel
29
+ from urllib3.response import BaseHTTPResponse
33
30
 
34
31
  # Import ContentStream here to avoid circular imports
35
32
  from julee.domain.models.custom_fields.content_stream import (
@@ -78,7 +75,7 @@ class MinioClient(Protocol):
78
75
  data: BinaryIO,
79
76
  length: int,
80
77
  content_type: str = "application/octet-stream",
81
- metadata: Optional[Dict[str, Union[str, List[str], tuple[str]]]] = None,
78
+ metadata: dict[str, str | list[str] | tuple[str]] | None = None,
82
79
  ) -> ObjectWriteResult:
83
80
  """Store an object in the bucket.
84
81
 
@@ -167,7 +164,7 @@ class MinioRepositoryMixin:
167
164
  client: MinioClient
168
165
  logger: Any # logging.Logger, but avoiding import
169
166
 
170
- def ensure_buckets_exist(self, bucket_names: Union[str, List[str]]) -> None:
167
+ def ensure_buckets_exist(self, bucket_names: str | list[str]) -> None:
171
168
  """Ensure one or more buckets exist, creating them if necessary.
172
169
 
173
170
  Args:
@@ -202,12 +199,12 @@ class MinioRepositoryMixin:
202
199
  def get_many_json_objects(
203
200
  self,
204
201
  bucket_name: str,
205
- object_names: List[str],
202
+ object_names: list[str],
206
203
  model_class: type[T],
207
204
  not_found_log_message: str,
208
205
  error_log_message: str,
209
- extra_log_data: Optional[Dict[str, Any]] = None,
210
- ) -> Dict[str, Optional[T]]:
206
+ extra_log_data: dict[str, Any] | None = None,
207
+ ) -> dict[str, T | None]:
211
208
  """Get multiple JSON objects from Minio and deserialize them.
212
209
 
213
210
  Note: S3/MinIO does not have native batch retrieval operations.
@@ -232,7 +229,7 @@ class MinioRepositoryMixin:
232
229
  S3Error: For non-NoSuchKey errors
233
230
  """
234
231
  extra_log_data = extra_log_data or {}
235
- result: Dict[str, Optional[T]] = {}
232
+ result: dict[str, T | None] = {}
236
233
  found_count = 0
237
234
 
238
235
  self.logger.debug(
@@ -297,11 +294,11 @@ class MinioRepositoryMixin:
297
294
  def get_many_binary_objects(
298
295
  self,
299
296
  bucket_name: str,
300
- object_names: List[str],
297
+ object_names: list[str],
301
298
  not_found_log_message: str,
302
299
  error_log_message: str,
303
- extra_log_data: Optional[Dict[str, Any]] = None,
304
- ) -> Dict[str, Optional[ContentStream]]:
300
+ extra_log_data: dict[str, Any] | None = None,
301
+ ) -> dict[str, ContentStream | None]:
305
302
  """Get multiple binary objects from Minio as ContentStreams.
306
303
 
307
304
  Note: S3/MinIO does not have native batch retrieval operations.
@@ -322,7 +319,7 @@ class MinioRepositoryMixin:
322
319
  S3Error: For non-NoSuchKey errors
323
320
  """
324
321
  extra_log_data = extra_log_data or {}
325
- result: Dict[str, Optional[ContentStream]] = {}
322
+ result: dict[str, ContentStream | None] = {}
326
323
  found_count = 0
327
324
 
328
325
  self.logger.debug(
@@ -383,8 +380,8 @@ class MinioRepositoryMixin:
383
380
  model_class: type[T],
384
381
  not_found_log_message: str,
385
382
  error_log_message: str,
386
- extra_log_data: Optional[Dict[str, Any]] = None,
387
- ) -> Optional[T]:
383
+ extra_log_data: dict[str, Any] | None = None,
384
+ ) -> T | None:
388
385
  """Get a JSON object from Minio and deserialize it to a Pydantic
389
386
  model.
390
387
 
@@ -441,7 +438,7 @@ class MinioRepositoryMixin:
441
438
  model: BaseModel,
442
439
  success_log_message: str,
443
440
  error_log_message: str,
444
- extra_log_data: Optional[Dict[str, Any]] = None,
441
+ extra_log_data: dict[str, Any] | None = None,
445
442
  ) -> None:
446
443
  """Store a Pydantic model as a JSON object in Minio.
447
444
 
@@ -494,11 +491,11 @@ class MinioRepositoryMixin:
494
491
 
495
492
  # Set created_at if it's None (for new objects)
496
493
  if hasattr(model, "created_at") and getattr(model, "created_at", None) is None:
497
- setattr(model, "created_at", now)
494
+ model.created_at = now
498
495
 
499
496
  # Always update updated_at
500
497
  if hasattr(model, "updated_at"):
501
- setattr(model, "updated_at", now)
498
+ model.updated_at = now
502
499
 
503
500
  def generate_id_with_prefix(self, prefix: str) -> str:
504
501
  """Generate a unique ID with the given prefix and log the generation.
@@ -530,7 +527,7 @@ class MinioRepositoryMixin:
530
527
  bucket_name: str,
531
528
  prefix: str,
532
529
  entity_type_name: str,
533
- ) -> List[str]:
530
+ ) -> list[str]:
534
531
  """Extract entity IDs from objects with a given prefix.
535
532
 
536
533
  This method provides a common implementation for listing objects
@@ -11,23 +11,23 @@ The implementation separates document metadata (stored as JSON) from content
11
11
  payload handling pattern from the architectural guidelines.
12
12
  """
13
13
 
14
+ import hashlib
14
15
  import io
15
16
  import json
16
- import hashlib
17
17
  import logging
18
18
  from datetime import datetime, timezone
19
- from typing import Optional, List, Dict
20
19
 
21
- from minio.error import S3Error # type: ignore[import-untyped]
22
20
  import multihash # type: ignore[import-untyped]
21
+ from minio.error import S3Error # type: ignore[import-untyped]
22
+ from pydantic import BaseModel, ConfigDict
23
23
 
24
- from julee.domain.models.document import Document
25
24
  from julee.domain.models.custom_fields.content_stream import (
26
25
  ContentStream,
27
26
  )
27
+ from julee.domain.models.document import Document
28
28
  from julee.domain.repositories.document import DocumentRepository
29
+
29
30
  from .client import MinioClient, MinioRepositoryMixin
30
- from pydantic import BaseModel, ConfigDict
31
31
 
32
32
 
33
33
  class RawMetadata(BaseModel):
@@ -36,7 +36,7 @@ class RawMetadata(BaseModel):
36
36
  model_config = ConfigDict(extra="allow") # Allow arbitrary fields
37
37
 
38
38
  # Only include fields we actually use for type safety
39
- content_multihash: Optional[str] = None
39
+ content_multihash: str | None = None
40
40
 
41
41
 
42
42
  class MinioDocumentRepository(DocumentRepository, MinioRepositoryMixin):
@@ -63,7 +63,7 @@ class MinioDocumentRepository(DocumentRepository, MinioRepositoryMixin):
63
63
  self.content_bucket = "documents-content"
64
64
  self.ensure_buckets_exist([self.metadata_bucket, self.content_bucket])
65
65
 
66
- async def get(self, document_id: str) -> Optional[Document]:
66
+ async def get(self, document_id: str) -> Document | None:
67
67
  """Retrieve a document with metadata and content."""
68
68
  try:
69
69
  # First, get the metadata
@@ -234,7 +234,7 @@ class MinioDocumentRepository(DocumentRepository, MinioRepositoryMixin):
234
234
  )
235
235
  raise
236
236
 
237
- async def get_many(self, document_ids: List[str]) -> Dict[str, Optional[Document]]:
237
+ async def get_many(self, document_ids: list[str]) -> dict[str, Document | None]:
238
238
  """Retrieve multiple documents by ID using batch operations.
239
239
 
240
240
  Args:
@@ -271,7 +271,7 @@ class MinioDocumentRepository(DocumentRepository, MinioRepositoryMixin):
271
271
  )
272
272
 
273
273
  # Use RawMetadata objects directly
274
- metadata_results: Dict[str, Optional[RawMetadata]] = raw_metadata_results
274
+ metadata_results: dict[str, RawMetadata | None] = raw_metadata_results
275
275
 
276
276
  # Step 2: Extract unique content multihashes from found metadata
277
277
  content_hashes = set()
@@ -294,7 +294,7 @@ class MinioDocumentRepository(DocumentRepository, MinioRepositoryMixin):
294
294
  )
295
295
 
296
296
  # Step 4: Splice metadata and content together into Documents
297
- result: Dict[str, Optional[Document]] = {}
297
+ result: dict[str, Document | None] = {}
298
298
  for document_id in document_ids:
299
299
  metadata = metadata_results.get(document_id)
300
300
  if not metadata:
@@ -335,7 +335,7 @@ class MinioDocumentRepository(DocumentRepository, MinioRepositoryMixin):
335
335
 
336
336
  return result
337
337
 
338
- async def list_all(self) -> List[Document]:
338
+ async def list_all(self) -> list[Document]:
339
339
  """List all documents.
340
340
 
341
341
  Returns:
@@ -14,12 +14,12 @@ status, scores, transformation results, and metadata.
14
14
  """
15
15
 
16
16
  import logging
17
- from typing import Optional, List, Dict
18
17
 
19
18
  from julee.domain.models.policy import DocumentPolicyValidation
20
19
  from julee.domain.repositories.document_policy_validation import (
21
20
  DocumentPolicyValidationRepository,
22
21
  )
22
+
23
23
  from .client import MinioClient, MinioRepositoryMixin
24
24
 
25
25
 
@@ -47,7 +47,7 @@ class MinioDocumentPolicyValidationRepository(
47
47
  self.validations_bucket = "document-policy-validations"
48
48
  self.ensure_buckets_exist(self.validations_bucket)
49
49
 
50
- async def get(self, validation_id: str) -> Optional[DocumentPolicyValidation]:
50
+ async def get(self, validation_id: str) -> DocumentPolicyValidation | None:
51
51
  """Retrieve a document policy validation by ID."""
52
52
  return self.get_json_object(
53
53
  bucket_name=self.validations_bucket,
@@ -88,8 +88,8 @@ class MinioDocumentPolicyValidationRepository(
88
88
  return self.generate_id_with_prefix("validation")
89
89
 
90
90
  async def get_many(
91
- self, validation_ids: List[str]
92
- ) -> Dict[str, Optional[DocumentPolicyValidation]]:
91
+ self, validation_ids: list[str]
92
+ ) -> dict[str, DocumentPolicyValidation | None]:
93
93
  """Retrieve multiple document policy validations by ID.
94
94
 
95
95
  Args:
@@ -113,7 +113,7 @@ class MinioDocumentPolicyValidationRepository(
113
113
  )
114
114
 
115
115
  # Convert object names back to validation IDs for the result
116
- result: Dict[str, Optional[DocumentPolicyValidation]] = {}
116
+ result: dict[str, DocumentPolicyValidation | None] = {}
117
117
  for validation_id in validation_ids:
118
118
  result[validation_id] = object_results[validation_id]
119
119
 
@@ -14,7 +14,6 @@ key.
14
14
  """
15
15
 
16
16
  import logging
17
- from typing import Optional, List, Dict
18
17
 
19
18
  from julee.domain.models.knowledge_service_config import (
20
19
  KnowledgeServiceConfig,
@@ -22,6 +21,7 @@ from julee.domain.models.knowledge_service_config import (
22
21
  from julee.domain.repositories.knowledge_service_config import (
23
22
  KnowledgeServiceConfigRepository,
24
23
  )
24
+
25
25
  from .client import MinioClient, MinioRepositoryMixin
26
26
 
27
27
 
@@ -53,7 +53,7 @@ class MinioKnowledgeServiceConfigRepository(
53
53
  self.bucket_name = "knowledge-service-configs"
54
54
  self.ensure_buckets_exist(self.bucket_name)
55
55
 
56
- async def get(self, knowledge_service_id: str) -> Optional[KnowledgeServiceConfig]:
56
+ async def get(self, knowledge_service_id: str) -> KnowledgeServiceConfig | None:
57
57
  """Retrieve a knowledge service configuration by ID.
58
58
 
59
59
  Args:
@@ -98,8 +98,8 @@ class MinioKnowledgeServiceConfigRepository(
98
98
  )
99
99
 
100
100
  async def get_many(
101
- self, knowledge_service_ids: List[str]
102
- ) -> Dict[str, Optional[KnowledgeServiceConfig]]:
101
+ self, knowledge_service_ids: list[str]
102
+ ) -> dict[str, KnowledgeServiceConfig | None]:
103
103
  """Retrieve multiple knowledge service configs by ID.
104
104
 
105
105
  Args:
@@ -124,7 +124,7 @@ class MinioKnowledgeServiceConfigRepository(
124
124
  )
125
125
 
126
126
  # Convert object names back to knowledge service IDs for the result
127
- result: Dict[str, Optional[KnowledgeServiceConfig]] = {}
127
+ result: dict[str, KnowledgeServiceConfig | None] = {}
128
128
  for i, service_id in enumerate(knowledge_service_ids):
129
129
  object_name = object_names[i]
130
130
  result[service_id] = object_results[object_name]
@@ -139,7 +139,7 @@ class MinioKnowledgeServiceConfigRepository(
139
139
  """
140
140
  return self.generate_id_with_prefix("ks")
141
141
 
142
- async def list_all(self) -> List[KnowledgeServiceConfig]:
142
+ async def list_all(self) -> list[KnowledgeServiceConfig]:
143
143
  """List all knowledge service configurations.
144
144
 
145
145
  Returns: