altcodepro-polydb-python 2.2.2__py3-none-any.whl → 2.2.4__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 (38) hide show
  1. altcodepro_polydb_python-2.2.4.dist-info/METADATA +489 -0
  2. altcodepro_polydb_python-2.2.4.dist-info/RECORD +57 -0
  3. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/WHEEL +1 -1
  4. polydb/__init__.py +2 -2
  5. polydb/adapters/AzureBlobStorageAdapter.py +146 -41
  6. polydb/adapters/AzureFileStorageAdapter.py +148 -43
  7. polydb/adapters/AzureQueueAdapter.py +96 -34
  8. polydb/adapters/AzureTableStorageAdapter.py +462 -119
  9. polydb/adapters/BlockchainBlobAdapter.py +111 -0
  10. polydb/adapters/BlockchainKVAdapter.py +152 -0
  11. polydb/adapters/BlockchainQueueAdapter.py +116 -0
  12. polydb/adapters/DynamoDBAdapter.py +463 -176
  13. polydb/adapters/FirestoreAdapter.py +320 -148
  14. polydb/adapters/GCPPubSubAdapter.py +217 -0
  15. polydb/adapters/GCPStorageAdapter.py +184 -39
  16. polydb/adapters/MongoDBAdapter.py +159 -39
  17. polydb/adapters/PostgreSQLAdapter.py +285 -83
  18. polydb/adapters/S3Adapter.py +172 -35
  19. polydb/adapters/S3CompatibleAdapter.py +62 -8
  20. polydb/adapters/SQSAdapter.py +121 -44
  21. polydb/adapters/VercelBlobAdapter.py +196 -0
  22. polydb/adapters/VercelKVAdapter.py +275 -283
  23. polydb/adapters/VercelQueueAdapter.py +61 -0
  24. polydb/audit/AuditStorage.py +1 -1
  25. polydb/base/NoSQLKVAdapter.py +113 -101
  26. polydb/base/ObjectStorageAdapter.py +42 -6
  27. polydb/base/QueueAdapter.py +2 -2
  28. polydb/base/SharedFilesAdapter.py +2 -2
  29. polydb/cloudDatabaseFactory.py +200 -0
  30. polydb/databaseFactory.py +434 -101
  31. polydb/models.py +63 -1
  32. polydb/query.py +111 -42
  33. altcodepro_polydb_python-2.2.2.dist-info/METADATA +0 -379
  34. altcodepro_polydb_python-2.2.2.dist-info/RECORD +0 -52
  35. polydb/adapters/PubSubAdapter.py +0 -85
  36. polydb/factory.py +0 -107
  37. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/licenses/LICENSE +0 -0
  38. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/top_level.txt +0 -0
@@ -1,379 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: altcodepro-polydb-python
3
- Version: 2.2.2
4
- Summary: Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety
5
- Author: AltCodePro
6
- Project-URL: Homepage, https://github.com/altcodepro/polydb-python
7
- Project-URL: Documentation, https://github.com/altcodepro/polydb-python#readme
8
- Project-URL: Repository, https://github.com/altcodepro/polydb-python
9
- Project-URL: Bug Tracker, https://github.com/altcodepro/polydb-python/issues
10
- Keywords: database,cloud,multi-cloud,aws,azure,gcp,abstraction,nosql,sql,postgres,mongodb,dynamodb,s3
11
- Classifier: Development Status :: 4 - Beta
12
- Classifier: Intended Audience :: Developers
13
- Classifier: Topic :: Database
14
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
- Classifier: License :: OSI Approved :: MIT License
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.8
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Operating System :: OS Independent
23
- Requires-Python: >=3.8
24
- Description-Content-Type: text/markdown
25
- License-File: LICENSE
26
- Requires-Dist: psycopg2-binary>=2.9.11
27
- Requires-Dist: tenacity>=9.1.4
28
- Requires-Dist: redis>=6.4.0
29
- Requires-Dist: python-dotenv>=1.1.1
30
- Provides-Extra: aws
31
- Requires-Dist: boto3>=1.42.47; extra == "aws"
32
- Requires-Dist: botocore>=1.42.47; extra == "aws"
33
- Provides-Extra: azure
34
- Requires-Dist: azure-core>=1.38.1; extra == "azure"
35
- Requires-Dist: azure-data-tables>=12.7.0; extra == "azure"
36
- Requires-Dist: azure-storage-blob>=12.28.0; extra == "azure"
37
- Requires-Dist: azure-storage-file-share>=12.24.0; extra == "azure"
38
- Requires-Dist: azure-storage-queue>=12.15.0; extra == "azure"
39
- Provides-Extra: gcp
40
- Requires-Dist: google-api-core>=2.29.0; extra == "gcp"
41
- Requires-Dist: google-auth>=2.48.0; extra == "gcp"
42
- Requires-Dist: google-cloud-core>=2.5.0; extra == "gcp"
43
- Requires-Dist: google-cloud-firestore>=2.23.0; extra == "gcp"
44
- Requires-Dist: google-cloud-pubsub>=2.35.0; extra == "gcp"
45
- Requires-Dist: google-cloud-storage>=3.9.0; extra == "gcp"
46
- Provides-Extra: mongodb
47
- Requires-Dist: pymongo>=4.16.0; extra == "mongodb"
48
- Provides-Extra: rabbitmq
49
- Requires-Dist: pika>=1.3.2; extra == "rabbitmq"
50
- Provides-Extra: vercel
51
- Requires-Dist: requests>=2.32.5; extra == "vercel"
52
- Provides-Extra: generic
53
- Requires-Dist: pymongo>=4.16.0; extra == "generic"
54
- Requires-Dist: pika>=1.3.2; extra == "generic"
55
- Requires-Dist: boto3>=1.42.47; extra == "generic"
56
- Provides-Extra: all
57
- Requires-Dist: boto3>=1.42.47; extra == "all"
58
- Requires-Dist: botocore>=1.42.47; extra == "all"
59
- Requires-Dist: azure-core>=1.38.1; extra == "all"
60
- Requires-Dist: azure-data-tables>=12.7.0; extra == "all"
61
- Requires-Dist: azure-storage-blob>=12.28.0; extra == "all"
62
- Requires-Dist: azure-storage-file-share>=12.24.0; extra == "all"
63
- Requires-Dist: azure-storage-queue>=12.15.0; extra == "all"
64
- Requires-Dist: google-cloud-firestore>=2.23.0; extra == "all"
65
- Requires-Dist: google-cloud-pubsub>=2.35.0; extra == "all"
66
- Requires-Dist: google-cloud-storage>=3.9.0; extra == "all"
67
- Requires-Dist: pymongo>=4.16.0; extra == "all"
68
- Requires-Dist: pika>=1.3.2; extra == "all"
69
- Requires-Dist: requests>=2.32.5; extra == "all"
70
- Provides-Extra: dev
71
- Requires-Dist: black>=26.1.0; extra == "dev"
72
- Requires-Dist: flake8>=7.3.0; extra == "dev"
73
- Requires-Dist: isort>=7.0.0; extra == "dev"
74
- Requires-Dist: mypy>=1.19.1; extra == "dev"
75
- Provides-Extra: test
76
- Requires-Dist: pytest>=9.0.2; extra == "test"
77
- Requires-Dist: pytest-cov>=7.0.0; extra == "test"
78
- Requires-Dist: pytest-mock>=3.15.1; extra == "test"
79
- Requires-Dist: moto>=5.1.21; extra == "test"
80
- Dynamic: license-file
81
-
82
- # PolyDB v2.2.2 - Enterprise Database Abstraction Layer
83
-
84
- **Production-ready, cloud-independent database abstraction with full LINQ support, field-level audit, cache, and overflow storage**
85
-
86
- ## Features
87
-
88
- ✅ **LINQ-Style Queries** - All SQL clauses: WHERE, ORDER BY, SELECT, GROUP BY, DISTINCT, COUNT
89
- ✅ **Multi-Cloud** - Azure, AWS, GCP, Vercel, MongoDB, PostgreSQL
90
- ✅ **Automatic Overflow** - Large NoSQL records → Object Storage (transparent)
91
- ✅ **Enterprise Audit** - Cryptographic hash chain, field-level changes, strict ordering
92
- ✅ **Cache Engine** - In-memory with TTL, automatic invalidation
93
- ✅ **Soft Delete** - Optional logical deletion with audit trail
94
- ✅ **Auto-Inject** - Tenant ID, audit fields (created_at, updated_by, etc.)
95
- ✅ **Thread-Safe** - Connection pooling, distributed-safe hash chaining
96
- ✅ **Retry Logic** - Exponential backoff, configurable
97
- ✅ **Type-Safe** - Protocol-based adapters, full type hints
98
-
99
- ## Quick Start
100
-
101
- ```python
102
- from polydb import DatabaseFactory, polydb_model, QueryBuilder, Operator, AuditContext
103
-
104
- # 1. Define model
105
- @polydb_model
106
- class User:
107
- __polydb__ = {
108
- "storage": "sql",
109
- "table": "users",
110
- "cache": True,
111
- "cache_ttl": 600,
112
- }
113
-
114
- # 2. Initialize
115
- db = DatabaseFactory(
116
- enable_audit=True,
117
- enable_cache=True,
118
- soft_delete=True,
119
- )
120
-
121
- # 3. Set context (per-request)
122
- AuditContext.set(
123
- actor_id="user_123",
124
- roles=["admin"],
125
- tenant_id="tenant_abc",
126
- )
127
-
128
- # 4. CRUD with auto-audit
129
- user = db.create(User, {"name": "John", "email": "john@example.com"})
130
- # Auto-injects: tenant_id, created_at, created_by, updated_at, updated_by
131
-
132
- # 5. LINQ queries
133
- query = (
134
- QueryBuilder()
135
- .where("role", Operator.EQ, "admin")
136
- .where("age", Operator.GTE, 18)
137
- .order_by("created_at", descending=True)
138
- .skip(10)
139
- .take(20)
140
- .select("id", "name", "email")
141
- )
142
-
143
- admins = db.query_linq(User, query)
144
- ```
145
-
146
- ## LINQ Operations
147
-
148
- ### Filters
149
- ```python
150
- builder.where("field", Operator.EQ, value) # ==
151
- builder.where("field", Operator.NE, value) # !=
152
- builder.where("field", Operator.GT, value) # >
153
- builder.where("field", Operator.GTE, value) # >=
154
- builder.where("field", Operator.LT, value) # <
155
- builder.where("field", Operator.LTE, value) # <=
156
- builder.where("field", Operator.IN, [1,2,3]) # IN
157
- builder.where("field", Operator.CONTAINS, "text") # LIKE
158
- builder.where("field", Operator.STARTS_WITH, "prefix")
159
- builder.where("field", Operator.ENDS_WITH, "suffix")
160
- ```
161
-
162
- ### Ordering & Pagination
163
- ```python
164
- builder.order_by("field", descending=True)
165
- builder.skip(10)
166
- builder.take(20)
167
- ```
168
-
169
- ### Projection
170
- ```python
171
- builder.select("id", "name", "email")
172
- ```
173
-
174
- ### Aggregation
175
- ```python
176
- builder.count()
177
- builder.distinct_on()
178
- builder.group_by("role", "department")
179
- ```
180
-
181
- ## NoSQL Overflow Storage
182
-
183
- Records >1MB automatically stored in object storage:
184
-
185
- ```python
186
- @polydb_model
187
- class Product:
188
- __polydb__ = {
189
- "storage": "nosql",
190
- "collection": "products",
191
- }
192
-
193
- # Large data automatically overflows
194
- product = db.create(Product, {
195
- "data": {"huge": "payload"} * 100000
196
- })
197
-
198
- # Transparent retrieval
199
- retrieved = db.read_one(Product, {"id": product["id"]})
200
- # User never knows it came from blob storage
201
- ```
202
-
203
- ## Enterprise Audit Trail
204
-
205
- ### Automatic Tracking
206
- - **Who**: actor_id, roles
207
- - **What**: action, model, entity_id, changed_fields
208
- - **When**: timestamp (microsecond precision)
209
- - **Where**: tenant_id, ip_address, user_agent
210
- - **Context**: trace_id, request_id
211
- - **Integrity**: cryptographic hash chain
212
-
213
- ### Field-Level Changes
214
- ```python
215
- db.update(User, user_id, {"email": "new@example.com"})
216
- # Audit log shows: changed_fields = ["email", "updated_at", "updated_by"]
217
- ```
218
-
219
- ### Verify Chain
220
- ```python
221
- from polydb.audit.storage import AuditStorage
222
-
223
- audit = AuditStorage()
224
- is_valid = audit.verify_chain(tenant_id="tenant_abc")
225
- ```
226
-
227
- ## Cache Engine
228
-
229
- ```python
230
- # Auto-cache from model metadata
231
- @polydb_model
232
- class User:
233
- __polydb__ = {
234
- "storage": "sql",
235
- "table": "users",
236
- "cache": True,
237
- "cache_ttl": 600, # 10 minutes
238
- }
239
-
240
- # Cached read
241
- users = db.read(User, {"role": "admin"})
242
-
243
- # Bypass cache
244
- users = db.read(User, {"role": "admin"}, no_cache=True)
245
-
246
- # Manual invalidation
247
- from polydb.cache import RedisCacheEngine
248
- cache = RedisCacheEngine()
249
- cache.invalidate("User")
250
- cache.clear()
251
- ```
252
-
253
- ## Soft Delete
254
-
255
- ```python
256
- db = DatabaseFactory(soft_delete=True)
257
-
258
- # Soft delete (sets deleted_at, deleted_by)
259
- db.delete(User, user_id)
260
-
261
- # Hard delete
262
- db.delete(User, user_id, hard=True)
263
-
264
- # Include deleted in queries
265
- all_users = db.read(User, {}, include_deleted=True)
266
- ```
267
-
268
- ## Pagination
269
-
270
- ```python
271
- page1, next_token = db.read_page(User, {"role": "admin"}, page_size=50)
272
- page2, token2 = db.read_page(User, {"role": "admin"}, page_size=50, continuation_token=next_token)
273
- ```
274
-
275
- ## Multi-Tenant
276
-
277
- ```python
278
- # Auto-inject tenant_id from context
279
- AuditContext.set(tenant_id="tenant_123", actor_id="user_456", roles=["admin"])
280
-
281
- user = db.create(User, {"name": "John"})
282
- # Result: {"name": "John", "tenant_id": "tenant_123", "created_by": "user_456", ...}
283
-
284
- # Filter by tenant (automatic)
285
- users = db.read(User, {}) # Only returns tenant_123 records
286
- ```
287
-
288
- ## Environment Variables
289
-
290
- ```bash
291
- # Provider selection (optional, auto-detected)
292
- CLOUD_PROVIDER=aws|azure|gcp|vercel|mongodb|postgresql
293
-
294
- # PostgreSQL
295
- POSTGRES_CONNECTION_STRING=postgresql://user:pass@host:5432/db
296
- POSTGRES_MIN_CONNECTIONS=2
297
- POSTGRES_MAX_CONNECTIONS=20
298
-
299
- # AWS
300
- AWS_ACCESS_KEY_ID=...
301
- AWS_SECRET_ACCESS_KEY=...
302
- DYNAMODB_TABLE_NAME=...
303
- S3_BUCKET_NAME=...
304
-
305
- # Azure
306
- AZURE_STORAGE_CONNECTION_STRING=...
307
- AZURE_TABLE_NAME=...
308
- AZURE_CONTAINER_NAME=...
309
-
310
- # GCP
311
- GOOGLE_CLOUD_PROJECT=...
312
- FIRESTORE_COLLECTION=...
313
- GCS_BUCKET_NAME=...
314
-
315
- # MongoDB
316
- MONGODB_URI=mongodb://...
317
- MONGODB_DATABASE=...
318
- MONGODB_COLLECTION=...
319
-
320
- # Vercel
321
- KV_URL=...
322
- KV_REST_API_TOKEN=...
323
- BLOB_READ_WRITE_TOKEN=...
324
- ```
325
-
326
- ## Model Metadata
327
-
328
- ```python
329
- @polydb_model
330
- class Entity:
331
- __polydb__ = {
332
- # Required
333
- "storage": "sql" | "nosql",
334
-
335
- # SQL
336
- "table": "table_name",
337
-
338
- # NoSQL
339
- "collection": "collection_name",
340
- "pk_field": "partition_key_field",
341
- "rk_field": "row_key_field",
342
-
343
- # Cache
344
- "cache": True,
345
- "cache_ttl": 300, # seconds
346
-
347
- # Optional
348
- "provider": "aws", # Override auto-detection
349
- }
350
- ```
351
-
352
- ## Thread Safety
353
-
354
- - Connection pooling with locks
355
- - Distributed-safe audit hash chaining
356
- - Cache with thread-safe operations
357
- - Retry logic with exponential backoff
358
-
359
- ## Performance
360
-
361
- - **SQL**: Connection pooling (min=2, max=20)
362
- - **NoSQL**: Client reuse, overflow storage
363
- - **Cache**: In-memory with automatic invalidation
364
- - **Retry**: Configurable backoff (0.5s-6s)
365
-
366
- ## Production Checklist
367
-
368
- ✅ Set `CLOUD_PROVIDER` explicitly
369
- ✅ Configure connection pool sizes
370
- ✅ Enable audit (`enable_audit=True`)
371
- ✅ Set cache TTL per model
372
- ✅ Use soft delete for compliance
373
- ✅ Set audit context per request
374
- ✅ Monitor audit chain integrity
375
- ✅ Configure retry attempts
376
-
377
- ## License
378
-
379
- MIT
@@ -1,52 +0,0 @@
1
- altcodepro_polydb_python-2.2.2.dist-info/licenses/LICENSE,sha256=9X8GLocsBwy-5aR5JGOt2SAMDDPs9Qv-YnqmHBHOXrw,1067
2
- polydb/__init__.py,sha256=u-YwcKMl-NkVemvAKqLgIHE2eQND64toGXyJ64JeF8U,1441
3
- polydb/advanced_query.py,sha256=cxMB-EB-qT3bWXJlhmjnMCUtrzogORWyoEfS50Dy7go,4280
4
- polydb/batch.py,sha256=_DjWZa1ZXYSk6MLKqFe0eT7SYVRZtYNqZb9bI8Y2sao,4566
5
- polydb/cache.py,sha256=FGg5ln2GPhUpj3fljdJ4cygNYhdwJmfQhDhA_2MvOFY,6290
6
- polydb/databaseFactory.py,sha256=ZMPzGeg6RQ-Sh3lWyN9kIk3_FITH8JtNlCZr2J9-VCY,26340
7
- polydb/decorators.py,sha256=Rzk8Bj8wHi8YFtc06HEYT5r_Vqqn7TGaCtR5qvHdY-E,420
8
- polydb/errors.py,sha256=rcFeBH0cenjJ86v0cmDc2Yjj4R019pLCBcTeSC4qps4,1428
9
- polydb/factory.py,sha256=qCZIK9X6s69DCwWWQbCST5MO411sb6hRa4rQQ59WJ70,4556
10
- polydb/json_safe.py,sha256=R5PrqAGirqjYKPyy-8KH-lSXjLH0FPr2TSGozy4eheU,149
11
- polydb/models.py,sha256=HZYKB67ayoS1D4qxYfNLrUplbk7W-SIpexUnz4foyuQ,923
12
- polydb/monitoring.py,sha256=pwR2p-sSlt6nA29lCAJFmdT0ODIyVQ9gSxB51hgaAbQ,10137
13
- polydb/multitenancy.py,sha256=9kyY98RpKg8xDy9ejB_MyV_YzF7eZd4uxashw5S8vlg,6408
14
- polydb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- polydb/query.py,sha256=qPisSV0i_GcgUz_DRKQPZy1TZ_6sEbbwQGhfh5BGWqQ,5097
16
- polydb/registry.py,sha256=g-jLKq5jzDvdZ24weAqZHSxUIUaBsu1TZghxRMqbUXQ,1926
17
- polydb/retry.py,sha256=etsj8MGo1WMvlcZMzWmFELAsWCRs-XPEuJe6K76QgbM,2548
18
- polydb/schema.py,sha256=VrOayX6V6AD2Qh3-lm4ZVPTpI24e4V52IYheZf2rNQ4,5812
19
- polydb/security.py,sha256=-bXdRjFmvq4X6ie6FrZMcO9ZbgjWFkNySSbRwFt1X1Q,16281
20
- polydb/types.py,sha256=XB_85Un8_aWt4dSfpjIGotHbK3KBY2WurQGXr9EOxWY,2992
21
- polydb/utils.py,sha256=G_ki5zKr5rGPgpFQM1CTq6twQd5OytaHKfet267MftM,1662
22
- polydb/validation.py,sha256=a1o1d02k3c6PWQwkBbw_0nEmIgrdB5RR8OcpNQMn4cA,4810
23
- polydb/adapters/AzureBlobStorageAdapter.py,sha256=knNpS-O-Kd7pDjMaP53sl7Tud_FUm5K7ZhdpVOm5Vmc,3124
24
- polydb/adapters/AzureFileStorageAdapter.py,sha256=EM6fzOLr7I8P4s0LgCcNrd3MuEkvOe2KeuwGHwrryW8,3168
25
- polydb/adapters/AzureQueueAdapter.py,sha256=Kut1p0KDMSTxVMmO9YJ1OoqVuuu9tYvtKzk84CWLryc,2487
26
- polydb/adapters/AzureTableStorageAdapter.py,sha256=qKvG6OujuvHYdv2U9BY7pqWRfsUfmE28USABeUpM5K4,7826
27
- polydb/adapters/DynamoDBAdapter.py,sha256=WvcnNdFpCkeIVeUgW60dfcvKjxEgvlrurflZzWxaX6U,8668
28
- polydb/adapters/EFSAdapter.py,sha256=GFHXn2fjohXxVJaM4ptbisEs5bwiwkHeQ1Av_5ILiCA,1688
29
- polydb/adapters/FirestoreAdapter.py,sha256=r0a1Act48CXGsVofZMCmelV-GE4fDnLgOHZ3jC7uEh0,7850
30
- polydb/adapters/GCPStorageAdapter.py,sha256=x_xcHE4w85hfJGfAqmc3Uu80KlXyCC0zssEfSOaMa6Y,2809
31
- polydb/adapters/MongoDBAdapter.py,sha256=aP_S3pLgoBthUNkOviAmxP-tlBsE5HXPBn33neEqthQ,4872
32
- polydb/adapters/PostgreSQLAdapter.py,sha256=aBPgh51513CcYmtRVZHj5fCmQPa1B-1zRUdmoYyx8N8,17053
33
- polydb/adapters/PubSubAdapter.py,sha256=1NFSj3-fZ84xAMhrbW1r6kMyTR8ntWcK4kiYpjPgMvA,3192
34
- polydb/adapters/S3Adapter.py,sha256=iw4bETrG5sPspQtYDadmTXbqydCXn-VEsGqHrvbYn9Y,3011
35
- polydb/adapters/S3CompatibleAdapter.py,sha256=3hiOVEqyGbRX1rnpeldea8aWljSlWgCN3iE-g_Bks0I,3513
36
- polydb/adapters/SQSAdapter.py,sha256=7DO0cPFW993oxKJ5gr6cmbG-4gDe4JaIj-RHvXiD-OU,2948
37
- polydb/adapters/VercelKVAdapter.py,sha256=jgD4rN6YYj_To1sN83MxkzEM8YRuYZ_Ulk7aRrIB7_I,12853
38
- polydb/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- polydb/audit/AuditStorage.py,sha256=w22LXLR0nohn7A5orIHob_KNyUEir8UgpPVnnnVojLE,4936
40
- polydb/audit/__init__.py,sha256=m_GE7gjLw00zfHX-1SpkF7QZpRE72HO699ZzKzqD3kc,244
41
- polydb/audit/context.py,sha256=-A1FMtmr-2snVAHpTrVT80u-D_MCaqX6AoV4Ku2bz_o,1955
42
- polydb/audit/manager.py,sha256=KzaaOf5bDfr4M-CkCAZBG_U_4xIBCKDLRAf3hsm-DAk,1236
43
- polydb/audit/models.py,sha256=BgkSEQRbjbourxyGcEeJYIYzozwTM-pqTiSOM_BhWHs,2256
44
- polydb/base/NoSQLKVAdapter.py,sha256=9qyKJt6EGdWdzSfKM15brVHMMqy932uJxACq-9bibGo,11468
45
- polydb/base/ObjectStorageAdapter.py,sha256=97ZGsOFOG3epS2ecF5GRtfx_opxcizNtKOduEc0aNxU,1216
46
- polydb/base/QueueAdapter.py,sha256=dVBlleJK0gNc0YliTVvvc7KO2VReQ7Ct1_Prdd2XP0s,746
47
- polydb/base/SharedFilesAdapter.py,sha256=BaDPXDTePvsMYEnKoZMi01tlnI_Ww0tOoHVupqle7vM,700
48
- polydb/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- altcodepro_polydb_python-2.2.2.dist-info/METADATA,sha256=hCW3c_3-nZYXjRvWRWSPsZyekD0x0QfrIAv2gS_5-M8,10866
50
- altcodepro_polydb_python-2.2.2.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
51
- altcodepro_polydb_python-2.2.2.dist-info/top_level.txt,sha256=WgLFWJoYjUhwvyPxJFl6jYLrVFuBJDX3OABf4ocwk_E,7
52
- altcodepro_polydb_python-2.2.2.dist-info/RECORD,,
@@ -1,85 +0,0 @@
1
- # src/polydb/adapters/PubSubAdapter.py
2
-
3
- from polydb.base.QueueAdapter import QueueAdapter
4
- from polydb.errors import ConnectionError, QueueError
5
- from polydb.retry import retry
6
- import os
7
- import threading
8
- from typing import Any, Dict, List
9
-
10
- from ..json_safe import json_safe
11
-
12
- class PubSubAdapter(QueueAdapter):
13
- """GCP Pub/Sub with client reuse"""
14
-
15
- def __init__(self):
16
- super().__init__()
17
- self.project_id = os.getenv("GOOGLE_CLOUD_PROJECT") or ""
18
- self.topic_name = os.getenv("PUBSUB_TOPIC", "default")
19
- self._publisher = None
20
- self._subscriber = None
21
- self._lock = threading.Lock()
22
- self._initialize_clients()
23
-
24
- def _initialize_clients(self):
25
- """Initialize Pub/Sub clients once"""
26
- try:
27
- from google.cloud import pubsub_v1
28
-
29
- with self._lock:
30
- if not self._publisher:
31
- self._publisher = pubsub_v1.PublisherClient()
32
- self._subscriber = pubsub_v1.SubscriberClient()
33
- self.logger.info("Initialized Pub/Sub clients")
34
- except Exception as e:
35
- raise ConnectionError(f"Failed to initialize Pub/Sub: {str(e)}")
36
-
37
- @retry(max_attempts=3, delay=1.0, exceptions=(QueueError,))
38
- def send(self, message: Dict[str, Any], queue_name: str = "default") -> str:
39
- """Send message to topic"""
40
- try:
41
- import json
42
-
43
- if self._publisher:
44
- topic_path = self._publisher.topic_path(
45
- self.project_id, queue_name or self.topic_name
46
- )
47
- data = json.dumps(message,default=json_safe).encode("utf-8")
48
- future = self._publisher.publish(topic_path, data)
49
- return future.result()
50
- return ""
51
- except Exception as e:
52
- raise QueueError(f"Pub/Sub send failed: {str(e)}")
53
-
54
- @retry(max_attempts=3, delay=1.0, exceptions=(QueueError,))
55
- def receive(self, queue_name: str = "default", max_messages: int = 1) -> List[Dict[str, Any]]:
56
- """Receive messages from subscription"""
57
- try:
58
- import json
59
-
60
- if self._subscriber:
61
- subscription_path = self._subscriber.subscription_path(
62
- self.project_id, queue_name or self.topic_name
63
- )
64
-
65
- response = self._subscriber.pull(
66
- subscription=subscription_path, max_messages=max_messages, timeout=5.0
67
- )
68
-
69
- messages = [
70
- json.loads(msg.message.data.decode()) for msg in response.received_messages
71
- ]
72
-
73
- # Acknowledge messages
74
- if response.received_messages:
75
- ack_ids = [msg.ack_id for msg in response.received_messages]
76
- self._subscriber.acknowledge(subscription=subscription_path, ack_ids=ack_ids)
77
-
78
- return messages
79
- return []
80
- except Exception as e:
81
- raise QueueError(f"Pub/Sub receive failed: {str(e)}")
82
-
83
- def delete(self, message_id: str, queue_name: str = "default") -> bool:
84
- """Messages are acknowledged upon receipt"""
85
- return True
polydb/factory.py DELETED
@@ -1,107 +0,0 @@
1
- # src/polydb/factory.py
2
- import os
3
- import threading
4
- from typing import Optional
5
-
6
- from .models import CloudProvider, PartitionConfig
7
- from .utils import setup_logger
8
-
9
-
10
- class CloudDatabaseFactory:
11
- """Cloud-independent factory with auto-detection"""
12
-
13
- def __init__(self, provider: Optional[CloudProvider] = None):
14
- self.logger = setup_logger(__name__)
15
- self.provider = provider or self._detect_provider()
16
- self.connections = {}
17
- self._lock = threading.Lock()
18
-
19
- self.logger.info(f"CloudDatabaseFactory provider: {self.provider.value}")
20
-
21
- def _detect_provider(self) -> CloudProvider:
22
- explicit = os.getenv('CLOUD_PROVIDER')
23
- if explicit:
24
- try:
25
- return CloudProvider(explicit.lower())
26
- except ValueError:
27
- self.logger.warning(f"Invalid CLOUD_PROVIDER: {explicit}")
28
-
29
- rules = [
30
- ('AZURE_STORAGE_CONNECTION_STRING', CloudProvider.AZURE),
31
- ('AWS_ACCESS_KEY_ID', CloudProvider.AWS),
32
- ('GOOGLE_CLOUD_PROJECT', CloudProvider.GCP),
33
- ('VERCEL_ENV', CloudProvider.VERCEL),
34
- ('MONGODB_URI', CloudProvider.MONGODB),
35
- ('POSTGRES_URL', CloudProvider.POSTGRESQL),
36
- ('POSTGRES_CONNECTION_STRING', CloudProvider.POSTGRESQL),
37
- ]
38
-
39
- for env_var, provider in rules:
40
- if os.getenv(env_var):
41
- return provider
42
-
43
- self.logger.warning("No provider detected, defaulting to PostgreSQL")
44
- return CloudProvider.POSTGRESQL
45
-
46
- def get_nosql_kv(self, partition_config: Optional[PartitionConfig] = None):
47
- if self.provider == CloudProvider.AZURE:
48
- from .adapters.AzureTableStorageAdapter import AzureTableStorageAdapter
49
- return AzureTableStorageAdapter(partition_config)
50
- elif self.provider == CloudProvider.AWS:
51
- from .adapters.DynamoDBAdapter import DynamoDBAdapter
52
- return DynamoDBAdapter(partition_config)
53
- elif self.provider == CloudProvider.GCP:
54
- from .adapters.FirestoreAdapter import FirestoreAdapter
55
- return FirestoreAdapter(partition_config)
56
- elif self.provider == CloudProvider.VERCEL:
57
- from .adapters.VercelKVAdapter import VercelKVAdapter
58
- return VercelKVAdapter(partition_config)
59
- else:
60
- from .adapters.MongoDBAdapter import MongoDBAdapter
61
- return MongoDBAdapter(partition_config)
62
-
63
- def get_object_storage(self):
64
- if self.provider == CloudProvider.AZURE:
65
- from .adapters.AzureBlobStorageAdapter import AzureBlobStorageAdapter
66
- return AzureBlobStorageAdapter()
67
- elif self.provider == CloudProvider.AWS:
68
- from .adapters.S3Adapter import S3Adapter
69
- return S3Adapter()
70
- elif self.provider == CloudProvider.GCP:
71
- from .adapters.GCPStorageAdapter import GCPStorageAdapter
72
- return GCPStorageAdapter()
73
- elif self.provider == CloudProvider.VERCEL:
74
- from .adapters.VercelKVAdapter import VercelBlobAdapter
75
- return VercelBlobAdapter()
76
- else:
77
- from .adapters.S3CompatibleAdapter import S3CompatibleAdapter
78
- return S3CompatibleAdapter()
79
-
80
- def get_queue(self):
81
- if self.provider == CloudProvider.AZURE:
82
- from .adapters.AzureQueueAdapter import AzureQueueAdapter
83
- return AzureQueueAdapter()
84
- elif self.provider == CloudProvider.AWS:
85
- from .adapters.SQSAdapter import SQSAdapter
86
- return SQSAdapter()
87
- elif self.provider == CloudProvider.GCP:
88
- from .adapters.PubSubAdapter import PubSubAdapter
89
- return PubSubAdapter()
90
- elif self.provider == CloudProvider.VERCEL:
91
- from .adapters.VercelKVAdapter import VercelQueueAdapter
92
- return VercelQueueAdapter()
93
-
94
- def get_shared_files(self):
95
- if self.provider == CloudProvider.AZURE:
96
- from .adapters.AzureFileStorageAdapter import AzureFileStorageAdapter
97
- return AzureFileStorageAdapter()
98
- elif self.provider == CloudProvider.AWS:
99
- from .adapters.EFSAdapter import EFSAdapter
100
- return EFSAdapter()
101
- elif self.provider == CloudProvider.GCP:
102
- from .adapters.GCPStorageAdapter import GCPStorageAdapter
103
- return GCPStorageAdapter()
104
-
105
- def get_sql(self):
106
- from .adapters.PostgreSQLAdapter import PostgreSQLAdapter
107
- return PostgreSQLAdapter()