altcodepro-polydb-python 2.5.18__tar.gz → 2.5.19__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.18/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.5.19}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/pyproject.toml +1 -1
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +1 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/PolyDB.py +4 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/AzureTableStorageAdapter.py +32 -2
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/PostgreSQLAdapter.py +5 -1
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/NoSQLKVAdapter.py +42 -2
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/databaseFactory.py +29 -6
- altcodepro_polydb_python-2.5.19/tests/test_read_projection.py +169 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/LICENSE +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/MANIFEST.in +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/README.md +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/requirements-aws.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/requirements-azure.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/requirements-dev.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/requirements-gcp.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/requirements-generic.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/requirements.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/setup.cfg +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/setup.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/AWSSecretsManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/AzureKeyVaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/BlockchainFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/EFSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/FirestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/GCPFilestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/GCPSecretManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/KafkaQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/MongoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/RabbitMQAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/S3Adapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/SQSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/VaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/VercelFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/VercelKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/advanced_query.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/aio.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/AuditStorage.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/context.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/manager.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/models.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/ObjectStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/QueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/SecretsAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/SharedFilesAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/batch.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/cache.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/cloudDatabaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/errors.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/json_safe.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/models.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/monitoring.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/multitenancy.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/observability/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/observability/logging.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/overflow_gc.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/py.typed +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/query.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/registry.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/retry.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/schema.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/security.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/services/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/services/compliance_service.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/services/security_service.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/types.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/utils.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/validation.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_advanced_query_injection.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_async_api.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_atomic_decrement.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_audit_chain_cutover.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_audit_hmac.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_aws.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure_queue_receipt_handle.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure_table_empty_filter.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure_table_id_property_persisted.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure_table_id_return_value_sanitization_mismatch.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure_table_large_record_patch_roundtrip.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_azure_table_unpack_entity.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_blockchain.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_blockchain_overflow_guard.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_cloud_factory.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_field_encryption.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_gcp.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_kafka.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_like_pattern_escaping.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_mongodb.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_monitoring_health.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_multi_engine.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_multitenancy_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_nosql_kv_overflow_write_path.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_nosql_operator_injection.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_observability.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_overflow_gc.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_postgresql.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_postgresql_deserialize_row.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_queue_extend_delay_cancel.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_rabbitmq.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_redis_kv.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_schema_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_secrets_aws.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_secrets_vault.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_session_vars.py +0 -0
- {altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/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.19
|
|
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.19"
|
|
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.19
|
|
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
|
|
@@ -115,6 +115,7 @@ tests/test_postgresql.py
|
|
|
115
115
|
tests/test_postgresql_deserialize_row.py
|
|
116
116
|
tests/test_queue_extend_delay_cancel.py
|
|
117
117
|
tests/test_rabbitmq.py
|
|
118
|
+
tests/test_read_projection.py
|
|
118
119
|
tests/test_redis_kv.py
|
|
119
120
|
tests/test_schema_ddl_injection.py
|
|
120
121
|
tests/test_secrets_aws.py
|
|
@@ -158,6 +158,8 @@ class PolyDB:
|
|
|
158
158
|
cache_ttl: Optional[int] = None,
|
|
159
159
|
include_deleted: bool = False,
|
|
160
160
|
engine_override: Optional[EngineOverride] = None,
|
|
161
|
+
fields: Optional[List[str]] = None,
|
|
162
|
+
omit: Optional[List[str]] = None,
|
|
161
163
|
) -> List[JsonDict]:
|
|
162
164
|
return self.db.read(
|
|
163
165
|
model,
|
|
@@ -168,6 +170,8 @@ class PolyDB:
|
|
|
168
170
|
cache_ttl=cache_ttl,
|
|
169
171
|
include_deleted=include_deleted,
|
|
170
172
|
engine_override=engine_override,
|
|
173
|
+
fields=fields,
|
|
174
|
+
omit=omit,
|
|
171
175
|
)
|
|
172
176
|
|
|
173
177
|
def read_one(
|
|
@@ -633,9 +633,35 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
|
|
|
633
633
|
return None
|
|
634
634
|
raise NoSQLError(f"Azure Table get failed: {str(e)}")
|
|
635
635
|
|
|
636
|
+
# `fields` / `omit` are sent to Azure as `$select`, so unrequested properties never leave the service.
|
|
637
|
+
SUPPORTS_SELECT_PUSHDOWN = True
|
|
638
|
+
|
|
639
|
+
def _select_properties(self, select: Optional[List[str]]) -> Optional[List[str]]:
|
|
640
|
+
"""The Azure property names to `$select` for the requested field names -- the requested ones, plus what `_unpack_entity`
|
|
641
|
+
needs to rebuild a row (the keys, the model tag, and the sanitized-name map). A per-property blob overflow is stored in
|
|
642
|
+
the property itself, so selecting the property is enough for `_restore_overflow_properties`. None = no pushdown: if any
|
|
643
|
+
requested name is rewritten by `_sanitize_prop_name` (so its stored name could carry a collision suffix), the whole row is
|
|
644
|
+
fetched and trimmed afterwards instead of risking a silently missing column."""
|
|
645
|
+
if not select:
|
|
646
|
+
return None
|
|
647
|
+
props: List[str] = []
|
|
648
|
+
for name in select:
|
|
649
|
+
safe = self._sanitize_prop_name(name)
|
|
650
|
+
if safe != str(name):
|
|
651
|
+
return None
|
|
652
|
+
props.append(safe)
|
|
653
|
+
for needed in ("PartitionKey", "RowKey", _MODEL_FIELD, "__keymap__"):
|
|
654
|
+
if needed not in props:
|
|
655
|
+
props.append(needed)
|
|
656
|
+
return props
|
|
657
|
+
|
|
636
658
|
@retry(max_attempts=3, delay=1.0, exceptions=(NoSQLError,))
|
|
637
659
|
def _query_raw(
|
|
638
|
-
self,
|
|
660
|
+
self,
|
|
661
|
+
model: type,
|
|
662
|
+
filters: Dict[str, Any],
|
|
663
|
+
limit: Optional[int],
|
|
664
|
+
select: Optional[List[str]] = None,
|
|
639
665
|
) -> List[JsonDict]:
|
|
640
666
|
try:
|
|
641
667
|
table_client = self._get_table_client(model)
|
|
@@ -685,7 +711,11 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
|
|
|
685
711
|
else:
|
|
686
712
|
query_filter = " and ".join(parts)
|
|
687
713
|
|
|
688
|
-
|
|
714
|
+
props = self._select_properties(select)
|
|
715
|
+
if props is None:
|
|
716
|
+
entities = table_client.query_entities(query_filter=query_filter)
|
|
717
|
+
else:
|
|
718
|
+
entities = table_client.query_entities(query_filter=query_filter, select=props)
|
|
689
719
|
|
|
690
720
|
results: List[JsonDict] = []
|
|
691
721
|
count = 0
|
|
@@ -487,8 +487,12 @@ class PostgreSQLAdapter:
|
|
|
487
487
|
tx: Optional[Any] = None,
|
|
488
488
|
*,
|
|
489
489
|
session_vars: Optional[Dict[str, str]] = None,
|
|
490
|
+
fields: Optional[List[str]] = None,
|
|
490
491
|
) -> List[JsonDict]:
|
|
491
492
|
table = validate_table_name(table)
|
|
493
|
+
if fields:
|
|
494
|
+
for f in fields:
|
|
495
|
+
validate_column_name(f)
|
|
492
496
|
conn = tx
|
|
493
497
|
own_conn = False
|
|
494
498
|
if not conn:
|
|
@@ -498,7 +502,7 @@ class PostgreSQLAdapter:
|
|
|
498
502
|
try:
|
|
499
503
|
self._apply_session_vars(conn, session_vars)
|
|
500
504
|
cursor = conn.cursor()
|
|
501
|
-
sql = f"SELECT * FROM {table}"
|
|
505
|
+
sql = f"SELECT {', '.join(fields)} FROM {table}" if fields else f"SELECT * FROM {table}"
|
|
502
506
|
params: List[Any] = []
|
|
503
507
|
|
|
504
508
|
if query:
|
|
@@ -17,9 +17,43 @@ if TYPE_CHECKING:
|
|
|
17
17
|
from ..models import PartitionConfig
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def project_rows(
|
|
21
|
+
rows: List[JsonDict], fields: Optional[List[str]] = None, omit: Optional[List[str]] = None
|
|
22
|
+
) -> List[JsonDict]:
|
|
23
|
+
"""The exact `fields` / `omit` semantics every NoSQL read shares: `fields` keeps only those keys, `omit` drops those keys
|
|
24
|
+
(`fields` wins if both are given). Applied by the base `query()` AFTER overflow rehydration, so it is correct for every
|
|
25
|
+
adapter whether or not it also pushes the projection down to the store."""
|
|
26
|
+
if fields:
|
|
27
|
+
keep = set(fields)
|
|
28
|
+
return [{k: v for k, v in r.items() if k in keep} for r in rows]
|
|
29
|
+
if omit:
|
|
30
|
+
drop = set(omit)
|
|
31
|
+
return [{k: v for k, v in r.items() if k not in drop} for r in rows]
|
|
32
|
+
return rows
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def select_columns(
|
|
36
|
+
fields: Optional[List[str]], omit: Optional[List[str]], columns: Optional[List[str]]
|
|
37
|
+
) -> Optional[List[str]]:
|
|
38
|
+
"""The column list a store can be asked for: `fields` as given, or -- for `omit` -- the model's known `columns` minus the
|
|
39
|
+
omitted ones. None means "no column list can be derived" (no projection, or `omit` on a model whose columns are unknown):
|
|
40
|
+
the read then fetches whole rows and `project_rows` trims them."""
|
|
41
|
+
if fields:
|
|
42
|
+
return list(fields)
|
|
43
|
+
if omit and columns:
|
|
44
|
+
drop = set(omit)
|
|
45
|
+
return [c for c in columns if c not in drop]
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
|
|
20
49
|
class NoSQLKVAdapter:
|
|
21
50
|
"""Base with auto-overflow and LINQ support"""
|
|
22
51
|
|
|
52
|
+
# An adapter sets this True when its `_query_raw` accepts `select=[property names]` and really sends it to the store (Azure
|
|
53
|
+
# Table's `$select`). False (the default) means `fields`/`omit` are applied after the rows come back -- same result, no
|
|
54
|
+
# network saving. Opt in per adapter only once the adapter's own rehydration is proven to survive a narrowed row.
|
|
55
|
+
SUPPORTS_SELECT_PUSHDOWN = False
|
|
56
|
+
|
|
23
57
|
def __init__(
|
|
24
58
|
self,
|
|
25
59
|
partition_config: Optional[PartitionConfig] = None,
|
|
@@ -242,9 +276,15 @@ class NoSQLKVAdapter:
|
|
|
242
276
|
limit: Optional[int] = None,
|
|
243
277
|
no_cache: bool = False,
|
|
244
278
|
cache_ttl: Optional[int] = None,
|
|
279
|
+
fields: Optional[List[str]] = None,
|
|
280
|
+
omit: Optional[List[str]] = None,
|
|
245
281
|
) -> List[JsonDict]:
|
|
246
|
-
|
|
247
|
-
|
|
282
|
+
select = select_columns(fields, omit, getattr(model, "__polydb__", {}).get("columns"))
|
|
283
|
+
if select is not None and self.SUPPORTS_SELECT_PUSHDOWN:
|
|
284
|
+
results = self._query_raw(model, query or {}, limit, select=select)
|
|
285
|
+
else:
|
|
286
|
+
results = self._query_raw(model, query or {}, limit)
|
|
287
|
+
return project_rows([self._retrieve_overflow(r) for r in results], fields, omit)
|
|
248
288
|
|
|
249
289
|
def query_page(
|
|
250
290
|
self, model: type, query: Lookup, page_size: int, continuation_token: Optional[str] = None
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/databaseFactory.py
RENAMED
|
@@ -24,7 +24,7 @@ from tenacity import retry, stop_after_attempt, wait_exponential
|
|
|
24
24
|
from .adapters.PostgreSQLAdapter import PostgreSQLAdapter
|
|
25
25
|
from .audit.context import AuditContext
|
|
26
26
|
from .audit.manager import AuditManager
|
|
27
|
-
from .base.NoSQLKVAdapter import NoSQLKVAdapter
|
|
27
|
+
from .base.NoSQLKVAdapter import NoSQLKVAdapter, project_rows, select_columns
|
|
28
28
|
from .batch import BatchOperations
|
|
29
29
|
from .cache import CacheWarmer, RedisCacheEngine
|
|
30
30
|
from .cloudDatabaseFactory import CloudDatabaseFactory
|
|
@@ -453,30 +453,53 @@ class DatabaseFactory:
|
|
|
453
453
|
include_deleted: bool = False,
|
|
454
454
|
engine_override: Optional[EngineOverride] = None,
|
|
455
455
|
session_vars: Optional[Dict[str, str]] = None,
|
|
456
|
+
fields: Optional[List[str]] = None,
|
|
457
|
+
omit: Optional[List[str]] = None,
|
|
456
458
|
) -> List[JsonDict]:
|
|
459
|
+
"""`fields` returns only those keys; `omit` returns every key except those (`fields` wins if both are given). SQL
|
|
460
|
+
names the columns in the SELECT; NoSQL adapters that can ($select on Azure Table) send the property list to the store,
|
|
461
|
+
the rest trim the rows after the read -- same result either way. `omit` needs the model's `__polydb__["columns"]` to
|
|
462
|
+
be turned into a column list for the store; without it the whole row is fetched and trimmed. A projected read never
|
|
463
|
+
goes through the external cache (its key does not include the projection)."""
|
|
457
464
|
name = _model_name(model)
|
|
458
465
|
meta = _extract_meta(model)
|
|
466
|
+
columns = (getattr(model, "__polydb__", None) or {}).get("columns") if isinstance(model, type) else None
|
|
467
|
+
projected = bool(fields or omit)
|
|
468
|
+
sql_columns = select_columns(fields, omit, columns)
|
|
459
469
|
|
|
460
470
|
if self._soft_delete and not include_deleted:
|
|
461
471
|
query = self._apply_soft_delete_filter(query)
|
|
462
472
|
|
|
463
473
|
adapters = self._adapters_for(model, meta, engine_override)
|
|
464
|
-
use_external_cache =
|
|
474
|
+
use_external_cache = (
|
|
475
|
+
self._enable_cache and self._cache and getattr(meta, "cache", False) and not projected
|
|
476
|
+
)
|
|
465
477
|
encrypted_fields = getattr(meta, "encrypted_fields", [])
|
|
466
478
|
|
|
467
479
|
def _op() -> List[JsonDict]:
|
|
468
480
|
if self._is_sql(meta, engine_override):
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
481
|
+
if sql_columns is not None:
|
|
482
|
+
raw = adapters.sql.select(
|
|
483
|
+
meta.table, query, limit=limit, offset=offset,
|
|
484
|
+
session_vars=session_vars, fields=sql_columns,
|
|
485
|
+
)
|
|
486
|
+
else:
|
|
487
|
+
raw = adapters.sql.select(
|
|
488
|
+
meta.table, query, limit=limit, offset=offset, session_vars=session_vars
|
|
489
|
+
)
|
|
490
|
+
raw = project_rows(raw, fields, omit)
|
|
472
491
|
else:
|
|
473
492
|
cls = (
|
|
474
493
|
model
|
|
475
494
|
if isinstance(model, type)
|
|
476
495
|
else type(name, (), {"__polydb__": meta.__dict__})
|
|
477
496
|
)
|
|
497
|
+
nosql_kwargs: Dict[str, Any] = {}
|
|
498
|
+
if projected:
|
|
499
|
+
nosql_kwargs = {"fields": fields, "omit": omit}
|
|
478
500
|
raw = adapters.nosql.query(
|
|
479
|
-
cls, query=query, limit=limit, no_cache=no_cache or bool(use_external_cache)
|
|
501
|
+
cls, query=query, limit=limit, no_cache=no_cache or bool(use_external_cache),
|
|
502
|
+
**nosql_kwargs,
|
|
480
503
|
)
|
|
481
504
|
if self.encryption and encrypted_fields:
|
|
482
505
|
raw = [self.encryption.decrypt_fields(r, encrypted_fields) for r in raw]
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""`fields` / `omit` on read: SQL names the columns, Azure Table sends `$select`, every other NoSQL adapter trims after the read.
|
|
2
|
+
|
|
3
|
+
Unit level (no Azurite / Postgres): fake table client, fake cursor.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from polydb.base.NoSQLKVAdapter import NoSQLKVAdapter, project_rows, select_columns
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ---------------- pure helpers -------------------------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
def test_project_rows_fields_omit_and_fields_wins():
|
|
14
|
+
rows = [{"id": "1", "a": 1, "b": 2, "big": "x" * 10}]
|
|
15
|
+
assert project_rows(rows, ["id", "a"], None) == [{"id": "1", "a": 1}]
|
|
16
|
+
assert project_rows(rows, None, ["big"]) == [{"id": "1", "a": 1, "b": 2}]
|
|
17
|
+
assert project_rows(rows, ["a"], ["a"]) == [{"a": 1}]
|
|
18
|
+
assert project_rows(rows, None, None) is rows
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_select_columns_from_fields_or_columns_minus_omit():
|
|
22
|
+
cols = ["id", "a", "b", "big"]
|
|
23
|
+
assert select_columns(["a"], None, cols) == ["a"]
|
|
24
|
+
assert select_columns(None, ["big"], cols) == ["id", "a", "b"]
|
|
25
|
+
assert select_columns(None, ["big"], None) is None # columns unknown: cannot derive a list, fetch whole rows
|
|
26
|
+
assert select_columns(None, None, cols) is None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ---------------- base adapter: pushdown flag ----------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
class _Adapter(NoSQLKVAdapter):
|
|
32
|
+
def __init__(self, pushdown):
|
|
33
|
+
super().__init__()
|
|
34
|
+
self.SUPPORTS_SELECT_PUSHDOWN = pushdown
|
|
35
|
+
self.calls = []
|
|
36
|
+
def _query_raw(self, model, filters, limit, select=None):
|
|
37
|
+
self.calls.append(select)
|
|
38
|
+
return [{"id": "1", "a": 1, "b": 2, "big": "zzz"}]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class _M:
|
|
42
|
+
__polydb__ = {"columns": ["id", "a", "b", "big"]}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_without_pushdown_rows_are_trimmed_after_the_read():
|
|
46
|
+
a = _Adapter(False)
|
|
47
|
+
assert a.query(_M, {"x": 1}, fields=["id", "a"]) == [{"id": "1", "a": 1}]
|
|
48
|
+
assert a.calls == [None] # the store was asked for whole rows
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_with_pushdown_the_select_list_reaches_the_store_and_result_is_still_exact():
|
|
52
|
+
a = _Adapter(True)
|
|
53
|
+
assert a.query(_M, {}, fields=["a"]) == [{"a": 1}]
|
|
54
|
+
assert a.query(_M, {}, omit=["big"]) == [{"id": "1", "a": 1, "b": 2}]
|
|
55
|
+
assert a.calls == [["a"], ["id", "a", "b"]]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_omit_on_a_model_without_known_columns_is_client_side_only():
|
|
59
|
+
class _Bare: pass
|
|
60
|
+
a = _Adapter(True)
|
|
61
|
+
assert a.query(_Bare, {}, omit=["big"]) == [{"id": "1", "a": 1, "b": 2}]
|
|
62
|
+
assert a.calls == [None]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_no_projection_keeps_the_old_call_shape():
|
|
66
|
+
a = _Adapter(True)
|
|
67
|
+
assert a.query(_M, {}) == [{"id": "1", "a": 1, "b": 2, "big": "zzz"}]
|
|
68
|
+
assert a.calls == [None]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# ---------------- Azure Table: $select -----------------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
azure = pytest.importorskip("azure.data.tables")
|
|
74
|
+
from polydb.adapters.AzureTableStorageAdapter import AzureTableStorageAdapter # noqa: E402
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class _Model:
|
|
78
|
+
__name__ = "Artifact"
|
|
79
|
+
__qualname__ = "Artifact"
|
|
80
|
+
__polydb__ = {"pk_field": "tenant_id", "rk_field": "id"}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class _Client:
|
|
84
|
+
def __init__(self, entities):
|
|
85
|
+
self.entities, self.kwargs = entities, []
|
|
86
|
+
def query_entities(self, query_filter=None, **kw):
|
|
87
|
+
self.kwargs.append((query_filter, kw)); return list(self.entities)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
ENT = {"PartitionKey": "t1", "RowKey": "r1", "__polydb_model__": "Artifact", "__keymap__": "{}", "id": "r1",
|
|
91
|
+
"name": "n", "status": "ok"}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _adp(client):
|
|
95
|
+
adp = object.__new__(AzureTableStorageAdapter)
|
|
96
|
+
adp._get_table_client = lambda model: client
|
|
97
|
+
return adp
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_azure_sends_select_with_the_keys_the_row_needs():
|
|
101
|
+
c = _Client([ENT])
|
|
102
|
+
rows = _adp(c).query(_Model, {"tenant_id": "t1"}, fields=["name", "status"])
|
|
103
|
+
(flt, kw), = c.kwargs
|
|
104
|
+
assert flt == "tenant_id eq 't1'"
|
|
105
|
+
assert set(kw["select"]) == {"name", "status", "PartitionKey", "RowKey", "__polydb_model__", "__keymap__"}
|
|
106
|
+
assert rows == [{"name": "n", "status": "ok"}] # id / tenant_id added by unpack are trimmed back out
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_azure_omit_becomes_select_of_the_remaining_known_columns():
|
|
110
|
+
class _M2(_Model):
|
|
111
|
+
__polydb__ = {"pk_field": "tenant_id", "rk_field": "id", "columns": ["id", "name", "status", "content"]}
|
|
112
|
+
c = _Client([ENT])
|
|
113
|
+
rows = _adp(c).query(_M2, {}, omit=["content"])
|
|
114
|
+
(_, kw), = c.kwargs
|
|
115
|
+
assert "content" not in kw["select"] and {"id", "name", "status"} <= set(kw["select"])
|
|
116
|
+
assert rows == [{"id": "r1", "name": "n", "status": "ok", "tenant_id": "t1"}] # omit drops only what was named
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_azure_no_projection_sends_no_select():
|
|
120
|
+
c = _Client([ENT])
|
|
121
|
+
_adp(c).query(_Model, {})
|
|
122
|
+
assert c.kwargs == [(None, {})]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_azure_falls_back_to_whole_rows_when_a_name_would_be_rewritten():
|
|
126
|
+
c = _Client([dict(ENT, f_1x="v")])
|
|
127
|
+
_adp(c).query(_Model, {}, fields=["1x"]) # "1x" is stored as "f_1x": cannot be selected by its own name
|
|
128
|
+
assert c.kwargs == [(None, {})]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# ---------------- Postgres: named columns --------------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
from polydb.adapters.PostgreSQLAdapter import PostgreSQLAdapter # noqa: E402
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class _Cur:
|
|
137
|
+
description = [("id",), ("status",)]
|
|
138
|
+
def fetchall(self): return [("1", "ok")]
|
|
139
|
+
def close(self): pass
|
|
140
|
+
class _Conn:
|
|
141
|
+
def cursor(self): return _Cur()
|
|
142
|
+
def commit(self): pass
|
|
143
|
+
def rollback(self): pass
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _pg(captured):
|
|
147
|
+
a = object.__new__(PostgreSQLAdapter)
|
|
148
|
+
a._get_connection = lambda: _Conn()
|
|
149
|
+
a._return_connection = lambda c: None
|
|
150
|
+
a._apply_session_vars = lambda c, v: None
|
|
151
|
+
a._timed_execute = lambda cur, sql, params, **k: captured.append((sql, params))
|
|
152
|
+
a._serialize_params = lambda p: p
|
|
153
|
+
a._deserialize_row = lambda r: r
|
|
154
|
+
return a
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_postgres_select_names_the_columns():
|
|
158
|
+
cap = []
|
|
159
|
+
rows = _pg(cap).select("orders", {"tenant_id": "t"}, limit=5, fields=["id", "status"])
|
|
160
|
+
assert cap[0][0].startswith("SELECT id, status FROM orders WHERE tenant_id = %s")
|
|
161
|
+
assert rows == [{"id": "1", "status": "ok"}]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def test_postgres_select_without_fields_is_unchanged_and_bad_names_are_refused():
|
|
165
|
+
cap = []
|
|
166
|
+
_pg(cap).select("orders", {})
|
|
167
|
+
assert cap[0][0] == "SELECT * FROM orders"
|
|
168
|
+
with pytest.raises(Exception):
|
|
169
|
+
_pg([]).select("orders", {}, fields=["id; DROP TABLE orders"])
|
|
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.18 → altcodepro_polydb_python-2.5.19}/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.18 → altcodepro_polydb_python-2.5.19}/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.18 → altcodepro_polydb_python-2.5.19}/src/polydb/adapters/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/advanced_query.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/AuditStorage.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/context.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/manager.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/audit/models.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/QueueAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/base/__init__.py
RENAMED
|
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.18 → altcodepro_polydb_python-2.5.19}/src/polydb/monitoring.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/multitenancy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/src/polydb/overflow_gc.py
RENAMED
|
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.18 → altcodepro_polydb_python-2.5.19}/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.18 → altcodepro_polydb_python-2.5.19}/src/polydb/validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_atomic_decrement.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/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
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_blockchain.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_cloud_factory.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/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.18 → altcodepro_polydb_python-2.5.19}/tests/test_monitoring_health.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_multi_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_observability.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_overflow_gc.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_postgresql.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.18 → altcodepro_polydb_python-2.5.19}/tests/test_secrets_aws.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_secrets_vault.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.18 → altcodepro_polydb_python-2.5.19}/tests/test_session_vars.py
RENAMED
|
File without changes
|
|
File without changes
|