persistence-kit 3.0.2__tar.gz → 3.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/PKG-INFO +140 -5
  2. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/README.md +128 -2
  3. persistence_kit-3.2.0/persistence_kit/__init__.py +231 -0
  4. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/api/__init__.py +3 -0
  5. persistence_kit-3.2.0/persistence_kit/api/rate_limit.py +103 -0
  6. persistence_kit-3.2.0/persistence_kit/authenticated_user.py +37 -0
  7. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/sqlalchemy_repo/sqlalchemy_engine.py +1 -1
  8. persistence_kit-3.2.0/persistence_kit/security/__init__.py +82 -0
  9. persistence_kit-3.2.0/persistence_kit/security/factory.py +156 -0
  10. persistence_kit-3.2.0/persistence_kit/security/ports.py +123 -0
  11. persistence_kit-3.2.0/persistence_kit/security/providers/__init__.py +23 -0
  12. persistence_kit-3.2.0/persistence_kit/security/providers/cognito_identity_provider.py +1232 -0
  13. persistence_kit-3.2.0/persistence_kit/security/providers/memory_security_provider.py +570 -0
  14. persistence_kit-3.2.0/persistence_kit/security/registration.py +100 -0
  15. persistence_kit-3.2.0/persistence_kit/security/token_verifiers/__init__.py +23 -0
  16. persistence_kit-3.2.0/persistence_kit/security/token_verifiers/cognito_jwt_verifier.py +60 -0
  17. persistence_kit-3.2.0/persistence_kit/security/token_verifiers/memory_jwt_verifier.py +44 -0
  18. persistence_kit-3.2.0/persistence_kit/settings/__init__.py +27 -0
  19. persistence_kit-3.2.0/persistence_kit/settings/app_settings.py +115 -0
  20. persistence_kit-3.2.0/persistence_kit/storage/__init__.py +70 -0
  21. persistence_kit-3.2.0/persistence_kit/storage/contracts.py +26 -0
  22. persistence_kit-3.2.0/persistence_kit/storage/errors.py +18 -0
  23. persistence_kit-3.2.0/persistence_kit/storage/factory.py +71 -0
  24. persistence_kit-3.2.0/persistence_kit/storage/local.py +114 -0
  25. persistence_kit-3.2.0/persistence_kit/storage/routes.py +119 -0
  26. persistence_kit-3.2.0/persistence_kit/storage/s3.py +95 -0
  27. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/pyproject.toml +14 -3
  28. persistence_kit-3.0.2/persistence_kit/__init__.py +0 -46
  29. persistence_kit-3.0.2/persistence_kit/settings/__init__.py +0 -5
  30. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/LICENSE +0 -0
  31. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/api/common.py +0 -0
  32. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/api/error_handlers.py +0 -0
  33. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/api/exceptions.py +0 -0
  34. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/api/route_loader.py +0 -0
  35. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/bootstrap/__init__.py +0 -0
  36. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/bootstrap/configuration.py +0 -0
  37. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/bootstrap/seeders.py +0 -0
  38. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/bootstrap/startup.py +0 -0
  39. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/contracts/__init__.py +0 -0
  40. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/contracts/repository.py +0 -0
  41. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/contracts/view_repository.py +0 -0
  42. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/py.typed +0 -0
  43. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/__init__.py +0 -0
  44. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/dynamodb_repo/dynamodb_mapper.py +0 -0
  45. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/dynamodb_repo/dynamodb_repo.py +0 -0
  46. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/filter_ops.py +0 -0
  47. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/memory_repo/__init__.py +0 -0
  48. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/memory_repo/memory_repo.py +0 -0
  49. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/mongo_repo/__init__.py +0 -0
  50. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/mongo_repo/mongo_mapper.py +0 -0
  51. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/mongo_repo/mongo_repo.py +0 -0
  52. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/sqlalchemy_repo/__init__.py +0 -0
  53. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/sqlalchemy_repo/schema_evolve.py +0 -0
  54. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/sqlalchemy_repo/sqlalchemy_dataclass_mapper.py +0 -0
  55. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/sqlalchemy_repo/sqlalchemy_repo.py +0 -0
  56. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository/sqlalchemy_repo/table_factory.py +0 -0
  57. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/__init__.py +0 -0
  58. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/factory/__init__.py +0 -0
  59. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/factory/repository_factory.py +0 -0
  60. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/registry/__init__.py +0 -0
  61. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/registry/entity_registry.py +0 -0
  62. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/view/__init__.py +0 -0
  63. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/repository_factory/view/populating_repository.py +0 -0
  64. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/settings/constants.py +0 -0
  65. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/settings/parsers.py +0 -0
  66. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/settings/repo_settings.py +0 -0
  67. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/utils/__init__.py +0 -0
  68. {persistence_kit-3.0.2 → persistence_kit-3.2.0}/persistence_kit/utils/upsert.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: persistence-kit
3
- Version: 3.0.2
3
+ Version: 3.2.0
4
4
  Summary: Reusable persistence and repository toolkit
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -18,11 +18,20 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python :: 3.14
19
19
  Classifier: Topic :: Database
20
20
  Classifier: Typing :: Typed
21
+ Provides-Extra: all
22
+ Provides-Extra: api
23
+ Provides-Extra: dynamodb
24
+ Provides-Extra: security
25
+ Provides-Extra: security-cognito
26
+ Provides-Extra: storage-routes
27
+ Provides-Extra: storage-s3
28
+ Provides-Extra: testing
21
29
  Requires-Dist: asyncpg (>=0.30.0,<0.31.0)
22
- Requires-Dist: boto3 (>=1.35.0,<2.0.0)
23
- Requires-Dist: fastapi (>=0.115.0,<0.116.0)
30
+ Requires-Dist: boto3 (>=1.35.0,<2.0.0) ; extra == "storage-s3" or extra == "security-cognito" or extra == "dynamodb" or extra == "all"
31
+ Requires-Dist: fastapi (>=0.115.0,<0.116.0) ; extra == "api" or extra == "storage-routes" or extra == "security" or extra == "security-cognito" or extra == "testing" or extra == "all"
24
32
  Requires-Dist: motor (>=3.7.1,<4.0.0)
25
33
  Requires-Dist: pydantic-settings (>=2.3.0,<3.0.0)
34
+ Requires-Dist: pyjwt[crypto] (>=2.10.1,<3.0.0) ; extra == "security" or extra == "security-cognito" or extra == "testing" or extra == "all"
26
35
  Requires-Dist: sqlalchemy[asyncio] (>=2.0.43,<3.0.0)
27
36
  Requires-Dist: typing-extensions (>=4.12.0,<5.0.0)
28
37
  Project-URL: Documentation, https://github.com/andresfserrano/persistence-kit#readme
@@ -53,6 +62,8 @@ Author: Andres Felipe Serrano Barrios
53
62
  - `api/`: reusable API exceptions, handlers, and route loading helpers
54
63
  - `bootstrap/`: startup helpers, configuration registry, and seed orchestration
55
64
  - `utils/`: transversal helpers such as upsert utilities
65
+ - `storage/`: reusable object storage contracts and local/S3 adapters
66
+ - `security/`: reusable identity provider contracts, Cognito/memory adapters, and JWT verifiers
56
67
  - `repository/`: concrete repository implementations by backend
57
68
  - `repository_factory/`: entity registry, repository creation, and populated view repository
58
69
 
@@ -67,6 +78,28 @@ Recommended rule:
67
78
  pip install persistence-kit
68
79
  ```
69
80
 
81
+ The base install keeps optional capabilities out of the dependency graph. Enable
82
+ only what the host project uses:
83
+
84
+ ```bash
85
+ pip install "persistence-kit[api]"
86
+ pip install "persistence-kit[security]"
87
+ pip install "persistence-kit[security-cognito]"
88
+ pip install "persistence-kit[storage-s3]"
89
+ pip install "persistence-kit[storage-routes]"
90
+ pip install "persistence-kit[dynamodb]"
91
+ ```
92
+
93
+ Available capabilities:
94
+
95
+ - `api`: FastAPI exceptions, pagination helpers, route loading, and error handlers.
96
+ - `security`: memory identity provider and JWT verifier.
97
+ - `security-cognito`: security plus Cognito and AWS/JWKS dependencies.
98
+ - `storage-s3`: S3 object storage adapter.
99
+ - `storage-routes`: FastAPI local export download router.
100
+ - `dynamodb`: DynamoDB repository backend.
101
+ - `all`: every optional capability.
102
+
70
103
  ## Quick Start
71
104
 
72
105
  ```python
@@ -96,10 +129,25 @@ from persistence_kit import (
96
129
  Repository,
97
130
  ViewRepository,
98
131
  RepoSettings,
132
+ PersistenceKitSettings,
133
+ AuthProvider,
134
+ ExportStorageProvider,
99
135
  Database,
100
136
  ConfigRegistry,
101
137
  configuration,
102
138
  SeederProvider,
139
+ ObjectStorage,
140
+ LocalObjectStorage,
141
+ S3ObjectStorage,
142
+ get_export_storage,
143
+ build_local_export_storage_router,
144
+ IdentityProvider,
145
+ MemorySecurityProvider,
146
+ CognitoIdentityProvider,
147
+ MemoryJwtVerifier,
148
+ CognitoJwtVerifier,
149
+ get_identity_provider,
150
+ get_token_verifier,
103
151
  build_api_router,
104
152
  handle_service_errors,
105
153
  handle_repository_errors,
@@ -125,6 +173,93 @@ Use internal paths only for implementation details, for example:
125
173
  - `persistence_kit.repository_factory.registry.entity_registry`
126
174
  - `persistence_kit.repository_factory.view.populating_repository`
127
175
 
176
+ ## Object Storage
177
+
178
+ `persistence_kit.storage` provides driven adapters for storing generated files or
179
+ binary objects outside the domain layer:
180
+
181
+ ```python
182
+ from persistence_kit.storage import LocalObjectStorage
183
+
184
+ storage = LocalObjectStorage(
185
+ base_dir=".local",
186
+ public_base_url="http://localhost:8000",
187
+ signing_secret="dev-secret",
188
+ )
189
+
190
+ key = await storage.upload("exports/report.csv", b"id,name\n1,Ada\n", "text/csv")
191
+ url = await storage.generate_presigned_url(key)
192
+ ```
193
+
194
+ Available adapters:
195
+
196
+ - `LocalObjectStorage`: stores files under a configured local directory and signs download URLs.
197
+ - `S3ObjectStorage`: uploads objects to S3 and returns AWS presigned URLs.
198
+
199
+ Backward-compatible aliases are exported for applications that previously used
200
+ `LocalExportStorageProvider` and `S3ExportStorageProvider`.
201
+
202
+ `get_export_storage(settings)` builds and caches the configured adapter from a
203
+ `PersistenceKitSettings` instance or a subclass inherited by the host app.
204
+
205
+ For FastAPI applications, `build_local_export_storage_router(...)` exposes a
206
+ reusable local download route. The host app passes its settings provider,
207
+ optional-current-user dependency, and product authorization callback.
208
+
209
+ Install `persistence-kit[storage-s3]` before using `S3ObjectStorage` and
210
+ `persistence-kit[storage-routes]` before using the FastAPI export route.
211
+
212
+ ## Security
213
+
214
+ `persistence_kit.security` provides reusable driven adapters for application
215
+ authentication flows:
216
+
217
+ ```python
218
+ from persistence_kit.security import MemorySecurityProvider, MemoryJwtVerifier
219
+
220
+ identity = MemorySecurityProvider(
221
+ jwt_secret="dev-secret-with-enough-length",
222
+ jwt_issuer="local-sandbox",
223
+ seed_role_users=True,
224
+ seed_role_codes=("admin", "operator"),
225
+ seed_user_domain="example.org",
226
+ )
227
+ verifier = MemoryJwtVerifier(secret="dev-secret-with-enough-length", issuer="local-sandbox")
228
+ ```
229
+
230
+ Available pieces:
231
+
232
+ - `IdentityProvider` and `TokenVerifier`: application-facing protocols.
233
+ - `MemorySecurityProvider`: local identity provider for tests/sandbox environments.
234
+ - `CognitoIdentityProvider`: AWS Cognito identity provider adapter.
235
+ - `MemoryJwtVerifier` and `CognitoJwtVerifier`: JWT token verifiers.
236
+ - Registration/login/password-reset result dataclasses and helper functions such as `unique_roles`.
237
+
238
+ Host applications should keep domain-specific roles, authorization policies,
239
+ scope rules, and route permission matrices outside the kit.
240
+
241
+ Install `persistence-kit[security]` for the memory provider/JWT verifier and
242
+ `persistence-kit[security-cognito]` for Cognito support.
243
+
244
+ `PersistenceKitSettings` centralizes common auth, storage, observability, AWS,
245
+ and job-service settings. Host applications can inherit from it and override
246
+ only product-specific defaults:
247
+
248
+ ```python
249
+ from persistence_kit import Database, PersistenceKitSettings
250
+
251
+
252
+ class Settings(PersistenceKitSettings):
253
+ service_name: str = "my-api"
254
+ key_status_history_database: Database = Database.MONGO
255
+ memory_seed_role_codes: tuple[str, ...] = ("admin", "operator")
256
+ ```
257
+
258
+ `persistence_kit.security.factory` can build the identity provider and token
259
+ verifier from that inherited settings object. `persistence_kit.storage.factory`
260
+ does the same for export storage, and `persistence_kit.storage.routes` exposes
261
+ the reusable FastAPI local export route.
262
+
128
263
  ## Typical Host Application Flow
129
264
 
130
265
  1. Define your entities as dataclasses.
@@ -150,13 +285,13 @@ Create the local environment and run tests from the library root:
150
285
 
151
286
  ```bash
152
287
  poetry lock
153
- poetry install --with dev
288
+ poetry install --with dev --all-extras
154
289
  poetry run pytest -q
155
290
  ```
156
291
 
157
292
  Current validation baseline:
158
293
 
159
- - `persistence_kit`: `138 passed`
294
+ - `persistence_kit`: `335 passed`
160
295
 
161
296
  ## Publish to PyPI (Manual)
162
297
 
@@ -21,6 +21,8 @@ Author: Andres Felipe Serrano Barrios
21
21
  - `api/`: reusable API exceptions, handlers, and route loading helpers
22
22
  - `bootstrap/`: startup helpers, configuration registry, and seed orchestration
23
23
  - `utils/`: transversal helpers such as upsert utilities
24
+ - `storage/`: reusable object storage contracts and local/S3 adapters
25
+ - `security/`: reusable identity provider contracts, Cognito/memory adapters, and JWT verifiers
24
26
  - `repository/`: concrete repository implementations by backend
25
27
  - `repository_factory/`: entity registry, repository creation, and populated view repository
26
28
 
@@ -35,6 +37,28 @@ Recommended rule:
35
37
  pip install persistence-kit
36
38
  ```
37
39
 
40
+ The base install keeps optional capabilities out of the dependency graph. Enable
41
+ only what the host project uses:
42
+
43
+ ```bash
44
+ pip install "persistence-kit[api]"
45
+ pip install "persistence-kit[security]"
46
+ pip install "persistence-kit[security-cognito]"
47
+ pip install "persistence-kit[storage-s3]"
48
+ pip install "persistence-kit[storage-routes]"
49
+ pip install "persistence-kit[dynamodb]"
50
+ ```
51
+
52
+ Available capabilities:
53
+
54
+ - `api`: FastAPI exceptions, pagination helpers, route loading, and error handlers.
55
+ - `security`: memory identity provider and JWT verifier.
56
+ - `security-cognito`: security plus Cognito and AWS/JWKS dependencies.
57
+ - `storage-s3`: S3 object storage adapter.
58
+ - `storage-routes`: FastAPI local export download router.
59
+ - `dynamodb`: DynamoDB repository backend.
60
+ - `all`: every optional capability.
61
+
38
62
  ## Quick Start
39
63
 
40
64
  ```python
@@ -64,10 +88,25 @@ from persistence_kit import (
64
88
  Repository,
65
89
  ViewRepository,
66
90
  RepoSettings,
91
+ PersistenceKitSettings,
92
+ AuthProvider,
93
+ ExportStorageProvider,
67
94
  Database,
68
95
  ConfigRegistry,
69
96
  configuration,
70
97
  SeederProvider,
98
+ ObjectStorage,
99
+ LocalObjectStorage,
100
+ S3ObjectStorage,
101
+ get_export_storage,
102
+ build_local_export_storage_router,
103
+ IdentityProvider,
104
+ MemorySecurityProvider,
105
+ CognitoIdentityProvider,
106
+ MemoryJwtVerifier,
107
+ CognitoJwtVerifier,
108
+ get_identity_provider,
109
+ get_token_verifier,
71
110
  build_api_router,
72
111
  handle_service_errors,
73
112
  handle_repository_errors,
@@ -93,6 +132,93 @@ Use internal paths only for implementation details, for example:
93
132
  - `persistence_kit.repository_factory.registry.entity_registry`
94
133
  - `persistence_kit.repository_factory.view.populating_repository`
95
134
 
135
+ ## Object Storage
136
+
137
+ `persistence_kit.storage` provides driven adapters for storing generated files or
138
+ binary objects outside the domain layer:
139
+
140
+ ```python
141
+ from persistence_kit.storage import LocalObjectStorage
142
+
143
+ storage = LocalObjectStorage(
144
+ base_dir=".local",
145
+ public_base_url="http://localhost:8000",
146
+ signing_secret="dev-secret",
147
+ )
148
+
149
+ key = await storage.upload("exports/report.csv", b"id,name\n1,Ada\n", "text/csv")
150
+ url = await storage.generate_presigned_url(key)
151
+ ```
152
+
153
+ Available adapters:
154
+
155
+ - `LocalObjectStorage`: stores files under a configured local directory and signs download URLs.
156
+ - `S3ObjectStorage`: uploads objects to S3 and returns AWS presigned URLs.
157
+
158
+ Backward-compatible aliases are exported for applications that previously used
159
+ `LocalExportStorageProvider` and `S3ExportStorageProvider`.
160
+
161
+ `get_export_storage(settings)` builds and caches the configured adapter from a
162
+ `PersistenceKitSettings` instance or a subclass inherited by the host app.
163
+
164
+ For FastAPI applications, `build_local_export_storage_router(...)` exposes a
165
+ reusable local download route. The host app passes its settings provider,
166
+ optional-current-user dependency, and product authorization callback.
167
+
168
+ Install `persistence-kit[storage-s3]` before using `S3ObjectStorage` and
169
+ `persistence-kit[storage-routes]` before using the FastAPI export route.
170
+
171
+ ## Security
172
+
173
+ `persistence_kit.security` provides reusable driven adapters for application
174
+ authentication flows:
175
+
176
+ ```python
177
+ from persistence_kit.security import MemorySecurityProvider, MemoryJwtVerifier
178
+
179
+ identity = MemorySecurityProvider(
180
+ jwt_secret="dev-secret-with-enough-length",
181
+ jwt_issuer="local-sandbox",
182
+ seed_role_users=True,
183
+ seed_role_codes=("admin", "operator"),
184
+ seed_user_domain="example.org",
185
+ )
186
+ verifier = MemoryJwtVerifier(secret="dev-secret-with-enough-length", issuer="local-sandbox")
187
+ ```
188
+
189
+ Available pieces:
190
+
191
+ - `IdentityProvider` and `TokenVerifier`: application-facing protocols.
192
+ - `MemorySecurityProvider`: local identity provider for tests/sandbox environments.
193
+ - `CognitoIdentityProvider`: AWS Cognito identity provider adapter.
194
+ - `MemoryJwtVerifier` and `CognitoJwtVerifier`: JWT token verifiers.
195
+ - Registration/login/password-reset result dataclasses and helper functions such as `unique_roles`.
196
+
197
+ Host applications should keep domain-specific roles, authorization policies,
198
+ scope rules, and route permission matrices outside the kit.
199
+
200
+ Install `persistence-kit[security]` for the memory provider/JWT verifier and
201
+ `persistence-kit[security-cognito]` for Cognito support.
202
+
203
+ `PersistenceKitSettings` centralizes common auth, storage, observability, AWS,
204
+ and job-service settings. Host applications can inherit from it and override
205
+ only product-specific defaults:
206
+
207
+ ```python
208
+ from persistence_kit import Database, PersistenceKitSettings
209
+
210
+
211
+ class Settings(PersistenceKitSettings):
212
+ service_name: str = "my-api"
213
+ key_status_history_database: Database = Database.MONGO
214
+ memory_seed_role_codes: tuple[str, ...] = ("admin", "operator")
215
+ ```
216
+
217
+ `persistence_kit.security.factory` can build the identity provider and token
218
+ verifier from that inherited settings object. `persistence_kit.storage.factory`
219
+ does the same for export storage, and `persistence_kit.storage.routes` exposes
220
+ the reusable FastAPI local export route.
221
+
96
222
  ## Typical Host Application Flow
97
223
 
98
224
  1. Define your entities as dataclasses.
@@ -118,13 +244,13 @@ Create the local environment and run tests from the library root:
118
244
 
119
245
  ```bash
120
246
  poetry lock
121
- poetry install --with dev
247
+ poetry install --with dev --all-extras
122
248
  poetry run pytest -q
123
249
  ```
124
250
 
125
251
  Current validation baseline:
126
252
 
127
- - `persistence_kit`: `138 passed`
253
+ - `persistence_kit`: `335 passed`
128
254
 
129
255
  ## Publish to PyPI (Manual)
130
256
 
@@ -0,0 +1,231 @@
1
+ from importlib import import_module
2
+
3
+ from .bootstrap.configuration import ConfigRegistry, configuration, set_config_package
4
+ from .bootstrap.seeders import Seeder, SeederProvider
5
+ from .bootstrap.startup import is_duplicate_startup_error, run_startup_bootstrap
6
+ from .contracts.repository import Repository
7
+ from .contracts.view_repository import ViewRepository
8
+ from .settings import (
9
+ DEFAULT_MEMORY_JWT_ISSUER,
10
+ DEFAULT_MEMORY_JWT_SECRET,
11
+ DEFAULT_MEMORY_JWT_TTL_SECONDS,
12
+ LOCAL_DEFAULT_JOB_SERVICE_API_KEY,
13
+ AuthProvider,
14
+ DeploymentStage,
15
+ ExportStorageProvider,
16
+ PersistenceKitSettings,
17
+ )
18
+ from .settings.constants import Database
19
+ from .settings.parsers import split_csv_list
20
+ from .settings.repo_settings import RepoSettings
21
+ from .storage import (
22
+ EXPORT_STORAGE_BUILDERS,
23
+ ExportStorage,
24
+ ExportStorageBuilder,
25
+ ObjectStorage,
26
+ StorageConfigError,
27
+ StorageError,
28
+ StoragePathError,
29
+ StoragePresignError,
30
+ StorageUploadError,
31
+ get_export_storage,
32
+ )
33
+ from .authenticated_user import AuthenticatedUser
34
+ from .utils.upsert import dataclass_field_names, upsert_entity
35
+
36
+ _OPTIONAL_EXPORTS = {
37
+ "ApiError": ("persistence_kit.api.common", "ApiError", "api"),
38
+ "pagination_params": ("persistence_kit.api.common", "pagination_params", "api"),
39
+ "BaseAPIException": ("persistence_kit.api.exceptions", "BaseAPIException", "api"),
40
+ "NotFoundException": ("persistence_kit.api.exceptions", "NotFoundException", "api"),
41
+ "ValidationException": ("persistence_kit.api.exceptions", "ValidationException", "api"),
42
+ "BusinessRuleException": (
43
+ "persistence_kit.api.exceptions",
44
+ "BusinessRuleException",
45
+ "api",
46
+ ),
47
+ "DatabaseException": ("persistence_kit.api.exceptions", "DatabaseException", "api"),
48
+ "handle_service_errors": (
49
+ "persistence_kit.api.error_handlers",
50
+ "handle_service_errors",
51
+ "api",
52
+ ),
53
+ "handle_repository_errors": (
54
+ "persistence_kit.api.error_handlers",
55
+ "handle_repository_errors",
56
+ "api",
57
+ ),
58
+ "build_api_router": ("persistence_kit.api.route_loader", "build_api_router", "api"),
59
+ "InMemoryRateLimiter": ("persistence_kit.api.rate_limit", "InMemoryRateLimiter", "api"),
60
+ "build_auth_rate_limit_dependency": (
61
+ "persistence_kit.api.rate_limit",
62
+ "build_auth_rate_limit_dependency",
63
+ "api",
64
+ ),
65
+ "IdentityProvider": ("persistence_kit.security.ports", "IdentityProvider", "security"),
66
+ "TokenVerifier": ("persistence_kit.security.ports", "TokenVerifier", "security"),
67
+ "CognitoIdentityProvider": (
68
+ "persistence_kit.security.providers",
69
+ "CognitoIdentityProvider",
70
+ "security-cognito",
71
+ ),
72
+ "MemorySecurityProvider": (
73
+ "persistence_kit.security.providers",
74
+ "MemorySecurityProvider",
75
+ "testing",
76
+ ),
77
+ "CognitoJwtVerifier": (
78
+ "persistence_kit.security.token_verifiers",
79
+ "CognitoJwtVerifier",
80
+ "security-cognito",
81
+ ),
82
+ "MemoryJwtVerifier": (
83
+ "persistence_kit.security.token_verifiers",
84
+ "MemoryJwtVerifier",
85
+ "testing",
86
+ ),
87
+ "get_identity_provider": (
88
+ "persistence_kit.security.factory",
89
+ "get_identity_provider",
90
+ "security",
91
+ ),
92
+ "get_token_verifier": (
93
+ "persistence_kit.security.factory",
94
+ "get_token_verifier",
95
+ "security",
96
+ ),
97
+ "RegistrationResult": (
98
+ "persistence_kit.security.registration",
99
+ "RegistrationResult",
100
+ "security",
101
+ ),
102
+ "RoleAssignmentResult": (
103
+ "persistence_kit.security.registration",
104
+ "RoleAssignmentResult",
105
+ "security",
106
+ ),
107
+ "UserStatusUpdateResult": (
108
+ "persistence_kit.security.registration",
109
+ "UserStatusUpdateResult",
110
+ "security",
111
+ ),
112
+ "LoginResult": ("persistence_kit.security.registration", "LoginResult", "security"),
113
+ "RefreshTokensResult": (
114
+ "persistence_kit.security.registration",
115
+ "RefreshTokensResult",
116
+ "security",
117
+ ),
118
+ "LogoutResult": ("persistence_kit.security.registration", "LogoutResult", "security"),
119
+ "PasswordResetCodeRequestResult": (
120
+ "persistence_kit.security.registration",
121
+ "PasswordResetCodeRequestResult",
122
+ "security",
123
+ ),
124
+ "PasswordResetConfirmResult": (
125
+ "persistence_kit.security.registration",
126
+ "PasswordResetConfirmResult",
127
+ "security",
128
+ ),
129
+ "PasswordResetResult": (
130
+ "persistence_kit.security.registration",
131
+ "PasswordResetResult",
132
+ "security",
133
+ ),
134
+ "RegisteredUserResult": (
135
+ "persistence_kit.security.registration",
136
+ "RegisteredUserResult",
137
+ "security",
138
+ ),
139
+ "RegisteredUsersPageResult": (
140
+ "persistence_kit.security.registration",
141
+ "RegisteredUsersPageResult",
142
+ "security",
143
+ ),
144
+ "validate_allowed_email_domain": (
145
+ "persistence_kit.security.registration",
146
+ "validate_allowed_email_domain",
147
+ "security",
148
+ ),
149
+ "unique_roles": ("persistence_kit.security.registration", "unique_roles", "security"),
150
+ "LocalObjectStorage": ("persistence_kit.storage.local", "LocalObjectStorage", "testing"),
151
+ "LocalExportStorageProvider": (
152
+ "persistence_kit.storage.local",
153
+ "LocalExportStorageProvider",
154
+ "testing",
155
+ ),
156
+ "S3ObjectStorage": ("persistence_kit.storage.s3", "S3ObjectStorage", "storage-s3"),
157
+ "S3ExportStorageProvider": (
158
+ "persistence_kit.storage.s3",
159
+ "S3ExportStorageProvider",
160
+ "storage-s3",
161
+ ),
162
+ "build_local_export_storage_router": (
163
+ "persistence_kit.storage.routes",
164
+ "build_local_export_storage_router",
165
+ "storage-routes",
166
+ ),
167
+ "serve_local_export": (
168
+ "persistence_kit.storage.routes",
169
+ "serve_local_export",
170
+ "storage-routes",
171
+ ),
172
+ "guess_export_media_type": (
173
+ "persistence_kit.storage.routes",
174
+ "guess_export_media_type",
175
+ "storage-routes",
176
+ ),
177
+ }
178
+
179
+ __all__ = [
180
+ "Repository",
181
+ "ViewRepository",
182
+ "split_csv_list",
183
+ "ConfigRegistry",
184
+ "configuration",
185
+ "Database",
186
+ "RepoSettings",
187
+ "AuthProvider",
188
+ "ExportStorageProvider",
189
+ "DeploymentStage",
190
+ "LOCAL_DEFAULT_JOB_SERVICE_API_KEY",
191
+ "DEFAULT_MEMORY_JWT_SECRET",
192
+ "DEFAULT_MEMORY_JWT_ISSUER",
193
+ "DEFAULT_MEMORY_JWT_TTL_SECONDS",
194
+ "PersistenceKitSettings",
195
+ "Seeder",
196
+ "SeederProvider",
197
+ "set_config_package",
198
+ "is_duplicate_startup_error",
199
+ "run_startup_bootstrap",
200
+ "AuthenticatedUser",
201
+ "dataclass_field_names",
202
+ "upsert_entity",
203
+ "ObjectStorage",
204
+ "StorageError",
205
+ "StorageConfigError",
206
+ "StoragePathError",
207
+ "StorageUploadError",
208
+ "StoragePresignError",
209
+ "ExportStorage",
210
+ "ExportStorageBuilder",
211
+ "EXPORT_STORAGE_BUILDERS",
212
+ "get_export_storage",
213
+ *_OPTIONAL_EXPORTS,
214
+ ]
215
+
216
+
217
+ def __getattr__(name: str):
218
+ if name not in _OPTIONAL_EXPORTS:
219
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
220
+
221
+ module_name, attr_name, extra_name = _OPTIONAL_EXPORTS[name]
222
+ try:
223
+ module = import_module(module_name)
224
+ except ModuleNotFoundError as exc:
225
+ raise ModuleNotFoundError(
226
+ f"{name} requiere la capability opcional '{extra_name}'. "
227
+ f"Instala con `persistence-kit[{extra_name}]`."
228
+ ) from exc
229
+ value = getattr(module, attr_name)
230
+ globals()[name] = value
231
+ return value
@@ -7,6 +7,7 @@ from .exceptions import (
7
7
  NotFoundException,
8
8
  ValidationException,
9
9
  )
10
+ from .rate_limit import InMemoryRateLimiter, build_auth_rate_limit_dependency
10
11
  from .route_loader import build_api_router
11
12
 
12
13
  __all__ = [
@@ -20,4 +21,6 @@ __all__ = [
20
21
  "handle_service_errors",
21
22
  "handle_repository_errors",
22
23
  "build_api_router",
24
+ "InMemoryRateLimiter",
25
+ "build_auth_rate_limit_dependency",
23
26
  ]