altcodepro-polydb-python 2.5.10__tar.gz → 2.5.11__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 (125) hide show
  1. {altcodepro_polydb_python-2.5.10/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.5.11}/PKG-INFO +1 -1
  2. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/pyproject.toml +1 -1
  3. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
  4. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +7 -1
  5. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/PolyDB.py +1 -1
  6. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/__init__.py +25 -14
  7. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/AzureBlobStorageAdapter.py +2 -1
  8. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/AzureQueueAdapter.py +3 -5
  9. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/AzureTableStorageAdapter.py +7 -8
  10. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -1
  11. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/BlockchainFileAdapter.py +1 -1
  12. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/BlockchainKVAdapter.py +20 -5
  13. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -1
  14. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/DynamoDBAdapter.py +2 -6
  15. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/EFSAdapter.py +1 -1
  16. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/GCPFilestoreAdapter.py +1 -1
  17. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/GCPStorageAdapter.py +1 -1
  18. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/KafkaQueueAdapter.py +10 -16
  19. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/MongoDBAdapter.py +3 -5
  20. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/PostgreSQLAdapter.py +38 -13
  21. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/S3Adapter.py +1 -3
  22. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/S3CompatibleAdapter.py +1 -1
  23. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/SQSAdapter.py +1 -2
  24. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/VercelKVAdapter.py +6 -5
  25. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/VercelQueueAdapter.py +18 -4
  26. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/advanced_query.py +5 -4
  27. altcodepro_polydb_python-2.5.11/src/polydb/aio.py +198 -0
  28. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/audit/AuditStorage.py +14 -19
  29. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/audit/context.py +6 -5
  30. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/audit/manager.py +3 -3
  31. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/audit/models.py +3 -2
  32. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/base/NoSQLKVAdapter.py +22 -14
  33. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/base/ObjectStorageAdapter.py +3 -2
  34. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/base/QueueAdapter.py +2 -3
  35. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/base/SecretsAdapter.py +2 -1
  36. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/base/SharedFilesAdapter.py +2 -3
  37. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/batch.py +38 -49
  38. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/cache.py +5 -2
  39. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/cloudDatabaseFactory.py +59 -22
  40. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/databaseFactory.py +7 -13
  41. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/errors.py +2 -0
  42. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/json_safe.py +1 -2
  43. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/models.py +1 -1
  44. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/monitoring.py +27 -15
  45. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/multitenancy.py +50 -59
  46. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/observability/logging.py +0 -1
  47. altcodepro_polydb_python-2.5.11/src/polydb/overflow_gc.py +179 -0
  48. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/query.py +3 -1
  49. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/schema.py +45 -60
  50. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/security.py +7 -9
  51. altcodepro_polydb_python-2.5.11/src/polydb/services/__init__.py +9 -0
  52. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/services/compliance_service.py +10 -4
  53. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/services/security_service.py +9 -12
  54. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/types.py +28 -62
  55. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/utils.py +7 -8
  56. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/validation.py +50 -52
  57. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_advanced_query_injection.py +47 -26
  58. altcodepro_polydb_python-2.5.11/tests/test_async_api.py +220 -0
  59. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_atomic_decrement.py +36 -12
  60. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_audit_hmac.py +13 -15
  61. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_azure.py +14 -13
  62. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_azure_table_empty_filter.py +12 -6
  63. altcodepro_polydb_python-2.5.11/tests/test_blockchain_overflow_guard.py +174 -0
  64. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_cloud_factory.py +93 -2
  65. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_field_encryption.py +25 -9
  66. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_kafka.py +8 -3
  67. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_like_pattern_escaping.py +1 -4
  68. altcodepro_polydb_python-2.5.11/tests/test_monitoring_health.py +56 -0
  69. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_multi_engine.py +49 -37
  70. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_multitenancy_ddl_injection.py +8 -14
  71. altcodepro_polydb_python-2.5.11/tests/test_nosql_kv_overflow_write_path.py +162 -0
  72. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_observability.py +8 -9
  73. altcodepro_polydb_python-2.5.11/tests/test_overflow_gc.py +175 -0
  74. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_postgresql.py +44 -38
  75. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_rabbitmq.py +4 -0
  76. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_redis_kv.py +3 -0
  77. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_schema_ddl_injection.py +1 -4
  78. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_secrets_aws.py +1 -0
  79. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_secrets_vault.py +1 -0
  80. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_session_vars.py +9 -9
  81. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_vercel.py +34 -3
  82. altcodepro_polydb_python-2.5.10/src/polydb/decorators.py +0 -1040
  83. altcodepro_polydb_python-2.5.10/src/polydb/services/__init__.py +0 -9
  84. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/LICENSE +0 -0
  85. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/MANIFEST.in +0 -0
  86. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/README.md +0 -0
  87. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/requirements-aws.txt +0 -0
  88. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/requirements-azure.txt +0 -0
  89. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/requirements-dev.txt +0 -0
  90. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/requirements-gcp.txt +0 -0
  91. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/requirements-generic.txt +0 -0
  92. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/requirements.txt +0 -0
  93. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/setup.cfg +0 -0
  94. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/setup.py +0 -0
  95. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
  96. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
  97. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
  98. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/AWSSecretsManagerAdapter.py +0 -0
  99. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
  100. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/AzureKeyVaultAdapter.py +0 -0
  101. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/FirestoreAdapter.py +0 -0
  102. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/GCPPubSubAdapter.py +2 -2
  103. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/GCPSecretManagerAdapter.py +0 -0
  104. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/RabbitMQAdapter.py +2 -2
  105. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/VaultAdapter.py +0 -0
  106. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/VercelBlobAdapter.py +1 -1
  107. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/VercelFileAdapter.py +0 -0
  108. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/adapters/__init__.py +0 -0
  109. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/audit/__init__.py +2 -2
  110. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/base/__init__.py +0 -0
  111. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/observability/__init__.py +0 -0
  112. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/py.typed +0 -0
  113. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/registry.py +0 -0
  114. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/src/polydb/retry.py +1 -1
  115. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_audit_chain_cutover.py +0 -0
  116. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_aws.py +1 -1
  117. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_azure_queue_receipt_handle.py +0 -0
  118. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_azure_table_id_property_persisted.py +0 -0
  119. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_azure_table_id_return_value_sanitization_mismatch.py +0 -0
  120. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_azure_table_unpack_entity.py +0 -0
  121. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_blockchain.py +3 -3
  122. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_gcp.py +2 -2
  123. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_mongodb.py +1 -1
  124. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_nosql_operator_injection.py +0 -0
  125. {altcodepro_polydb_python-2.5.10 → altcodepro_polydb_python-2.5.11}/tests/test_queue_extend_delay_cancel.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: altcodepro-polydb-python
3
- Version: 2.5.10
3
+ Version: 2.5.11
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.5.10"
7
+ version = "2.5.11"
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.5.10
3
+ Version: 2.5.11
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
@@ -17,16 +17,17 @@ src/altcodepro_polydb_python.egg-info/top_level.txt
17
17
  src/polydb/PolyDB.py
18
18
  src/polydb/__init__.py
19
19
  src/polydb/advanced_query.py
20
+ src/polydb/aio.py
20
21
  src/polydb/batch.py
21
22
  src/polydb/cache.py
22
23
  src/polydb/cloudDatabaseFactory.py
23
24
  src/polydb/databaseFactory.py
24
- src/polydb/decorators.py
25
25
  src/polydb/errors.py
26
26
  src/polydb/json_safe.py
27
27
  src/polydb/models.py
28
28
  src/polydb/monitoring.py
29
29
  src/polydb/multitenancy.py
30
+ src/polydb/overflow_gc.py
30
31
  src/polydb/py.typed
31
32
  src/polydb/query.py
32
33
  src/polydb/registry.py
@@ -83,6 +84,7 @@ src/polydb/services/__init__.py
83
84
  src/polydb/services/compliance_service.py
84
85
  src/polydb/services/security_service.py
85
86
  tests/test_advanced_query_injection.py
87
+ tests/test_async_api.py
86
88
  tests/test_atomic_decrement.py
87
89
  tests/test_audit_chain_cutover.py
88
90
  tests/test_audit_hmac.py
@@ -94,16 +96,20 @@ tests/test_azure_table_id_property_persisted.py
94
96
  tests/test_azure_table_id_return_value_sanitization_mismatch.py
95
97
  tests/test_azure_table_unpack_entity.py
96
98
  tests/test_blockchain.py
99
+ tests/test_blockchain_overflow_guard.py
97
100
  tests/test_cloud_factory.py
98
101
  tests/test_field_encryption.py
99
102
  tests/test_gcp.py
100
103
  tests/test_kafka.py
101
104
  tests/test_like_pattern_escaping.py
102
105
  tests/test_mongodb.py
106
+ tests/test_monitoring_health.py
103
107
  tests/test_multi_engine.py
104
108
  tests/test_multitenancy_ddl_injection.py
109
+ tests/test_nosql_kv_overflow_write_path.py
105
110
  tests/test_nosql_operator_injection.py
106
111
  tests/test_observability.py
112
+ tests/test_overflow_gc.py
107
113
  tests/test_postgresql.py
108
114
  tests/test_queue_extend_delay_cancel.py
109
115
  tests/test_rabbitmq.py
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
- from typing import Any, Dict, List, Optional, Tuple, Type, Union
4
+ from typing import Any, Dict, List, Optional, Tuple, Type
5
5
 
6
6
  from .advanced_query import AdvancedQueryBuilder, QueryHelper
7
7
  from .batch import BatchOperations, BatchResult
@@ -4,32 +4,40 @@ PolyDB - Enterprise Cloud-Independent Database Abstraction
4
4
  Full LINQ support, field-level audit, cache, soft delete, overflow storage
5
5
  """
6
6
 
7
- __version__ = "2.5.10"
7
+ __version__ = "2.5.14"
8
8
 
9
- from .cloudDatabaseFactory import CloudDatabaseFactory
10
- from .databaseFactory import DatabaseFactory
11
- from .models import CloudProvider, PartitionConfig, MongoConfig, CosmosMongoConfig
12
- from .query import QueryBuilder, Operator
9
+ from .aio import AsyncDatabaseFactory, AsyncPolyDB
13
10
  from .audit.context import AuditContext
14
11
  from .cache import RedisCacheEngine as CacheEngine
12
+ from .cloudDatabaseFactory import CloudDatabaseFactory
13
+ from .databaseFactory import DatabaseFactory
15
14
  from .errors import (
15
+ AdapterConfigurationError,
16
16
  CloudDBError,
17
+ ConnectionError,
17
18
  DatabaseError,
19
+ InsufficientBalanceError,
20
+ InvalidModelMetadataError,
21
+ ModelNotRegisteredError,
18
22
  NoSQLError,
19
- StorageError,
20
- QueueError,
21
- ConnectionError,
22
- ValidationError,
23
+ OperationNotSupportedError,
23
24
  PolyDBError,
24
- ModelNotRegisteredError,
25
- InvalidModelMetadataError,
25
+ QueueError,
26
+ StorageError,
26
27
  UnsupportedStorageTypeError,
27
- AdapterConfigurationError,
28
- OperationNotSupportedError,
29
- InsufficientBalanceError,
28
+ ValidationError,
30
29
  )
30
+ from .models import CloudProvider, CosmosMongoConfig, MongoConfig, PartitionConfig
31
+ from .overflow_gc import GCReport, sweep_overflow_blobs
32
+ from .PolyDB import PolyDB
33
+ from .query import Operator, QueryBuilder
31
34
 
32
35
  __all__ = [
36
+ # Facade
37
+ "PolyDB",
38
+ # Async facade (see aio.py's own module docstring for the design)
39
+ "AsyncPolyDB",
40
+ "AsyncDatabaseFactory",
33
41
  # Factories
34
42
  "CloudDatabaseFactory",
35
43
  "DatabaseFactory",
@@ -44,6 +52,9 @@ __all__ = [
44
52
  # Audit & Cache
45
53
  "AuditContext",
46
54
  "CacheEngine",
55
+ # Overflow GC
56
+ "sweep_overflow_blobs",
57
+ "GCReport",
47
58
  # Errors
48
59
  "CloudDBError",
49
60
  "DatabaseError",
@@ -1,9 +1,10 @@
1
1
  # src/polydb/adapters/AzureBlobStorageAdapter.py
2
2
 
3
+ import mimetypes
3
4
  import os
4
5
  import threading
5
- import mimetypes
6
6
  from typing import Any, Dict, List, Optional
7
+
7
8
  from ..base.ObjectStorageAdapter import ObjectStorageAdapter
8
9
  from ..errors import ConnectionError, StorageError
9
10
  from ..retry import retry
@@ -1,17 +1,15 @@
1
1
  # src/polydb/adapters/AzureQueueAdapter.py
2
2
 
3
- import os
4
- import threading
5
3
  import json
4
+ import os
6
5
  import re
7
-
6
+ import threading
8
7
  from typing import Any, Dict, List, Optional
9
8
 
10
-
11
9
  from ..base.QueueAdapter import QueueAdapter
12
10
  from ..errors import ConnectionError, QueueError
13
- from ..retry import retry
14
11
  from ..json_safe import json_safe
12
+ from ..retry import retry
15
13
 
16
14
 
17
15
  class AzureQueueAdapter(QueueAdapter):
@@ -2,25 +2,24 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import os
6
- import re
7
- import json
8
5
  import base64
9
6
  import hashlib
10
- import threading
7
+ import json
11
8
  import logging
12
-
13
- from datetime import datetime, date
9
+ import os
10
+ import re
11
+ import threading
12
+ from datetime import date, datetime
14
13
  from decimal import Decimal
15
14
  from typing import Any, Dict, List, Optional
16
15
  from uuid import UUID
17
16
 
18
17
  from ..base.NoSQLKVAdapter import NoSQLKVAdapter
18
+ from ..errors import ConnectionError, NoSQLError
19
19
  from ..json_safe import json_safe
20
- from ..errors import NoSQLError, ConnectionError
20
+ from ..models import PageResult, PartitionConfig
21
21
  from ..retry import retry
22
22
  from ..types import JsonDict
23
- from ..models import PageResult, PartitionConfig
24
23
 
25
24
  logger = logging.getLogger(__name__)
26
25
 
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import os
4
4
  from typing import Any, Dict, List, Optional
5
5
 
6
-
7
6
  from dotenv import load_dotenv
8
7
 
9
8
  from ..base.ObjectStorageAdapter import ObjectStorageAdapter
@@ -8,7 +8,7 @@ from typing import List, Optional
8
8
  from dotenv import load_dotenv
9
9
 
10
10
  from ..base.SharedFilesAdapter import SharedFilesAdapter
11
- from ..errors import StorageError, ConnectionError
11
+ from ..errors import ConnectionError, StorageError
12
12
 
13
13
  SUPPORTED_CHAINS = {"ethereum", "polygon", "avalanche", "bnb", "arbitrum"}
14
14
 
@@ -5,9 +5,10 @@ import logging
5
5
  import os
6
6
  from typing import Any, Dict, Optional
7
7
 
8
-
9
8
  from dotenv import load_dotenv
10
9
 
10
+ from ..base.NoSQLKVAdapter import NoSQLKVAdapter
11
+
11
12
  logger = logging.getLogger(__name__)
12
13
 
13
14
  SUPPORTED_CHAINS = {
@@ -18,8 +19,18 @@ SUPPORTED_CHAINS = {
18
19
  "arbitrum",
19
20
  }
20
21
 
22
+ # On-chain storage is priced per byte of calldata/state -- a far lower ceiling
23
+ # than an off-chain KV store makes sense here, both for gas cost and because
24
+ # most chains cap contract call-data size well under 1MB. Anything over this
25
+ # spills to the paired object store via the inherited _check_overflow /
26
+ # _retrieve_overflow, the same "any size record" guarantee every other
27
+ # NoSQLKVAdapter gives (see CLAUDE.md's overflow section) -- previously this
28
+ # adapter had no size guard at all and would silently attempt an oversized,
29
+ # expensive (or outright rejected) on-chain write.
30
+ BLOCKCHAIN_MAX_SIZE = 8 * 1024
21
31
 
22
- class BlockchainKVAdapter:
32
+
33
+ class BlockchainKVAdapter(NoSQLKVAdapter):
23
34
  """
24
35
  Generic blockchain key-value adapter.
25
36
 
@@ -41,6 +52,9 @@ class BlockchainKVAdapter:
41
52
  contract_address: Optional[str] = None,
42
53
  contract_abi: Optional[list] = None,
43
54
  ):
55
+ super().__init__(partition_config=None)
56
+ self.max_size = BLOCKCHAIN_MAX_SIZE
57
+
44
58
  load_dotenv()
45
59
 
46
60
  self.chain = (chain or os.getenv("BLOCKCHAIN_CHAIN", "ethereum")).lower()
@@ -126,12 +140,13 @@ class BlockchainKVAdapter:
126
140
 
127
141
  def put(self, model, data: Dict[str, Any]) -> Dict[str, Any]:
128
142
  key = str(data["id"])
129
- payload = json.dumps(data)
143
+ store_data, _ = self._check_overflow(data)
144
+ payload = json.dumps(store_data)
130
145
 
131
146
  fn = self.contract.functions.put(key, payload)
132
147
  self._send_tx(fn)
133
148
 
134
- return data
149
+ return store_data
135
150
 
136
151
  def get(self, model, key: str) -> Optional[Dict[str, Any]]:
137
152
  result = self.contract.functions.get(str(key)).call()
@@ -139,7 +154,7 @@ class BlockchainKVAdapter:
139
154
  if not result:
140
155
  return None
141
156
 
142
- return json.loads(result)
157
+ return self._retrieve_overflow(json.loads(result))
143
158
 
144
159
  def delete(self, model, key: str):
145
160
  fn = self.contract.functions.deleteKey(str(key))
@@ -5,7 +5,6 @@ import logging
5
5
  import os
6
6
  from typing import Any, Dict, List, Optional
7
7
 
8
-
9
8
  from dotenv import load_dotenv
10
9
 
11
10
  from ..errors import QueueError
@@ -6,9 +6,9 @@ import hashlib
6
6
  import json
7
7
  import os
8
8
  import threading
9
- from polydb.errors import DatabaseError
10
9
  from typing import Any, Dict, List, Optional, Tuple
11
10
 
11
+ from polydb.errors import DatabaseError
12
12
 
13
13
  from ..base.NoSQLKVAdapter import NoSQLKVAdapter
14
14
  from ..errors import ConnectionError, NoSQLError
@@ -123,7 +123,6 @@ class DynamoDBAdapter(NoSQLKVAdapter):
123
123
  Ensure PK/SK table exists. Safe in prod (no-op if exists).
124
124
  Required for LocalStack integration tests.
125
125
  """
126
- from boto3.dynamodb.conditions import Attr, Key
127
126
  from botocore.exceptions import ClientError
128
127
 
129
128
  if not self._dynamodb:
@@ -322,7 +321,6 @@ class DynamoDBAdapter(NoSQLKVAdapter):
322
321
  Supports filters like {"id": "..."} and arbitrary Attr equality.
323
322
  """
324
323
  from boto3.dynamodb.conditions import Attr, Key
325
- from botocore.exceptions import ClientError
326
324
 
327
325
  try:
328
326
  table = self._get_table(model)
@@ -342,9 +340,7 @@ class DynamoDBAdapter(NoSQLKVAdapter):
342
340
  kwargs: Dict[str, Any] = {"KeyConditionExpression": key_cond}
343
341
 
344
342
  # Other filters as FilterExpression
345
- other = {
346
- k: v for k, v in filters.items() if k not in ("PK", "SK", "partition_key")
347
- }
343
+ other = {k: v for k, v in filters.items() if k not in ("PK", "SK", "partition_key")}
348
344
  if other:
349
345
  expr = None
350
346
  for k, v in other.items():
@@ -4,7 +4,7 @@ import os
4
4
  from typing import List, Optional
5
5
 
6
6
  from ..base.SharedFilesAdapter import SharedFilesAdapter
7
- from ..errors import StorageError, ConnectionError
7
+ from ..errors import ConnectionError, StorageError
8
8
 
9
9
 
10
10
  class EFSAdapter(SharedFilesAdapter):
@@ -4,7 +4,7 @@ import os
4
4
  from typing import List, Optional
5
5
 
6
6
  from ..base.SharedFilesAdapter import SharedFilesAdapter
7
- from ..errors import StorageError, ConnectionError
7
+ from ..errors import ConnectionError, StorageError
8
8
 
9
9
 
10
10
  class FilestoreAdapter(SharedFilesAdapter):
@@ -6,7 +6,7 @@ import threading
6
6
  from typing import Any, Dict, List, Optional
7
7
 
8
8
  from ..base.ObjectStorageAdapter import ObjectStorageAdapter
9
- from ..errors import StorageError, ConnectionError
9
+ from ..errors import ConnectionError, StorageError
10
10
  from ..retry import retry
11
11
 
12
12
 
@@ -1,14 +1,14 @@
1
1
  # src/polydb/adapters/KafkaQueueAdapter.py
2
- import os
3
2
  import json
3
+ import os
4
4
  import threading
5
5
  import uuid
6
- from typing import Any, Dict, List, Optional
6
+ from typing import Any, Dict, List
7
7
 
8
8
  from ..base.QueueAdapter import QueueAdapter
9
9
  from ..errors import ConnectionError, QueueError
10
- from ..retry import retry
11
10
  from ..json_safe import json_safe
11
+ from ..retry import retry
12
12
 
13
13
 
14
14
  class KafkaQueueAdapter(QueueAdapter):
@@ -47,9 +47,7 @@ class KafkaQueueAdapter(QueueAdapter):
47
47
  # partition assignment / offsets with each other. Callers that
48
48
  # actually want shared work-queue semantics across processes pass
49
49
  # an explicit group_id (or set KAFKA_GROUP_ID).
50
- self.group_id = (
51
- group_id or os.getenv("KAFKA_GROUP_ID") or f"polydb-{uuid.uuid4().hex[:12]}"
52
- )
50
+ self.group_id = group_id or os.getenv("KAFKA_GROUP_ID") or f"polydb-{uuid.uuid4().hex[:12]}"
53
51
  self.client_id = client_id or os.getenv("KAFKA_CLIENT_ID", "polydb")
54
52
  self.auto_offset_reset = auto_offset_reset
55
53
 
@@ -61,12 +59,8 @@ class KafkaQueueAdapter(QueueAdapter):
61
59
  "KAFKA_SECURITY_PROTOCOL", "PLAINTEXT"
62
60
  )
63
61
  self.sasl_mechanism = sasl_mechanism or os.getenv("KAFKA_SASL_MECHANISM") or None
64
- self.sasl_plain_username = (
65
- sasl_plain_username or os.getenv("KAFKA_SASL_USERNAME") or None
66
- )
67
- self.sasl_plain_password = (
68
- sasl_plain_password or os.getenv("KAFKA_SASL_PASSWORD") or None
69
- )
62
+ self.sasl_plain_username = sasl_plain_username or os.getenv("KAFKA_SASL_USERNAME") or None
63
+ self.sasl_plain_password = sasl_plain_password or os.getenv("KAFKA_SASL_PASSWORD") or None
70
64
  self.ssl_cafile = ssl_cafile or os.getenv("KAFKA_SSL_CAFILE") or None
71
65
 
72
66
  self._producer: Any = None
@@ -114,9 +108,7 @@ class KafkaQueueAdapter(QueueAdapter):
114
108
  value_serializer=lambda v: v,
115
109
  **self._client_kwargs(),
116
110
  )
117
- self.logger.info(
118
- f"Initialized Kafka producer (bootstrap={self.bootstrap_servers})"
119
- )
111
+ self.logger.info(f"Initialized Kafka producer (bootstrap={self.bootstrap_servers})")
120
112
  except Exception as e:
121
113
  raise ConnectionError(f"Kafka producer init failed: {e}")
122
114
  return self._producer
@@ -142,7 +134,9 @@ class KafkaQueueAdapter(QueueAdapter):
142
134
  auto_offset_reset=self.auto_offset_reset,
143
135
  **self._client_kwargs(),
144
136
  )
145
- self.logger.info(f"Initialized Kafka consumer (topic={topic}, group={self.group_id})")
137
+ self.logger.info(
138
+ f"Initialized Kafka consumer (topic={topic}, group={self.group_id})"
139
+ )
146
140
  except Exception as e:
147
141
  raise ConnectionError(f"Kafka consumer init failed: {e}")
148
142
  self._consumers[topic] = consumer
@@ -8,10 +8,10 @@ import threading
8
8
  from typing import Any, Dict, List, Optional
9
9
 
10
10
  from ..base.NoSQLKVAdapter import NoSQLKVAdapter
11
- from ..errors import NoSQLError, ConnectionError, DatabaseError
11
+ from ..errors import ConnectionError, DatabaseError, NoSQLError
12
+ from ..models import PartitionConfig
12
13
  from ..retry import retry
13
14
  from ..types import JsonDict
14
- from ..models import PartitionConfig
15
15
 
16
16
 
17
17
  def _as_literal(value: Any) -> Any:
@@ -122,9 +122,7 @@ class MongoDBAdapter(NoSQLKVAdapter):
122
122
  return
123
123
 
124
124
  try:
125
- collection.create_index(
126
- [("_pk", 1), ("_rk", 1)], unique=True, name="pk_rk_unique"
127
- )
125
+ collection.create_index([("_pk", 1), ("_rk", 1)], unique=True, name="pk_rk_unique")
128
126
  except Exception:
129
127
  self.logger.warning(
130
128
  "Could not ensure (_pk, _rk) index on %s",
@@ -1,24 +1,24 @@
1
1
  # src/polydb/adapters/postgres.py
2
+ import base64
3
+ import hashlib
4
+ import json
2
5
  import os
3
6
  import threading
4
7
  import time
5
- from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
6
- import hashlib
7
8
  from contextlib import contextmanager
8
- import json
9
- import base64
9
+ from datetime import date, datetime
10
10
  from decimal import Decimal
11
- from datetime import datetime, date
11
+ from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
12
12
 
13
13
  import psycopg2.extensions
14
14
  from psycopg2 import sql as pg_sql
15
15
  from psycopg2.extras import Json
16
16
 
17
- from ..errors import DatabaseError, ConnectionError, InsufficientBalanceError
17
+ from ..errors import ConnectionError, DatabaseError, InsufficientBalanceError
18
+ from ..query import Operator, QueryBuilder
18
19
  from ..retry import retry
19
- from ..utils import validate_table_name, validate_column_name
20
- from ..query import QueryBuilder, Operator
21
20
  from ..types import JsonDict, Lookup
21
+ from ..utils import validate_column_name, validate_table_name
22
22
 
23
23
  # Postgres session variables this adapter is willing to SET (scoped to one
24
24
  # transaction, via set_config(..., is_local=True)) on a caller's behalf.
@@ -89,8 +89,9 @@ class PostgreSQLAdapter:
89
89
 
90
90
  def _initialize_pool(self):
91
91
  try:
92
+ from urllib.parse import parse_qs, quote, urlencode, urlparse, urlunparse
93
+
92
94
  import psycopg2.pool
93
- from urllib.parse import urlparse, parse_qs, quote, urlencode, urlunparse
94
95
 
95
96
  dsn = self.connection_string
96
97
  if "postgresql://" in dsn:
@@ -157,7 +158,9 @@ class PostgreSQLAdapter:
157
158
  if pct > 80:
158
159
  self.logger.warning(
159
160
  "PostgreSQL pool utilization: %d/%d connections in use (%.0f%%)",
160
- used_count, maxconn, pct,
161
+ used_count,
162
+ maxconn,
163
+ pct,
161
164
  )
162
165
  except Exception:
163
166
  pass
@@ -212,7 +215,10 @@ class PostgreSQLAdapter:
212
215
  if duration_ms > self._slow_query_ms:
213
216
  self.logger.warning(
214
217
  "Slow query detected: operation=%s table=%s duration_ms=%.1f threshold=%.1f",
215
- operation, table, duration_ms, self._slow_query_ms,
218
+ operation,
219
+ table,
220
+ duration_ms,
221
+ self._slow_query_ms,
216
222
  )
217
223
 
218
224
  return duration_ms
@@ -313,8 +319,26 @@ class PostgreSQLAdapter:
313
319
  def _serialize_value(self, v: Any) -> Any:
314
320
  if v is None:
315
321
  return None
316
- if isinstance(v, (dict, list, tuple)):
322
+ if isinstance(v, dict):
317
323
  return Json(self._json_safe(v))
324
+ if isinstance(v, (list, tuple)):
325
+ # A bare list/tuple of scalars is a real Postgres array column
326
+ # (e.g. TEXT[]) -- psycopg2 adapts a plain Python list to that
327
+ # natively, so it must pass through untouched here, exactly
328
+ # like _serialize_param already does for query parameters
329
+ # (below). Only a list/tuple actually containing dicts is
330
+ # genuinely JSON-shaped (no Postgres array type holds JSON
331
+ # objects as elements), so that case alone still gets
332
+ # Json()-wrapped for a JSONB column. Wrapping every list
333
+ # unconditionally (the pre-fix behavior) sent a JSON string
334
+ # literal like '["x","y"]' to any TEXT[] column, which
335
+ # Postgres correctly refuses ("malformed array literal") --
336
+ # this insert/update/upsert path silently could never write
337
+ # a real array column at all.
338
+ seq = list(v)
339
+ if any(isinstance(x, dict) for x in seq):
340
+ return Json(self._json_safe(seq))
341
+ return seq
318
342
  if isinstance(v, (datetime, date)):
319
343
  return v
320
344
  if isinstance(v, Decimal):
@@ -779,6 +803,7 @@ class PostgreSQLAdapter:
779
803
  @property
780
804
  def capabilities(self):
781
805
  from ..models import BackendCapabilities
806
+
782
807
  return BackendCapabilities(
783
808
  server_order=True,
784
809
  server_filter=True,
@@ -814,7 +839,7 @@ class PostgreSQLAdapter:
814
839
 
815
840
  has_more = len(results) > request.limit
816
841
  if has_more:
817
- results = results[:request.limit]
842
+ results = results[: request.limit]
818
843
 
819
844
  next_cursor = None
820
845
  if has_more:
@@ -11,9 +11,8 @@ import os
11
11
  import threading
12
12
  from typing import Any, Dict, List, Optional
13
13
 
14
-
15
14
  from ..base.ObjectStorageAdapter import ObjectStorageAdapter
16
- from ..errors import StorageError, ConnectionError
15
+ from ..errors import ConnectionError, StorageError
17
16
  from ..retry import retry
18
17
 
19
18
 
@@ -72,7 +71,6 @@ class S3Adapter(ObjectStorageAdapter):
72
71
 
73
72
  def _ensure_bucket_exists(self):
74
73
  """Create bucket if it doesn't exist (safe for AWS + LocalStack)"""
75
- import boto3
76
74
  from botocore.exceptions import ClientError
77
75
 
78
76
  if not self._client:
@@ -5,7 +5,7 @@ import threading
5
5
  from typing import Any, Dict, List, Optional
6
6
 
7
7
  from ..base.ObjectStorageAdapter import ObjectStorageAdapter
8
- from ..errors import StorageError, ConnectionError
8
+ from ..errors import ConnectionError, StorageError
9
9
  from ..retry import retry
10
10
 
11
11
 
@@ -5,11 +5,10 @@ import os
5
5
  import threading
6
6
  from typing import Any, Dict, List
7
7
 
8
-
9
8
  from ..base.QueueAdapter import QueueAdapter
10
9
  from ..errors import ConnectionError, QueueError
11
- from ..retry import retry
12
10
  from ..json_safe import json_safe
11
+ from ..retry import retry
13
12
 
14
13
 
15
14
  class SQSAdapter(QueueAdapter):
@@ -1,16 +1,17 @@
1
1
  # src/polydb/adapters/VercelKVAdapter.py
2
2
 
3
- import os
4
3
  import json
5
- import redis
4
+ import os
6
5
  from typing import Any, Dict, List, Optional, Tuple
7
6
 
7
+ import redis
8
+
9
+ from ..base.NoSQLKVAdapter import NoSQLKVAdapter
10
+ from ..errors import DatabaseError, NoSQLError
8
11
  from ..json_safe import json_safe
9
- from ..errors import NoSQLError, DatabaseError
12
+ from ..models import PartitionConfig
10
13
  from ..retry import retry
11
14
  from ..types import JsonDict
12
- from ..models import PartitionConfig
13
- from ..base.NoSQLKVAdapter import NoSQLKVAdapter
14
15
 
15
16
 
16
17
  class VercelKVAdapter(NoSQLKVAdapter):