altcodepro-polydb-python 2.5.12__tar.gz → 2.5.18__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.
- {altcodepro_polydb_python-2.5.12/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.5.18}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/pyproject.toml +1 -1
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +2 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/__init__.py +1 -1
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/AzureTableStorageAdapter.py +13 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/PostgreSQLAdapter.py +44 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/schema.py +19 -1
- altcodepro_polydb_python-2.5.18/tests/test_azure_table_large_record_patch_roundtrip.py +118 -0
- altcodepro_polydb_python-2.5.18/tests/test_postgresql_deserialize_row.py +120 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_schema_ddl_injection.py +30 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/LICENSE +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/MANIFEST.in +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/README.md +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements-aws.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements-azure.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements-dev.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements-gcp.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements-generic.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/setup.cfg +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/setup.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/PolyDB.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/AWSSecretsManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/AzureKeyVaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/BlockchainFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/EFSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/FirestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/GCPFilestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/GCPSecretManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/KafkaQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/MongoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/RabbitMQAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/S3Adapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/SQSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/VaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/VercelFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/VercelKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/advanced_query.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/aio.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/AuditStorage.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/context.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/manager.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/models.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/NoSQLKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/ObjectStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/QueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/SecretsAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/SharedFilesAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/batch.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/cache.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/cloudDatabaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/databaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/errors.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/json_safe.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/models.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/monitoring.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/multitenancy.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/observability/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/observability/logging.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/overflow_gc.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/py.typed +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/query.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/registry.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/retry.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/security.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/services/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/services/compliance_service.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/services/security_service.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/types.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/utils.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/validation.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_advanced_query_injection.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_async_api.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_atomic_decrement.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_audit_chain_cutover.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_audit_hmac.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_aws.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_azure.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_azure_queue_receipt_handle.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_azure_table_empty_filter.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_azure_table_id_property_persisted.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_azure_table_id_return_value_sanitization_mismatch.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_azure_table_unpack_entity.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_blockchain.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_blockchain_overflow_guard.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_cloud_factory.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_field_encryption.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_gcp.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_kafka.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_like_pattern_escaping.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_mongodb.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_monitoring_health.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_multi_engine.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_multitenancy_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_nosql_kv_overflow_write_path.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_nosql_operator_injection.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_observability.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_overflow_gc.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_postgresql.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_queue_extend_delay_cancel.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_rabbitmq.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_redis_kv.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_secrets_aws.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_secrets_vault.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_session_vars.py +0 -0
- {altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/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.5.
|
|
3
|
+
Version: 2.5.18
|
|
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.
|
|
7
|
+
version = "2.5.18"
|
|
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.
|
|
3
|
+
Version: 2.5.18
|
|
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
|
|
@@ -94,6 +94,7 @@ tests/test_azure_queue_receipt_handle.py
|
|
|
94
94
|
tests/test_azure_table_empty_filter.py
|
|
95
95
|
tests/test_azure_table_id_property_persisted.py
|
|
96
96
|
tests/test_azure_table_id_return_value_sanitization_mismatch.py
|
|
97
|
+
tests/test_azure_table_large_record_patch_roundtrip.py
|
|
97
98
|
tests/test_azure_table_unpack_entity.py
|
|
98
99
|
tests/test_blockchain.py
|
|
99
100
|
tests/test_blockchain_overflow_guard.py
|
|
@@ -111,6 +112,7 @@ tests/test_nosql_operator_injection.py
|
|
|
111
112
|
tests/test_observability.py
|
|
112
113
|
tests/test_overflow_gc.py
|
|
113
114
|
tests/test_postgresql.py
|
|
115
|
+
tests/test_postgresql_deserialize_row.py
|
|
114
116
|
tests/test_queue_extend_delay_cancel.py
|
|
115
117
|
tests/test_rabbitmq.py
|
|
116
118
|
tests/test_redis_kv.py
|
|
@@ -4,7 +4,7 @@ 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.
|
|
7
|
+
__version__ = "2.5.18"
|
|
8
8
|
|
|
9
9
|
from .aio import AsyncDatabaseFactory, AsyncPolyDB
|
|
10
10
|
from .audit.context import AuditContext
|
|
@@ -125,6 +125,19 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
|
|
|
125
125
|
s = re.sub(r"[\\/#\?\x00-\x1f\x7f:+ ]", "_", s)
|
|
126
126
|
return s[:1024] if len(s) > 1024 else s
|
|
127
127
|
|
|
128
|
+
def _check_overflow(self, data: JsonDict): # type: ignore[override]
|
|
129
|
+
"""Azure overflows per PROPERTY inside `_put_raw`, never per record.
|
|
130
|
+
|
|
131
|
+
The base class' whole-record overflow replaces the record with a stub
|
|
132
|
+
of underscore keys (`_overflow`, `_blob_key`, ...), but `_put_raw`
|
|
133
|
+
drops every key starting with "_" when it builds the entity -- so the
|
|
134
|
+
stub's pointer was never stored and the real fields of the write were
|
|
135
|
+
silently lost (only an orphaned blob remained). Returning the data
|
|
136
|
+
untouched lets `_put_raw` spill each >30KB property on its own, which
|
|
137
|
+
`_get_raw`/`_query_raw` already rehydrate.
|
|
138
|
+
"""
|
|
139
|
+
return data, None
|
|
140
|
+
|
|
128
141
|
def _sanitize_prop_name(self, name: Any) -> str:
|
|
129
142
|
s = str(name)
|
|
130
143
|
s = re.sub(r"[^A-Za-z0-9_]", "_", s)
|
|
@@ -365,6 +365,50 @@ class PostgreSQLAdapter:
|
|
|
365
365
|
return [self._serialize_param(p) for p in params]
|
|
366
366
|
|
|
367
367
|
def _deserialize_row(self, row: JsonDict) -> JsonDict:
|
|
368
|
+
"""Best-effort convenience decode: any string column value that
|
|
369
|
+
LOOKS like JSON (starts/ends with `{}`/`[]`) is `json.loads`'d,
|
|
370
|
+
regardless of the column's own declared type. This is a real,
|
|
371
|
+
deliberate, LOAD-BEARING convenience a real caller depends on --
|
|
372
|
+
e.g. universal-interprter's `observability.py`'s `Observability.
|
|
373
|
+
query()` writes a `logs.emit` payload as `json.dumps(...)` into a
|
|
374
|
+
plain TEXT column (`payload`, never JSONB -- see that module's
|
|
375
|
+
own comment) and its own docstring explicitly promises "logs.
|
|
376
|
+
query's own `payload` field gets a real dict back"; removing this
|
|
377
|
+
heuristic (briefly tried, then reverted -- see this repo's own
|
|
378
|
+
2.5.16/2.5.17 CLAUDE.md history) silently broke that real,
|
|
379
|
+
already-shipped contract. `query_log.py`'s own `fields` column is
|
|
380
|
+
the identical shape, just defended a second way: it independently
|
|
381
|
+
`json.loads`'s its own value with an `isinstance(..., str)` guard
|
|
382
|
+
rather than relying on this method at all -- proof this repo has
|
|
383
|
+
real callers on both sides (some lean on this adapter-level
|
|
384
|
+
decode, some defend for themselves).
|
|
385
|
+
|
|
386
|
+
**The real, honest trade-off, unavoidable at this layer**: a
|
|
387
|
+
genuinely non-JSON TEXT/VARCHAR string whose own real content
|
|
388
|
+
merely LOOKS JSON-shaped (e.g. a prompt template's own `content`
|
|
389
|
+
column holding a literal JSON-encoded email template -- see
|
|
390
|
+
universal-interprter's `prompt_template_store.py`) gets coerced
|
|
391
|
+
from `str` to `dict`/`list` here too, since this method has no
|
|
392
|
+
way to distinguish "real app data serialized as JSON text" from
|
|
393
|
+
"a legitimately JSON-shaped string that must stay a string" --
|
|
394
|
+
both are simply "a string that starts with `{` and ends with
|
|
395
|
+
`}`." This adapter deliberately does NOT try to solve that
|
|
396
|
+
ambiguity generically (declaring the column JSONB instead sidesteps
|
|
397
|
+
it entirely -- psycopg2 registers global JSON/JSONB typecasters
|
|
398
|
+
for OIDs 114/3802 automatically at import time, so a genuine
|
|
399
|
+
`json`/`jsonb` column never even reaches this heuristic, `isinstance
|
|
400
|
+
(v, str)` already `False` by the time this method sees it); a
|
|
401
|
+
caller that must keep a TEXT column's string content literal
|
|
402
|
+
despite it being JSON-shaped owns that coercion at ITS OWN layer
|
|
403
|
+
instead (see `prompt_template_store.py`'s own `_coerce_content_to_str`
|
|
404
|
+
for the concrete pattern: re-`json.dumps()` a `content` value that
|
|
405
|
+
came back non-`str`, restoring the real string every caller of
|
|
406
|
+
that store is promised). This adapter stays a "dumb storage
|
|
407
|
+
layer" in the sense that it never MODELS what a column's real
|
|
408
|
+
semantic type should be -- it does still apply this one generic,
|
|
409
|
+
best-effort convenience decode uniformly, exactly as it always
|
|
410
|
+
has.
|
|
411
|
+
"""
|
|
368
412
|
for k, v in list(row.items()):
|
|
369
413
|
if isinstance(v, str):
|
|
370
414
|
s = v.strip()
|
|
@@ -61,6 +61,17 @@ class Index:
|
|
|
61
61
|
name: str
|
|
62
62
|
columns: List[str]
|
|
63
63
|
unique: bool = False
|
|
64
|
+
# Postgres index access method -- "btree" (the default, and the only
|
|
65
|
+
# one Postgres actually permits combined with UNIQUE) plus the real
|
|
66
|
+
# non-default methods a caller may need for a specific column shape:
|
|
67
|
+
# "gin"/"gist" (full-text search, JSONB containment, array overlap),
|
|
68
|
+
# "hash" (equality-only, smaller than btree for that one case), "brin"
|
|
69
|
+
# (large, naturally-ordered, append-mostly columns -- cheap to
|
|
70
|
+
# maintain relative to btree at real scale). Never validated against
|
|
71
|
+
# Postgres's own real per-type support here -- that's a live DDL
|
|
72
|
+
# concern the caller's own database will enforce; this dataclass only
|
|
73
|
+
# carries the caller's choice through to the generated statement.
|
|
74
|
+
using: str = "btree"
|
|
64
75
|
|
|
65
76
|
|
|
66
77
|
class SchemaBuilder:
|
|
@@ -128,10 +139,17 @@ class SchemaBuilder:
|
|
|
128
139
|
|
|
129
140
|
for idx in self.indexes:
|
|
130
141
|
unique = "UNIQUE " if idx.unique else ""
|
|
142
|
+
# "btree" omitted outright rather than spelled out as
|
|
143
|
+
# "USING btree" -- it's Postgres's own implicit default, and
|
|
144
|
+
# every index this codebase generated before `using` existed
|
|
145
|
+
# rendered without a USING clause at all; emitting it only for
|
|
146
|
+
# a non-default method keeps every pre-existing caller's own
|
|
147
|
+
# generated SQL text byte-for-byte unchanged.
|
|
148
|
+
using = f"USING {idx.using} " if idx.using != "btree" else ""
|
|
131
149
|
cols = ", ".join(validate_column_name(c) for c in idx.columns)
|
|
132
150
|
sql = (
|
|
133
151
|
f"CREATE {unique}INDEX IF NOT EXISTS {validate_table_name(idx.name)} "
|
|
134
|
-
f"ON {table_name}({cols});"
|
|
152
|
+
f"ON {table_name}{' ' if using else ''}{using}({cols});"
|
|
135
153
|
)
|
|
136
154
|
statements.append(sql)
|
|
137
155
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Unit tests (no Azurite needed) for a real, reproduced data-loss bug.
|
|
2
|
+
|
|
3
|
+
`NoSQLKVAdapter.put()/patch()` run `_check_overflow()` on the WHOLE record
|
|
4
|
+
before calling `_put_raw()`. `AzureTableStorageAdapter` sets `max_size` to
|
|
5
|
+
60KB (it has its own per-PROPERTY overflow for strings > 30KB inside
|
|
6
|
+
`_put_raw`), so any record above 60KB was replaced by a whole-record stub
|
|
7
|
+
`{_overflow, _blob_key, _size, _checksum}`. `_put_raw` then skips every key
|
|
8
|
+
starting with "_" when it builds the entity, so the stub's pointer was never
|
|
9
|
+
stored and the update's real fields (content_url, version, ...) were never
|
|
10
|
+
written -- a silent drop that left only an orphaned blob. Seen live: a
|
|
11
|
+
~41KB generated document plus its prompt context pushed an `artifacts` row
|
|
12
|
+
over 60KB; `core.db.update` reported success but the re-read row had none
|
|
13
|
+
of the fields.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import threading
|
|
17
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
|
|
20
|
+
pytest.importorskip("azure.data.tables")
|
|
21
|
+
|
|
22
|
+
from polydb.adapters.AzureTableStorageAdapter import AzureTableStorageAdapter # noqa: E402
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _Model:
|
|
26
|
+
__name__ = "artifacts"
|
|
27
|
+
__qualname__ = "artifacts"
|
|
28
|
+
__polydb__ = {"pk_field": "project_slug", "rk_field": "artifact_id"}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class _FakeTableClient:
|
|
32
|
+
def __init__(self):
|
|
33
|
+
self.store = {}
|
|
34
|
+
|
|
35
|
+
def upsert_entity(self, entity, **kw):
|
|
36
|
+
key = (entity["PartitionKey"], entity["RowKey"])
|
|
37
|
+
merged = dict(self.store.get(key, {}))
|
|
38
|
+
merged.update(entity) # azure MERGE semantics
|
|
39
|
+
self.store[key] = merged
|
|
40
|
+
|
|
41
|
+
def get_entity(self, pk, rk):
|
|
42
|
+
return dict(self.store[(pk, rk)])
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _adapter():
|
|
46
|
+
fake = _FakeTableClient()
|
|
47
|
+
blobs = {}
|
|
48
|
+
adp = object.__new__(AzureTableStorageAdapter)
|
|
49
|
+
adp.max_size = AzureTableStorageAdapter.AZURE_TABLE_MAX_SIZE
|
|
50
|
+
adp.partition_config = None
|
|
51
|
+
adp._lock = threading.Lock()
|
|
52
|
+
|
|
53
|
+
class _ObjStore: # what the base class' whole-record overflow writes to
|
|
54
|
+
def put(self, key, data):
|
|
55
|
+
blobs[key] = data
|
|
56
|
+
|
|
57
|
+
def get(self, key):
|
|
58
|
+
return blobs[key]
|
|
59
|
+
|
|
60
|
+
adp.object_storage = _ObjStore()
|
|
61
|
+
adp._blob_service = None
|
|
62
|
+
adp._get_table_client = lambda model: fake
|
|
63
|
+
adp._blob_upload = lambda key, data: blobs.__setitem__(key, data)
|
|
64
|
+
adp._blob_download = lambda key: blobs[key]
|
|
65
|
+
return adp, fake, blobs
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _row(**extra):
|
|
69
|
+
base = {"project_slug": "p-1", "artifact_id": "a-1", "status": "generating", "version": 0}
|
|
70
|
+
base.update(extra)
|
|
71
|
+
return base
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_patch_of_a_record_over_60kb_keeps_every_field():
|
|
75
|
+
adp, fake, blobs = _adapter()
|
|
76
|
+
adp.put(_Model, _row())
|
|
77
|
+
|
|
78
|
+
big = "x" * (45 * 1024)
|
|
79
|
+
adp.patch(
|
|
80
|
+
_Model,
|
|
81
|
+
{"pk": "p-1", "rk": "a-1"},
|
|
82
|
+
{
|
|
83
|
+
"content": big,
|
|
84
|
+
"system_prompt": "y" * (40 * 1024),
|
|
85
|
+
"content_url": "https://example/blob/1",
|
|
86
|
+
"content_blob_key": "blob-1",
|
|
87
|
+
"version": 1,
|
|
88
|
+
"preview_text": "# Title...",
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
row = adp._get_raw(_Model, "p-1", "a-1")
|
|
93
|
+
assert row["content"] == big
|
|
94
|
+
assert row["content_url"] == "https://example/blob/1"
|
|
95
|
+
assert row["content_blob_key"] == "blob-1"
|
|
96
|
+
assert row["version"] == 1
|
|
97
|
+
assert row["preview_text"] == "# Title..."
|
|
98
|
+
assert row["status"] == "generating"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_later_small_patch_does_not_lose_the_large_fields():
|
|
102
|
+
adp, fake, blobs = _adapter()
|
|
103
|
+
adp.put(_Model, _row())
|
|
104
|
+
big = "z" * (50 * 1024)
|
|
105
|
+
adp.patch(_Model, {"pk": "p-1", "rk": "a-1"}, {"content": big, "system_prompt": "q" * 50000})
|
|
106
|
+
adp.patch(_Model, {"pk": "p-1", "rk": "a-1"}, {"status": "validating"})
|
|
107
|
+
|
|
108
|
+
row = adp._get_raw(_Model, "p-1", "a-1")
|
|
109
|
+
assert row["status"] == "validating"
|
|
110
|
+
assert row["content"] == big
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_no_whole_record_stub_is_ever_written_for_azure():
|
|
114
|
+
adp, fake, blobs = _adapter()
|
|
115
|
+
adp.put(_Model, _row(content="w" * (70 * 1024)))
|
|
116
|
+
stored = fake.store[("p-1", "a-1")]
|
|
117
|
+
assert "_overflow" not in stored and not any(k.startswith("overflow/") for k in blobs)
|
|
118
|
+
assert stored["status"] == "generating"
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""PostgreSQLAdapter._deserialize_row's best-effort JSON-shaped-string
|
|
2
|
+
decode -- real, load-bearing behavior a real caller depends on, plus the
|
|
3
|
+
honest trade-off it can't avoid.
|
|
4
|
+
|
|
5
|
+
History: this heuristic (`json.loads()` any string column value that
|
|
6
|
+
starts/ends with `{}`/`[]`, regardless of the column's own declared
|
|
7
|
+
type) was briefly REMOVED in 2.5.16 after a real, reproduced bug --
|
|
8
|
+
universal-interprter's `prompt_template_store.py` stores an email
|
|
9
|
+
template's `content` as a plain TEXT column holding a JSON-encoded
|
|
10
|
+
string, and reading it back silently coerced it from `str` to `dict`,
|
|
11
|
+
crashing `prompt.render` -> `text.template`'s `template.replace(...)`
|
|
12
|
+
with `'dict' object has no attribute 'replace'`. That removal was itself
|
|
13
|
+
a real regression, reverted in 2.5.17: universal-interprter's own
|
|
14
|
+
`observability.py` (`Observability.query()`) writes a `logs.emit`
|
|
15
|
+
payload as `json.dumps(...)` into a plain TEXT column (`payload`, never
|
|
16
|
+
JSONB) and its own docstring explicitly promises "logs.query's own
|
|
17
|
+
`payload` field gets a real dict back" -- a real, already-shipped
|
|
18
|
+
contract this heuristic is the only thing that ever fulfilled, since
|
|
19
|
+
that read path is a raw `sql_adapter.execute()` call with no explicit
|
|
20
|
+
parsing of its own (unlike `query_log.py`'s own `fields` column, the
|
|
21
|
+
identical shape, which defends itself with an `isinstance(..., str)`
|
|
22
|
+
guard + its own `json.loads()` rather than relying on this method).
|
|
23
|
+
|
|
24
|
+
The real, honest trade-off (unavoidable at this layer, see
|
|
25
|
+
_deserialize_row's own docstring): a TEXT column can never be told apart
|
|
26
|
+
from a JSONB one purely by string-sniffing its OWN value's shape, so a
|
|
27
|
+
caller that must keep a TEXT column's real string content literal
|
|
28
|
+
despite it looking JSON-shaped (like `prompt_template_store.py`'s
|
|
29
|
+
`content`) owns that coercion at ITS OWN layer -- see that module's own
|
|
30
|
+
`_coerce_content_to_str` in universal-interprter for the concrete
|
|
31
|
+
pattern. No live Postgres connection is needed for any of this --
|
|
32
|
+
`_deserialize_row` is a pure dict-in/dict-out method.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
from __future__ import annotations
|
|
36
|
+
|
|
37
|
+
from polydb.adapters.PostgreSQLAdapter import PostgreSQLAdapter
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _adapter() -> PostgreSQLAdapter:
|
|
41
|
+
# __init__ eagerly opens a real connection pool (no lazy-connect mode
|
|
42
|
+
# exists) -- _deserialize_row touches no instance state at all, so a
|
|
43
|
+
# bare, uninitialized instance is enough to exercise it without a
|
|
44
|
+
# live Postgres.
|
|
45
|
+
return object.__new__(PostgreSQLAdapter)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TestDeserializeRowDecodesJsonShapedStrings:
|
|
49
|
+
def test_a_json_object_shaped_string_is_parsed_into_a_dict(self):
|
|
50
|
+
# The real, load-bearing case: a caller (e.g. observability.py's
|
|
51
|
+
# own `payload` column) wrote `json.dumps(...)` into a plain TEXT
|
|
52
|
+
# column and expects a real dict back on read.
|
|
53
|
+
adapter = _adapter()
|
|
54
|
+
row = {"id": "1", "payload": '{"event": "otp_sent", "channel": "email"}'}
|
|
55
|
+
|
|
56
|
+
result = adapter._deserialize_row(dict(row))
|
|
57
|
+
|
|
58
|
+
assert result["payload"] == {"event": "otp_sent", "channel": "email"}
|
|
59
|
+
|
|
60
|
+
def test_a_json_array_shaped_string_is_parsed_into_a_list(self):
|
|
61
|
+
adapter = _adapter()
|
|
62
|
+
row = {"id": "1", "fields": '["email", "status"]'}
|
|
63
|
+
|
|
64
|
+
result = adapter._deserialize_row(dict(row))
|
|
65
|
+
|
|
66
|
+
assert result["fields"] == ["email", "status"]
|
|
67
|
+
|
|
68
|
+
def test_a_string_that_merely_looks_json_shaped_but_isnt_valid_json_is_left_alone(self):
|
|
69
|
+
adapter = _adapter()
|
|
70
|
+
row = {"id": "1", "notes": "{not actually valid json}"}
|
|
71
|
+
|
|
72
|
+
result = adapter._deserialize_row(dict(row))
|
|
73
|
+
|
|
74
|
+
assert result["notes"] == row["notes"]
|
|
75
|
+
assert isinstance(result["notes"], str)
|
|
76
|
+
|
|
77
|
+
def test_an_ordinary_scalar_string_is_untouched(self):
|
|
78
|
+
adapter = _adapter()
|
|
79
|
+
row = {"id": "1", "name": "plain text, not json at all"}
|
|
80
|
+
|
|
81
|
+
result = adapter._deserialize_row(dict(row))
|
|
82
|
+
|
|
83
|
+
assert result == row
|
|
84
|
+
|
|
85
|
+
def test_a_real_dict_value_already_parsed_by_the_driver_passes_through_unchanged(self):
|
|
86
|
+
# This is what a genuine json/jsonb column already looks like by
|
|
87
|
+
# the time _deserialize_row runs -- psycopg2's own global
|
|
88
|
+
# typecasters (OIDs 114/3802) already turned it into a native
|
|
89
|
+
# dict, so there is nothing left for this method to do.
|
|
90
|
+
adapter = _adapter()
|
|
91
|
+
row = {"id": "1", "metadata": {"subject": "hi"}}
|
|
92
|
+
|
|
93
|
+
result = adapter._deserialize_row(dict(row))
|
|
94
|
+
|
|
95
|
+
assert result == row
|
|
96
|
+
assert isinstance(result["metadata"], dict)
|
|
97
|
+
|
|
98
|
+
def test_none_and_non_string_values_are_left_alone(self):
|
|
99
|
+
adapter = _adapter()
|
|
100
|
+
row = {"id": "1", "deleted_at": None, "count": 3, "active": True}
|
|
101
|
+
|
|
102
|
+
result = adapter._deserialize_row(dict(row))
|
|
103
|
+
|
|
104
|
+
assert result == row
|
|
105
|
+
|
|
106
|
+
def test_the_honest_trade_off_a_json_shaped_string_that_is_meant_to_stay_literal_text_still_gets_coerced(
|
|
107
|
+
self,
|
|
108
|
+
):
|
|
109
|
+
# The real cost this heuristic imposes, documented rather than
|
|
110
|
+
# hidden: a caller owning a TEXT column whose real content
|
|
111
|
+
# happens to be JSON-shaped (e.g. prompt_template_store.py's own
|
|
112
|
+
# `content`) must defend against this itself -- this adapter has
|
|
113
|
+
# no way to know that a given TEXT value should stay a literal
|
|
114
|
+
# string instead of being decoded.
|
|
115
|
+
adapter = _adapter()
|
|
116
|
+
row = {"id": "1", "content": '{"subject": "hi", "html": "<p>{{code}}</p>"}'}
|
|
117
|
+
|
|
118
|
+
result = adapter._deserialize_row(dict(row))
|
|
119
|
+
|
|
120
|
+
assert isinstance(result["content"], dict) # not the literal string it was written as
|
|
@@ -140,3 +140,33 @@ class TestLegitimateSchemasStillBuild:
|
|
|
140
140
|
assert builder.to_create_indexes("users") == [
|
|
141
141
|
"CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users(email, id);"
|
|
142
142
|
]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class TestIndexUsingClause:
|
|
146
|
+
"""Index.using (default "btree") -- added to let a caller pick a
|
|
147
|
+
non-default Postgres index access method (gin/gist/hash/brin) for a
|
|
148
|
+
specific column shape, without touching the default btree case's own
|
|
149
|
+
generated SQL text at all."""
|
|
150
|
+
|
|
151
|
+
def test_default_btree_renders_with_no_using_clause_at_all(self):
|
|
152
|
+
# Every Index constructed before `using` existed implicitly meant
|
|
153
|
+
# btree -- this proves that default still renders byte-for-byte
|
|
154
|
+
# identical to the pre-`using` SQL (no "USING btree" ever emitted).
|
|
155
|
+
builder = _builder().add_index(Index(name="idx_users_email", columns=["email"]))
|
|
156
|
+
assert builder.to_create_indexes("users") == [
|
|
157
|
+
"CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);"
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
def test_non_default_using_is_rendered_between_table_name_and_columns(self):
|
|
161
|
+
builder = _builder().add_index(Index(name="idx_users_tags", columns=["tags"], using="gin"))
|
|
162
|
+
assert builder.to_create_indexes("users") == [
|
|
163
|
+
"CREATE INDEX IF NOT EXISTS idx_users_tags ON users USING gin (tags);"
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
def test_unique_and_a_non_default_using_compose(self):
|
|
167
|
+
builder = _builder().add_index(
|
|
168
|
+
Index(name="idx_users_key", columns=["key"], unique=True, using="hash")
|
|
169
|
+
)
|
|
170
|
+
assert builder.to_create_indexes("users") == [
|
|
171
|
+
"CREATE UNIQUE INDEX IF NOT EXISTS idx_users_key ON users USING hash (key);"
|
|
172
|
+
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/requirements-generic.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/S3Adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/adapters/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/advanced_query.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/AuditStorage.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/context.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/manager.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/audit/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/QueueAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/base/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/databaseFactory.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/monitoring.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/multitenancy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/overflow_gc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/src/polydb/validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_atomic_decrement.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_audit_hmac.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_blockchain.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_cloud_factory.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_field_encryption.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_monitoring_health.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_multi_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_observability.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_overflow_gc.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_postgresql.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_secrets_aws.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_secrets_vault.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.12 → altcodepro_polydb_python-2.5.18}/tests/test_session_vars.py
RENAMED
|
File without changes
|
|
File without changes
|