altcodepro-polydb-python 2.3.3__tar.gz → 2.3.5__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 (81) hide show
  1. {altcodepro_polydb_python-2.3.3/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.3.5}/PKG-INFO +1 -1
  2. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/pyproject.toml +1 -1
  3. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
  4. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/AzureTableStorageAdapter.py +46 -38
  5. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/LICENSE +0 -0
  6. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/MANIFEST.in +0 -0
  7. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/README.md +0 -0
  8. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/example_usage.py +0 -0
  9. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/requirements-aws.txt +0 -0
  10. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/requirements-azure.txt +0 -0
  11. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/requirements-dev.txt +0 -0
  12. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/requirements-gcp.txt +0 -0
  13. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/requirements-generic.txt +0 -0
  14. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/requirements.txt +0 -0
  15. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/setup.cfg +0 -0
  16. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/setup.py +0 -0
  17. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +0 -0
  18. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
  19. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
  20. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
  21. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/PolyDB.py +0 -0
  22. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/__init__.py +0 -0
  23. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
  24. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
  25. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
  26. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
  27. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
  28. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
  29. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
  30. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/EFSAdapter.py +0 -0
  31. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/FirestoreAdapter.py +0 -0
  32. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
  33. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
  34. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/MongoDBAdapter.py +0 -0
  35. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/PostgreSQLAdapter.py +0 -0
  36. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/S3Adapter.py +0 -0
  37. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
  38. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/SQSAdapter.py +0 -0
  39. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
  40. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/VercelKVAdapter.py +0 -0
  41. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
  42. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/adapters/__init__.py +0 -0
  43. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/advanced_query.py +0 -0
  44. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/audit/AuditStorage.py +0 -0
  45. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/audit/__init__.py +0 -0
  46. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/audit/context.py +0 -0
  47. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/audit/manager.py +0 -0
  48. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/audit/models.py +0 -0
  49. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/base/NoSQLKVAdapter.py +0 -0
  50. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/base/ObjectStorageAdapter.py +0 -0
  51. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/base/QueueAdapter.py +0 -0
  52. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/base/SharedFilesAdapter.py +0 -0
  53. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/base/__init__.py +0 -0
  54. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/batch.py +0 -0
  55. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/cache.py +0 -0
  56. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/cloudDatabaseFactory.py +0 -0
  57. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/databaseFactory.py +0 -0
  58. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/decorators.py +0 -0
  59. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/errors.py +0 -0
  60. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/json_safe.py +0 -0
  61. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/models.py +0 -0
  62. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/monitoring.py +0 -0
  63. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/multitenancy.py +0 -0
  64. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/py.typed +0 -0
  65. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/query.py +0 -0
  66. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/registry.py +0 -0
  67. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/retry.py +0 -0
  68. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/schema.py +0 -0
  69. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/security.py +0 -0
  70. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/types.py +0 -0
  71. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/utils.py +0 -0
  72. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/src/polydb/validation.py +0 -0
  73. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_aws.py +0 -0
  74. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_azure.py +0 -0
  75. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_blockchain.py +0 -0
  76. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_cloud_factory.py +0 -0
  77. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_gcp.py +0 -0
  78. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_mongodb.py +0 -0
  79. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_multi_engine.py +0 -0
  80. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_postgresql.py +0 -0
  81. {altcodepro_polydb_python-2.3.3 → altcodepro_polydb_python-2.3.5}/tests/test_vercel.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: altcodepro-polydb-python
3
- Version: 2.3.3
3
+ Version: 2.3.5
4
4
  Summary: Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety
5
5
  Author: AltCodePro
6
6
  Project-URL: Homepage, https://github.com/altcodepro/polydb-python
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "altcodepro-polydb-python"
7
- version = "2.3.3"
7
+ version = "2.3.5"
8
8
  description = "Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: altcodepro-polydb-python
3
- Version: 2.3.3
3
+ Version: 2.3.5
4
4
  Summary: Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety
5
5
  Author: AltCodePro
6
6
  Project-URL: Homepage, https://github.com/altcodepro/polydb-python
@@ -213,7 +213,6 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
213
213
  def _pack_entity(self, model: type, pk: str, rk: str, data: JsonDict) -> JsonDict:
214
214
  entity: JsonDict = {"PartitionKey": pk, "RowKey": rk}
215
215
 
216
- # ✅ model isolation
217
216
  entity[_MODEL_FIELD] = model.__qualname__
218
217
 
219
218
  keymap: Dict[str, str] = {}
@@ -334,18 +333,18 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
334
333
  safe_pk = self._sanitize_pk_rk(pk)
335
334
  safe_rk = self._sanitize_pk_rk(rk)
336
335
 
336
+ # Pack entity (encoded for Azure Table)
337
337
  entity = self._pack_entity(model, safe_pk, safe_rk, data)
338
338
 
339
339
  # ---------------------------------------------------
340
- # SIZE ESTIMATION (Azure uses UTF-16 for strings)
340
+ # SIZE ESTIMATION (use ORIGINAL payload, not packed)
341
341
  # ---------------------------------------------------
342
- MAX_PROPERTY_CHARS = 30 * 1024 # ~30K chars safe under 32K limit
343
- MAX_ENTITY_SIZE = 40 * 1024 # conservative total entity threshold
342
+ MAX_PROPERTY_CHARS = 30 * 1024 # ~30K safe under UTF-16 32K limit
343
+ MAX_ENTITY_SIZE = 40 * 1024 # conservative total threshold
344
344
 
345
345
  def _is_large_string(val: Any) -> bool:
346
346
  return isinstance(val, str) and len(val) > MAX_PROPERTY_CHARS
347
347
 
348
- # Check if any property exceeds safe char limit
349
348
  has_large_property = False
350
349
  large_key = None
351
350
 
@@ -358,42 +357,40 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
358
357
  )
359
358
  break
360
359
 
361
- # Check full entity size
362
- entity_json = json.dumps(entity, default=json_safe)
363
- entity_size = len(entity_json.encode("utf-8"))
360
+ payload_json = json.dumps(data, default=json_safe)
361
+ payload_bytes = payload_json.encode("utf-8")
362
+ payload_size = len(payload_bytes)
364
363
 
365
- force_blob = has_large_property or entity_size > MAX_ENTITY_SIZE
364
+ force_blob = has_large_property or payload_size > MAX_ENTITY_SIZE
366
365
 
366
+ # ---------------------------------------------------
367
+ # BLOB OVERFLOW PATH
368
+ # ---------------------------------------------------
367
369
  if force_blob:
368
370
  logger.info(
369
371
  f"Entity exceeds safe limits → using blob storage "
370
- f"(size={entity_size//1024} KB, large_key={large_key})"
372
+ f"(size={payload_size // 1024} KB, large_key={large_key})"
371
373
  )
372
374
 
373
- # ---------------------------------------------------
374
- # STORE FULL ENTITY IN BLOB
375
- # ---------------------------------------------------
376
- full_payload_bytes = entity_json.encode("utf-8")
377
- checksum = hashlib.md5(full_payload_bytes).hexdigest()
375
+ checksum = hashlib.md5(payload_bytes).hexdigest()
378
376
  blob_key = self._blob_key(safe_pk, safe_rk, checksum)
379
377
 
380
- self._blob_upload(blob_key, full_payload_bytes)
378
+ # Upload ORIGINAL payload (not packed entity)
379
+ self._blob_upload(blob_key, payload_bytes)
381
380
 
382
- # ---------------------------------------------------
383
- # STORE REFERENCE IN TABLE
384
- # ---------------------------------------------------
381
+ # Build reference entity
385
382
  reference_entity = {
386
383
  "PartitionKey": safe_pk,
387
384
  "RowKey": safe_rk,
388
385
  _MODEL_FIELD: model.__qualname__,
389
386
  "_overflow": True,
390
387
  "_blob_key": blob_key,
391
- "_size": len(full_payload_bytes),
388
+ "_size": payload_size,
392
389
  "_checksum": checksum,
393
390
  "__keymap__": entity.get("__keymap__", "{}"),
394
391
  }
395
392
 
396
- # Keep only small searchable fields
393
+ # Keep only small queryable fields
397
394
  for k, v in entity.items():
398
395
  if k in ("PartitionKey", "RowKey", "__keymap__", _MODEL_FIELD):
399
396
  continue
@@ -410,29 +407,28 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
410
407
 
411
408
  self._table_client.upsert_entity(reference_entity)
412
409
 
413
- logger.info(f"Stored in blob: {blob_key} ({len(full_payload_bytes)//1024} KB)")
410
+ logger.info(f"Stored in blob: {blob_key} ({payload_size // 1024} KB)")
414
411
 
415
- return {
416
- "PartitionKey": safe_pk,
417
- "RowKey": safe_rk,
418
- "_overflow": True,
419
- "_blob_key": blob_key,
420
- "id": safe_rk,
421
- }
412
+ restored = self._unpack_entity(entity)
413
+ restored["_overflow"] = True
414
+ restored["_blob_key"] = blob_key
415
+ restored["_checksum"] = checksum
416
+ restored["_size"] = payload_size
417
+ restored["id"] = safe_rk
418
+
419
+ return restored
422
420
 
423
421
  # ---------------------------------------------------
424
422
  # NORMAL TABLE STORAGE
425
423
  # ---------------------------------------------------
426
424
  self._table_client.upsert_entity(entity)
427
425
 
428
- return {
429
- "PartitionKey": safe_pk,
430
- "RowKey": safe_rk,
431
- "id": safe_rk,
432
- }
426
+ restored = self._unpack_entity(entity)
427
+ restored["id"] = safe_rk
428
+
429
+ return restored
433
430
 
434
431
  except Exception as e:
435
- # Do NOT retry deterministic size errors
436
432
  if "PropertyValueTooLarge" in str(e):
437
433
  raise NoSQLError("Azure Table limit exceeded → must use blob overflow") from e
438
434
 
@@ -469,6 +465,9 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
469
465
 
470
466
  restored = json.loads(blob_data.decode("utf-8"))
471
467
  out = self._unpack_entity(restored)
468
+ out["_overflow"] = True
469
+ out["_blob_key"] = blob_key
470
+ out["_checksum"] = checksum
472
471
  if "id" not in out:
473
472
  out["id"] = safe_rk
474
473
  return out
@@ -541,10 +540,19 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
541
540
 
542
541
  if ent_dict.get("_overflow"):
543
542
  blob_key = ent_dict.get("_blob_key")
543
+ checksum = ent_dict.get("_checksum")
544
544
  if blob_key:
545
- blob_data = self._blob_download(blob_key)
546
- restored = json.loads(blob_data.decode("utf-8"))
547
- out = self._unpack_entity(restored)
545
+ try:
546
+ blob_data = self._blob_download(blob_key)
547
+ actual_checksum = hashlib.md5(blob_data).hexdigest()
548
+ if checksum and actual_checksum != checksum:
549
+ raise NoSQLError("Checksum mismatch")
550
+
551
+ restored = json.loads(blob_data.decode("utf-8"))
552
+ out = self._unpack_entity(restored)
553
+ except Exception as e:
554
+ logger.error(f"Blob read failed, falling back to table: {e}")
555
+ out = self._unpack_entity(ent_dict)
548
556
  else:
549
557
  out = self._unpack_entity(ent_dict)
550
558
  else: