altcodepro-polydb-python 2.5.9__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.9/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.5.10}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/pyproject.toml +1 -1
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +1 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/__init__.py +1 -1
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureTableStorageAdapter.py +20 -1
- altcodepro_polydb_python-2.5.10/tests/test_azure_table_id_return_value_sanitization_mismatch.py +151 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/LICENSE +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/MANIFEST.in +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/README.md +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/requirements-aws.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/requirements-azure.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/requirements-dev.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/requirements-gcp.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/requirements-generic.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/requirements.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/setup.cfg +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/setup.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/PolyDB.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AWSSecretsManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureKeyVaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/EFSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/FirestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPFilestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPSecretManagerAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/KafkaQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/MongoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/PostgreSQLAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/RabbitMQAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/S3Adapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/SQSAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VaultAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/advanced_query.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/AuditStorage.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/context.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/manager.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/models.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/NoSQLKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/ObjectStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/QueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/SecretsAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/SharedFilesAdapter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/batch.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/cache.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/cloudDatabaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/databaseFactory.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/decorators.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/errors.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/json_safe.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/models.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/monitoring.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/multitenancy.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/observability/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/observability/logging.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/py.typed +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/query.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/registry.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/retry.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/schema.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/security.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/services/__init__.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/services/compliance_service.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/services/security_service.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/types.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/utils.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/validation.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_advanced_query_injection.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_atomic_decrement.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_audit_chain_cutover.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_audit_hmac.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_aws.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_azure.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_azure_queue_receipt_handle.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_azure_table_empty_filter.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_azure_table_id_property_persisted.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_azure_table_unpack_entity.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_blockchain.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_cloud_factory.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_field_encryption.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_gcp.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_kafka.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_like_pattern_escaping.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_mongodb.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_multi_engine.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_multitenancy_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_nosql_operator_injection.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_observability.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_postgresql.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_queue_extend_delay_cancel.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_rabbitmq.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_redis_kv.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_schema_ddl_injection.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_aws.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_vault.py +0 -0
- {altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_session_vars.py +0 -0
- {altcodepro_polydb_python-2.5.9 → 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
|
|
@@ -91,6 +91,7 @@ tests/test_azure.py
|
|
|
91
91
|
tests/test_azure_queue_receipt_handle.py
|
|
92
92
|
tests/test_azure_table_empty_filter.py
|
|
93
93
|
tests/test_azure_table_id_property_persisted.py
|
|
94
|
+
tests/test_azure_table_id_return_value_sanitization_mismatch.py
|
|
94
95
|
tests/test_azure_table_unpack_entity.py
|
|
95
96
|
tests/test_blockchain.py
|
|
96
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
|
|
@@ -566,7 +566,26 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
|
|
|
566
566
|
table_client.upsert_entity(reference_entity)
|
|
567
567
|
|
|
568
568
|
restored = self._unpack_entity(model, entity)
|
|
569
|
-
|
|
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
|
|
570
589
|
|
|
571
590
|
return restored
|
|
572
591
|
|
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.9 → 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.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/S3Adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → 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.9 → altcodepro_polydb_python-2.5.10}/src/polydb/adapters/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/advanced_query.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/AuditStorage.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/context.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/manager.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/audit/models.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/NoSQLKVAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/QueueAdapter.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/src/polydb/base/SecretsAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → 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.9 → 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.9 → 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.9 → 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.9 → altcodepro_polydb_python-2.5.10}/tests/test_atomic_decrement.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → 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
|
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_cloud_factory.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → 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.9 → 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.9 → 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.9 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_aws.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_secrets_vault.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.5.9 → altcodepro_polydb_python-2.5.10}/tests/test_session_vars.py
RENAMED
|
File without changes
|
|
File without changes
|