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.
- altcodepro_polydb_python-2.2.4.dist-info/METADATA +489 -0
- altcodepro_polydb_python-2.2.4.dist-info/RECORD +57 -0
- {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/WHEEL +1 -1
- polydb/__init__.py +2 -2
- polydb/adapters/AzureBlobStorageAdapter.py +146 -41
- polydb/adapters/AzureFileStorageAdapter.py +148 -43
- polydb/adapters/AzureQueueAdapter.py +96 -34
- polydb/adapters/AzureTableStorageAdapter.py +462 -119
- polydb/adapters/BlockchainBlobAdapter.py +111 -0
- polydb/adapters/BlockchainKVAdapter.py +152 -0
- polydb/adapters/BlockchainQueueAdapter.py +116 -0
- polydb/adapters/DynamoDBAdapter.py +463 -176
- polydb/adapters/FirestoreAdapter.py +320 -148
- polydb/adapters/GCPPubSubAdapter.py +217 -0
- polydb/adapters/GCPStorageAdapter.py +184 -39
- polydb/adapters/MongoDBAdapter.py +159 -39
- polydb/adapters/PostgreSQLAdapter.py +285 -83
- polydb/adapters/S3Adapter.py +172 -35
- polydb/adapters/S3CompatibleAdapter.py +62 -8
- polydb/adapters/SQSAdapter.py +121 -44
- polydb/adapters/VercelBlobAdapter.py +196 -0
- polydb/adapters/VercelKVAdapter.py +275 -283
- polydb/adapters/VercelQueueAdapter.py +61 -0
- polydb/audit/AuditStorage.py +1 -1
- polydb/base/NoSQLKVAdapter.py +113 -101
- polydb/base/ObjectStorageAdapter.py +42 -6
- polydb/base/QueueAdapter.py +2 -2
- polydb/base/SharedFilesAdapter.py +2 -2
- polydb/cloudDatabaseFactory.py +200 -0
- polydb/databaseFactory.py +434 -101
- polydb/models.py +63 -1
- polydb/query.py +111 -42
- altcodepro_polydb_python-2.2.2.dist-info/METADATA +0 -379
- altcodepro_polydb_python-2.2.2.dist-info/RECORD +0 -52
- polydb/adapters/PubSubAdapter.py +0 -85
- polydb/factory.py +0 -107
- {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/licenses/LICENSE +0 -0
- {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,,
|
polydb/adapters/PubSubAdapter.py
DELETED
|
@@ -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()
|
|
File without changes
|
{altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/top_level.txt
RENAMED
|
File without changes
|