altcodepro-polydb-python 2.5.8__tar.gz → 2.5.10__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.8/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.5.10}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/pyproject.toml +1 -1
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +2 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/__init__.py +1 -1
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureTableStorageAdapter.py +47 -1
- altcodepro_polydb_python-2.5.10/tests/test_azure_table_id_property_persisted.py +175 -0
- altcodepro_polydb_python-2.5.10/tests/test_azure_table_id_return_value_sanitization_mismatch.py +151 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/LICENSE +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/MANIFEST.in +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/README.md +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/requirements-aws.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/requirements-azure.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/requirements-dev.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/requirements-gcp.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/requirements-generic.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/requirements.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/setup.cfg +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/setup.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/PolyDB.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AWSSecretsManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureKeyVaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/EFSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/FirestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPFilestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPSecretManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/KafkaQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/MongoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/PostgreSQLAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/RabbitMQAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/S3Adapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/SQSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/advanced_query.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/AuditStorage.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/context.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/manager.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/models.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/NoSQLKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/ObjectStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/QueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/SecretsAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/SharedFilesAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/batch.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/cache.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/cloudDatabaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/databaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/decorators.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/errors.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/json_safe.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/models.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/monitoring.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/multitenancy.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/observability/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/observability/logging.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/py.typed +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/query.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/registry.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/retry.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/schema.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/security.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/services/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/services/compliance_service.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/services/security_service.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/types.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/utils.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/validation.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_advanced_query_injection.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_atomic_decrement.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_audit_chain_cutover.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_audit_hmac.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_aws.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_azure.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_azure_queue_receipt_handle.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_azure_table_empty_filter.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_azure_table_unpack_entity.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_blockchain.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_cloud_factory.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_field_encryption.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_gcp.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_kafka.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_like_pattern_escaping.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_mongodb.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_multi_engine.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_multitenancy_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_nosql_operator_injection.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_observability.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_postgresql.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_queue_extend_delay_cancel.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_rabbitmq.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_redis_kv.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_schema_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_aws.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_vault.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_session_vars.py +0 -0
- {altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/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.10
|
|
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.10"
|
|
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.10
|
|
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
|
|
@@ -90,6 +90,8 @@ tests/test_aws.py
|
|
|
90
90
|
tests/test_azure.py
|
|
91
91
|
tests/test_azure_queue_receipt_handle.py
|
|
92
92
|
tests/test_azure_table_empty_filter.py
|
|
93
|
+
tests/test_azure_table_id_property_persisted.py
|
|
94
|
+
tests/test_azure_table_id_return_value_sanitization_mismatch.py
|
|
93
95
|
tests/test_azure_table_unpack_entity.py
|
|
94
96
|
tests/test_blockchain.py
|
|
95
97
|
tests/test_cloud_factory.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.10"
|
|
8
8
|
|
|
9
9
|
from .cloudDatabaseFactory import CloudDatabaseFactory
|
|
10
10
|
from .databaseFactory import DatabaseFactory
|
|
@@ -493,6 +493,33 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
|
|
|
493
493
|
table_client = self._get_table_client(model)
|
|
494
494
|
safe_pk = self._sanitize_pk_rk(pk)
|
|
495
495
|
safe_rk = self._sanitize_pk_rk(rk)
|
|
496
|
+
# Persist "id" as a REAL, queryable property whenever the
|
|
497
|
+
# caller's own data didn't already supply one -- not just
|
|
498
|
+
# synthesized onto this call's own return value below
|
|
499
|
+
# (`restored["id"] = safe_rk`), which only ever helped the
|
|
500
|
+
# ONE caller holding that return value. _query_raw already
|
|
501
|
+
# does the equivalent synthesis on the READ side (`out["id"]
|
|
502
|
+
# = ent_dict["RowKey"]` when absent) for a query's own
|
|
503
|
+
# results, but that can't fix a *filtered* read: a later
|
|
504
|
+
# `read_one(model, {"id": X, ...})` -- the ordinary
|
|
505
|
+
# id-addressed lookup every `update()`/`patch()` call makes
|
|
506
|
+
# for its own "before" read -- builds a real OData `id eq
|
|
507
|
+
# 'X'` filter against whatever property is actually named
|
|
508
|
+
# "id" on the stored entity. When the original create's own
|
|
509
|
+
# data never included one (true for essentially any model
|
|
510
|
+
# whose caller doesn't explicitly generate an id, default
|
|
511
|
+
# pk_field/rk_field or a custom mapping alike), that property
|
|
512
|
+
# never existed, so the filter matched nothing -- `before`
|
|
513
|
+
# came back None, and DatabaseFactory.update()'s own pk/rk
|
|
514
|
+
# recovery (see this file's own 2.5.7 changelog entry for the
|
|
515
|
+
# closely related bug) had nothing to recover from, falling
|
|
516
|
+
# through to a literal `str(None) == "None"` PartitionKey.
|
|
517
|
+
# Reproduced directly before this fix, not assumed: a create
|
|
518
|
+
# with no "id" in its own payload, followed by
|
|
519
|
+
# read_one(model, {"id": <the id the create call itself
|
|
520
|
+
# returned>}), always returned None.
|
|
521
|
+
if "id" not in data:
|
|
522
|
+
data = {**data, "id": safe_rk}
|
|
496
523
|
entity = self._pack_entity(model, safe_pk, safe_rk, data)
|
|
497
524
|
MAX_PROPERTY_CHARS = 30 * 1024
|
|
498
525
|
|
|
@@ -539,7 +566,26 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
|
|
|
539
566
|
table_client.upsert_entity(reference_entity)
|
|
540
567
|
|
|
541
568
|
restored = self._unpack_entity(model, entity)
|
|
542
|
-
|
|
569
|
+
# Mirror the write-side condition above (line ~521): only
|
|
570
|
+
# synthesize "id" onto the return value when the caller's own
|
|
571
|
+
# data didn't already supply one. Unconditionally overwriting
|
|
572
|
+
# it with safe_rk here was a real, reproduced bug -- whenever
|
|
573
|
+
# the caller's own id needed RowKey sanitization (contains a
|
|
574
|
+
# character Azure forbids in a RowKey: ':', ' ', '#', '?',
|
|
575
|
+
# '/', '\'), the PERSISTED "id" property kept the caller's
|
|
576
|
+
# original, unsanitized value (data["id"], written untouched
|
|
577
|
+
# via reference_entity above) while this return value handed
|
|
578
|
+
# back the sanitized safe_rk instead -- two different strings
|
|
579
|
+
# for the same row. Any caller holding onto that return
|
|
580
|
+
# value's own "id" (e.g. building a follow-up
|
|
581
|
+
# read_one(model, {"id": ...}) call, or an id.map() over a
|
|
582
|
+
# create_many result) would then filter for a value that
|
|
583
|
+
# never matches any real stored "id" property, silently
|
|
584
|
+
# getting nothing back. Reproduced directly before this fix:
|
|
585
|
+
# data={"id": "a:b"} on a model with a rk_field whose value
|
|
586
|
+
# contains ":" persisted "id"="a:b" but returned "id"="a_b".
|
|
587
|
+
if "id" not in data:
|
|
588
|
+
restored["id"] = safe_rk
|
|
543
589
|
|
|
544
590
|
return restored
|
|
545
591
|
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Unit tests (no Azurite needed) for a real, reproduced bug: `_put_raw`
|
|
2
|
+
never persisted a real "id" property on the entity unless the caller's own
|
|
3
|
+
write payload already had one -- only synthesized it onto that one call's
|
|
4
|
+
own RETURN value (`restored["id"] = safe_rk`). A later id-addressed lookup
|
|
5
|
+
(`read_one(model, {"id": X, ...})`, the "before" read every
|
|
6
|
+
`DatabaseFactory.update()`/`patch()` call makes) builds a real OData
|
|
7
|
+
`id eq 'X'` filter against whatever property is actually named "id" on the
|
|
8
|
+
stored entity -- which, for any model whose caller doesn't explicitly set
|
|
9
|
+
"id" at create time (default pk_field/rk_field or a custom deterministic
|
|
10
|
+
mapping alike), never existed. `before` therefore always came back None,
|
|
11
|
+
cascading into `DatabaseFactory.update()`'s own pk/rk recovery logic
|
|
12
|
+
finding nothing to recover from and falling through to a literal
|
|
13
|
+
`str(None) == "None"` PartitionKey -- the same class of bug this file's own
|
|
14
|
+
2.5.7 changelog entry already documents for a related codepath.
|
|
15
|
+
|
|
16
|
+
Reproduces the bug on the OLD code shape directly (a create whose own
|
|
17
|
+
payload has no "id" never lands a real "id" property), then proves the fix
|
|
18
|
+
closes it (a create with no "id" DOES land a real, filterable "id"
|
|
19
|
+
property equal to the physical RowKey, and a create that ALREADY supplies
|
|
20
|
+
its own "id" is left completely untouched).
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import pytest
|
|
24
|
+
|
|
25
|
+
pytest.importorskip("azure.data.tables") # adapter needs the SDK to import
|
|
26
|
+
|
|
27
|
+
from polydb.adapters.AzureTableStorageAdapter import AzureTableStorageAdapter # noqa: E402
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _Model:
|
|
31
|
+
__name__ = "users"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _FakeTableClient:
|
|
35
|
+
"""A minimal, real filter-evaluating fake -- unlike
|
|
36
|
+
test_azure_table_empty_filter.py's own fake (which only needs to tell
|
|
37
|
+
a None filter apart from a non-None one), this one has to actually
|
|
38
|
+
match `_query_raw`'s real OData-shaped filter string against stored
|
|
39
|
+
entities, since that's the exact mechanism this bug lives in."""
|
|
40
|
+
|
|
41
|
+
def __init__(self):
|
|
42
|
+
self.store: dict[tuple, dict] = {}
|
|
43
|
+
|
|
44
|
+
def upsert_entity(self, entity, **kw):
|
|
45
|
+
self.store[(entity["PartitionKey"], entity["RowKey"])] = dict(entity)
|
|
46
|
+
|
|
47
|
+
def query_entities(self, query_filter=None, **kw):
|
|
48
|
+
if query_filter is None:
|
|
49
|
+
return list(self.store.values())
|
|
50
|
+
conditions = []
|
|
51
|
+
for part in query_filter.split(" and "):
|
|
52
|
+
prop, _, raw_val = part.partition(" eq ")
|
|
53
|
+
if raw_val.startswith("'") and raw_val.endswith("'"):
|
|
54
|
+
val = raw_val[1:-1].replace("''", "'")
|
|
55
|
+
elif raw_val == "null":
|
|
56
|
+
val = None
|
|
57
|
+
elif raw_val in ("true", "false"):
|
|
58
|
+
val = raw_val == "true"
|
|
59
|
+
else:
|
|
60
|
+
val = float(raw_val) if "." in raw_val else int(raw_val)
|
|
61
|
+
conditions.append((prop, val))
|
|
62
|
+
return [
|
|
63
|
+
e for e in self.store.values() if all(e.get(prop) == val for prop, val in conditions)
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _adapter(fake):
|
|
68
|
+
adp = object.__new__(AzureTableStorageAdapter) # bypass live-connection __init__
|
|
69
|
+
adp._get_table_client = lambda model: fake
|
|
70
|
+
adp._blob_service = None
|
|
71
|
+
adp.object_storage = None
|
|
72
|
+
return adp
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_a_create_with_no_id_in_its_own_payload_still_lands_a_real_filterable_id_property():
|
|
76
|
+
"""The actual bug: users.identity_key-style deterministic addressing
|
|
77
|
+
(pk_field=rk_field="identity_key", "id" never in the create payload)."""
|
|
78
|
+
fake = _FakeTableClient()
|
|
79
|
+
adapter = _adapter(fake)
|
|
80
|
+
|
|
81
|
+
data = {
|
|
82
|
+
"identity_key": "email:sireesh.psvs@gmail.com",
|
|
83
|
+
"tenant_id": "altcodepro",
|
|
84
|
+
"email": "sireesh.psvs@gmail.com",
|
|
85
|
+
"auth_method": "password",
|
|
86
|
+
}
|
|
87
|
+
created = adapter._put_raw(
|
|
88
|
+
_Model, "email:sireesh.psvs@gmail.com", "email:sireesh.psvs@gmail.com", data
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
returned_id = created["id"]
|
|
92
|
+
assert returned_id == "email_sireesh.psvs@gmail.com" # sanitized (colon -> underscore)
|
|
93
|
+
|
|
94
|
+
# The load-bearing assertion: the STORED entity itself (not just this
|
|
95
|
+
# one call's own return value) now has a real "id" property.
|
|
96
|
+
stored = fake.store[("email_sireesh.psvs@gmail.com", "email_sireesh.psvs@gmail.com")]
|
|
97
|
+
assert stored["id"] == returned_id
|
|
98
|
+
|
|
99
|
+
# And the ordinary id-addressed lookup every update()/patch() "before"
|
|
100
|
+
# read performs now actually finds the row -- reproduced BROKEN before
|
|
101
|
+
# this fix (would have returned []).
|
|
102
|
+
found = adapter._query_raw(_Model, {"id": returned_id, "tenant_id": "altcodepro"}, None)
|
|
103
|
+
assert len(found) == 1
|
|
104
|
+
assert found[0]["email"] == "sireesh.psvs@gmail.com"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_a_create_that_already_supplies_its_own_id_is_left_untouched():
|
|
108
|
+
fake = _FakeTableClient()
|
|
109
|
+
adapter = _adapter(fake)
|
|
110
|
+
|
|
111
|
+
data = {"id": "caller-chosen-id", "tenant_id": "t1", "name": "x"}
|
|
112
|
+
created = adapter._put_raw(_Model, "t1", "caller-chosen-id", data)
|
|
113
|
+
|
|
114
|
+
assert created["id"] == "caller-chosen-id"
|
|
115
|
+
stored = fake.store[("t1", "caller-chosen-id")]
|
|
116
|
+
assert stored["id"] == "caller-chosen-id"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_two_different_identities_never_collide_and_both_are_independently_findable():
|
|
120
|
+
fake = _FakeTableClient()
|
|
121
|
+
adapter = _adapter(fake)
|
|
122
|
+
|
|
123
|
+
for email in ("sireesh.psvs@gmail.com", "pangaluri2010@gmail.com"):
|
|
124
|
+
key = f"email:{email}"
|
|
125
|
+
adapter._put_raw(
|
|
126
|
+
_Model,
|
|
127
|
+
key,
|
|
128
|
+
key,
|
|
129
|
+
{
|
|
130
|
+
"identity_key": key,
|
|
131
|
+
"tenant_id": "altcodepro",
|
|
132
|
+
"email": email,
|
|
133
|
+
},
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
assert len(fake.store) == 2
|
|
137
|
+
for email in ("sireesh.psvs@gmail.com", "pangaluri2010@gmail.com"):
|
|
138
|
+
rows = adapter._query_raw(_Model, {"email": email}, None)
|
|
139
|
+
assert len(rows) == 1 and rows[0]["email"] == email
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_repeat_put_for_the_same_identity_key_upserts_the_same_row_not_a_duplicate():
|
|
143
|
+
"""The actual, originally-reported symptom this whole chain of fixes
|
|
144
|
+
exists to close: a second signup attempt for the same email must
|
|
145
|
+
collapse onto the SAME physical row, never mint a new one."""
|
|
146
|
+
fake = _FakeTableClient()
|
|
147
|
+
adapter = _adapter(fake)
|
|
148
|
+
|
|
149
|
+
key = "email:sireesh.psvs@gmail.com"
|
|
150
|
+
adapter._put_raw(
|
|
151
|
+
_Model,
|
|
152
|
+
key,
|
|
153
|
+
key,
|
|
154
|
+
{
|
|
155
|
+
"identity_key": key,
|
|
156
|
+
"tenant_id": "altcodepro",
|
|
157
|
+
"email": "sireesh.psvs@gmail.com",
|
|
158
|
+
"display_name": "Sireesh",
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
adapter._put_raw(
|
|
162
|
+
_Model,
|
|
163
|
+
key,
|
|
164
|
+
key,
|
|
165
|
+
{
|
|
166
|
+
"identity_key": key,
|
|
167
|
+
"tenant_id": "altcodepro",
|
|
168
|
+
"email": "sireesh.psvs@gmail.com",
|
|
169
|
+
"display_name": "Sireesh Updated",
|
|
170
|
+
},
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
assert len(fake.store) == 1
|
|
174
|
+
only_row = next(iter(fake.store.values()))
|
|
175
|
+
assert only_row["display_name"] == "Sireesh Updated"
|
altcodepro_polydb_python-2.5.10/tests/test_azure_table_id_return_value_sanitization_mismatch.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Unit tests (no Azurite needed) for a real, reproduced bug: `_put_raw`
|
|
2
|
+
unconditionally overwrote its own RETURN value's "id" field with `safe_rk`
|
|
3
|
+
(the Azure-RowKey-sanitized value) even when the caller's own write payload
|
|
4
|
+
already supplied a real "id" -- so whenever that caller-supplied id needed
|
|
5
|
+
RowKey sanitization (contains a character Azure forbids in a RowKey: ':',
|
|
6
|
+
' ', '#', '?', '/', '\\'), the PERSISTED entity's "id" property (written
|
|
7
|
+
verbatim from the caller's own `data`, untouched) and the RETURNED value's
|
|
8
|
+
"id" (always `safe_rk`) silently disagreed.
|
|
9
|
+
|
|
10
|
+
This is a distinct bug from the one `test_azure_table_id_property_persisted.py`
|
|
11
|
+
already covers and fixed (2.5.9: a create with NO "id" in its own payload
|
|
12
|
+
never landed a real "id" property at all) -- that fix's own condition
|
|
13
|
+
(`if "id" not in data: data = {**data, "id": safe_rk}`) only ever touches
|
|
14
|
+
the WRITE side. The return-value line right below it (`restored["id"] =
|
|
15
|
+
safe_rk`) had no matching condition, so it fired even when `data["id"]`
|
|
16
|
+
was already present and different from `safe_rk`.
|
|
17
|
+
|
|
18
|
+
Real, reproduced downstream symptom (altcodepro-blueprint-engine): the
|
|
19
|
+
`artifacts` model deliberately builds a colon-joined deterministic id
|
|
20
|
+
(`project_id + ':' + definition_id`) with `rk_field` pointing at that same
|
|
21
|
+
value. `core.db.create_many`'s own CEL-built row data already supplies
|
|
22
|
+
this "id" explicitly. The persisted entity's "id" property therefore kept
|
|
23
|
+
the real, colon-joined value -- but every returned row's own "id" (what a
|
|
24
|
+
workflow's `steps.<create_step>.created.map(c, ...c.id...)` reads to
|
|
25
|
+
enqueue a follow-up job) came back with the colon sanitized to an
|
|
26
|
+
underscore instead. The follow-up job's own `core.db.get(id=<that wrong,
|
|
27
|
+
sanitized value>)` then built an OData `id eq '<sanitized>'` filter that
|
|
28
|
+
matched nothing -- every real row existed, but was unreachable by the very
|
|
29
|
+
id its own creation step just handed out.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
import pytest
|
|
33
|
+
|
|
34
|
+
pytest.importorskip("azure.data.tables") # adapter needs the SDK to import
|
|
35
|
+
|
|
36
|
+
from polydb.adapters.AzureTableStorageAdapter import AzureTableStorageAdapter # noqa: E402
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class _Model:
|
|
40
|
+
__name__ = "artifacts"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class _FakeTableClient:
|
|
44
|
+
"""The same real filter-evaluating fake
|
|
45
|
+
test_azure_table_id_property_persisted.py already establishes -- reused
|
|
46
|
+
verbatim rather than re-derived, since this bug lives in the identical
|
|
47
|
+
`_query_raw` OData-filter mechanism."""
|
|
48
|
+
|
|
49
|
+
def __init__(self):
|
|
50
|
+
self.store: dict[tuple, dict] = {}
|
|
51
|
+
|
|
52
|
+
def upsert_entity(self, entity, **kw):
|
|
53
|
+
self.store[(entity["PartitionKey"], entity["RowKey"])] = dict(entity)
|
|
54
|
+
|
|
55
|
+
def query_entities(self, query_filter=None, **kw):
|
|
56
|
+
if query_filter is None:
|
|
57
|
+
return list(self.store.values())
|
|
58
|
+
conditions = []
|
|
59
|
+
for part in query_filter.split(" and "):
|
|
60
|
+
prop, _, raw_val = part.partition(" eq ")
|
|
61
|
+
if raw_val.startswith("'") and raw_val.endswith("'"):
|
|
62
|
+
val = raw_val[1:-1].replace("''", "'")
|
|
63
|
+
elif raw_val == "null":
|
|
64
|
+
val = None
|
|
65
|
+
elif raw_val in ("true", "false"):
|
|
66
|
+
val = raw_val == "true"
|
|
67
|
+
else:
|
|
68
|
+
val = float(raw_val) if "." in raw_val else int(raw_val)
|
|
69
|
+
conditions.append((prop, val))
|
|
70
|
+
return [
|
|
71
|
+
e for e in self.store.values() if all(e.get(prop) == val for prop, val in conditions)
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _adapter(fake):
|
|
76
|
+
adp = object.__new__(AzureTableStorageAdapter) # bypass live-connection __init__
|
|
77
|
+
adp._get_table_client = lambda model: fake
|
|
78
|
+
adp._blob_service = None
|
|
79
|
+
adp.object_storage = None
|
|
80
|
+
return adp
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_a_caller_supplied_id_needing_rowkey_sanitization_is_returned_unsanitized():
|
|
84
|
+
"""The actual reported bug, reproduced with the real shape:
|
|
85
|
+
project_id + ':' + definition_id, used as both "id" and the rk_field
|
|
86
|
+
value -- ':' is not a legal Azure RowKey character."""
|
|
87
|
+
fake = _FakeTableClient()
|
|
88
|
+
adapter = _adapter(fake)
|
|
89
|
+
|
|
90
|
+
caller_id = "485533b9-8d0f-4e5f-92da-670cedfe92f5:backend.backend_schema"
|
|
91
|
+
data = {
|
|
92
|
+
"id": caller_id,
|
|
93
|
+
"artifact_id": caller_id,
|
|
94
|
+
"project_slug": "community-platform-187",
|
|
95
|
+
"tenant_id": "altcodepro",
|
|
96
|
+
"name": "Backend Schema",
|
|
97
|
+
}
|
|
98
|
+
created = adapter._put_raw(_Model, "community-platform-187", caller_id, data)
|
|
99
|
+
|
|
100
|
+
# The load-bearing assertion: the RETURN value's "id" must equal what
|
|
101
|
+
# the caller actually supplied -- never the sanitized RowKey. Before
|
|
102
|
+
# the fix this was "485533b9-...-670cedfe92f5_backend.backend_schema"
|
|
103
|
+
# (colon silently replaced with underscore).
|
|
104
|
+
assert created["id"] == caller_id
|
|
105
|
+
|
|
106
|
+
# And it must agree with what's genuinely persisted -- the real
|
|
107
|
+
# invariant this bug violated (two different strings for the same
|
|
108
|
+
# row's own "id").
|
|
109
|
+
safe_rk = adapter._sanitize_pk_rk(caller_id)
|
|
110
|
+
stored = fake.store[("community-platform-187", safe_rk)]
|
|
111
|
+
assert stored["id"] == caller_id == created["id"]
|
|
112
|
+
|
|
113
|
+
# The actual downstream failure this caused: a follow-up step (e.g.
|
|
114
|
+
# start_artifact_generation's own load_artifact) doing
|
|
115
|
+
# core.db.get(id=<the id create_many just returned>) must find the
|
|
116
|
+
# row. Reproduced BROKEN before this fix -- querying by the correct,
|
|
117
|
+
# returned id found nothing, because the stored property and the
|
|
118
|
+
# returned value disagreed.
|
|
119
|
+
found = adapter._query_raw(_Model, {"id": created["id"], "tenant_id": "altcodepro"}, None)
|
|
120
|
+
assert len(found) == 1
|
|
121
|
+
assert found[0]["name"] == "Backend Schema"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_a_caller_supplied_id_needing_no_sanitization_is_unaffected():
|
|
125
|
+
"""Negative control: when the caller's own id is already RowKey-safe,
|
|
126
|
+
safe_rk == the caller's id anyway, so this bug was invisible -- exactly
|
|
127
|
+
why it slipped past every existing test until now."""
|
|
128
|
+
fake = _FakeTableClient()
|
|
129
|
+
adapter = _adapter(fake)
|
|
130
|
+
|
|
131
|
+
data = {"id": "caller-chosen-id", "tenant_id": "t1", "name": "x"}
|
|
132
|
+
created = adapter._put_raw(_Model, "t1", "caller-chosen-id", data)
|
|
133
|
+
|
|
134
|
+
assert created["id"] == "caller-chosen-id"
|
|
135
|
+
stored = fake.store[("t1", "caller-chosen-id")]
|
|
136
|
+
assert stored["id"] == "caller-chosen-id"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_no_id_in_payload_still_synthesizes_safe_rk_onto_both_sides():
|
|
140
|
+
"""The 2.5.9 case must still work identically -- this fix only adds a
|
|
141
|
+
condition around the return-value line, it must not touch the
|
|
142
|
+
no-id-supplied path at all."""
|
|
143
|
+
fake = _FakeTableClient()
|
|
144
|
+
adapter = _adapter(fake)
|
|
145
|
+
|
|
146
|
+
data = {"identity_key": "email:x@example.com", "tenant_id": "altcodepro"}
|
|
147
|
+
created = adapter._put_raw(_Model, "email:x@example.com", "email:x@example.com", data)
|
|
148
|
+
|
|
149
|
+
assert created["id"] == "email_x@example.com"
|
|
150
|
+
stored = fake.store[("email_x@example.com", "email_x@example.com")]
|
|
151
|
+
assert stored["id"] == created["id"] == "email_x@example.com"
|
|
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.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/EFSAdapter.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
|
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/S3Adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/SQSAdapter.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.8 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/advanced_query.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/AuditStorage.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/context.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/manager.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/models.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/NoSQLKVAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/QueueAdapter.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/SecretsAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/base/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/src/polydb/databaseFactory.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.8 → altcodepro_polydb_python-2.5.10}/src/polydb/multitenancy.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.8 → altcodepro_polydb_python-2.5.10}/src/polydb/services/__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.8 → altcodepro_polydb_python-2.5.10}/tests/test_atomic_decrement.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_audit_chain_cutover.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.8 → altcodepro_polydb_python-2.5.10}/tests/test_cloud_factory.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/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.8 → altcodepro_polydb_python-2.5.10}/tests/test_multi_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_observability.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.8 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_aws.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_vault.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.8 → altcodepro_polydb_python-2.5.10}/tests/test_session_vars.py
RENAMED
|
File without changes
|
|
File without changes
|