altcodepro-polydb-python 2.6.0__tar.gz → 2.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. {altcodepro_polydb_python-2.6.0/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.6.1}/PKG-INFO +1 -1
  2. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/pyproject.toml +1 -1
  3. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
  4. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +1 -0
  5. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/AzureTableStorageAdapter.py +28 -16
  6. altcodepro_polydb_python-2.6.1/tests/test_azure_table_list_filter.py +53 -0
  7. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/LICENSE +0 -0
  8. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/MANIFEST.in +0 -0
  9. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/README.md +0 -0
  10. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/requirements-aws.txt +0 -0
  11. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/requirements-azure.txt +0 -0
  12. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/requirements-dev.txt +0 -0
  13. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/requirements-gcp.txt +0 -0
  14. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/requirements-generic.txt +0 -0
  15. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/requirements.txt +0 -0
  16. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/setup.cfg +0 -0
  17. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/setup.py +0 -0
  18. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
  19. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
  20. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
  21. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/PolyDB.py +0 -0
  22. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/__init__.py +0 -0
  23. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/AWSSecretsManagerAdapter.py +0 -0
  24. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
  25. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
  26. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/AzureKeyVaultAdapter.py +0 -0
  27. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
  28. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
  29. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/BlockchainFileAdapter.py +0 -0
  30. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
  31. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
  32. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
  33. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/EFSAdapter.py +0 -0
  34. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/FirestoreAdapter.py +0 -0
  35. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/GCPFilestoreAdapter.py +0 -0
  36. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
  37. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/GCPSecretManagerAdapter.py +0 -0
  38. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
  39. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/KafkaQueueAdapter.py +0 -0
  40. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/MongoDBAdapter.py +0 -0
  41. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/PostgreSQLAdapter.py +0 -0
  42. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/RabbitMQAdapter.py +0 -0
  43. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/S3Adapter.py +0 -0
  44. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
  45. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/SQSAdapter.py +0 -0
  46. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/VaultAdapter.py +0 -0
  47. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
  48. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/VercelFileAdapter.py +0 -0
  49. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/VercelKVAdapter.py +0 -0
  50. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
  51. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/adapters/__init__.py +0 -0
  52. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/advanced_query.py +0 -0
  53. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/aio.py +0 -0
  54. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/audit/AuditStorage.py +0 -0
  55. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/audit/__init__.py +0 -0
  56. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/audit/context.py +0 -0
  57. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/audit/manager.py +0 -0
  58. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/audit/models.py +0 -0
  59. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/NoSQLKVAdapter.py +0 -0
  60. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/ObjectStorageAdapter.py +0 -0
  61. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/QueueAdapter.py +0 -0
  62. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/SecretsAdapter.py +0 -0
  63. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/SharedFilesAdapter.py +0 -0
  64. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/__init__.py +0 -0
  65. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/base/constraints.py +0 -0
  66. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/batch.py +0 -0
  67. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/cache.py +0 -0
  68. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/cloudDatabaseFactory.py +0 -0
  69. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/databaseFactory.py +0 -0
  70. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/errors.py +0 -0
  71. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/json_safe.py +0 -0
  72. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/models.py +0 -0
  73. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/monitoring.py +0 -0
  74. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/multitenancy.py +0 -0
  75. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/observability/__init__.py +0 -0
  76. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/observability/logging.py +0 -0
  77. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/overflow_gc.py +0 -0
  78. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/py.typed +0 -0
  79. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/query.py +0 -0
  80. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/read_batch.py +0 -0
  81. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/registry.py +0 -0
  82. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/retry.py +0 -0
  83. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/schema.py +0 -0
  84. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/security.py +0 -0
  85. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/services/__init__.py +0 -0
  86. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/services/compliance_service.py +0 -0
  87. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/services/security_service.py +0 -0
  88. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/types.py +0 -0
  89. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/utils.py +0 -0
  90. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/validation.py +0 -0
  91. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/src/polydb/write_behind.py +0 -0
  92. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_advanced_query_injection.py +0 -0
  93. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_async_api.py +0 -0
  94. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_atomic_decrement.py +0 -0
  95. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_audit_chain_cutover.py +0 -0
  96. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_audit_hmac.py +0 -0
  97. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_aws.py +0 -0
  98. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure.py +0 -0
  99. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_keyvault_credential.py +0 -0
  100. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_queue_receipt_handle.py +0 -0
  101. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_empty_filter.py +0 -0
  102. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_id_property_persisted.py +0 -0
  103. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_id_return_value_sanitization_mismatch.py +0 -0
  104. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_key_field_filter.py +0 -0
  105. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_large_record_patch_roundtrip.py +0 -0
  106. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_self_heal.py +0 -0
  107. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_azure_table_unpack_entity.py +0 -0
  108. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_blockchain.py +0 -0
  109. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_blockchain_overflow_guard.py +0 -0
  110. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_cloud_factory.py +0 -0
  111. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_create_unique_violation.py +0 -0
  112. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_factory_wiring.py +0 -0
  113. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_field_encryption.py +0 -0
  114. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_gcp.py +0 -0
  115. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_kafka.py +0 -0
  116. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_like_pattern_escaping.py +0 -0
  117. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_mongodb.py +0 -0
  118. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_monitoring_health.py +0 -0
  119. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_multi_engine.py +0 -0
  120. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_multitenancy_ddl_injection.py +0 -0
  121. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_nosql_constraints.py +0 -0
  122. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_nosql_kv_overflow_write_path.py +0 -0
  123. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_nosql_operator_injection.py +0 -0
  124. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_observability.py +0 -0
  125. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_overflow_gc.py +0 -0
  126. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_postgres_lazy_pool.py +0 -0
  127. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_postgresql.py +0 -0
  128. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_postgresql_deserialize_row.py +0 -0
  129. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_queue_extend_delay_cancel.py +0 -0
  130. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_rabbitmq.py +0 -0
  131. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_read_batch.py +0 -0
  132. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_read_projection.py +0 -0
  133. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_redis_kv.py +0 -0
  134. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_schema_ddl_injection.py +0 -0
  135. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_secrets_aws.py +0 -0
  136. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_secrets_vault.py +0 -0
  137. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_session_vars.py +0 -0
  138. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_vercel.py +0 -0
  139. {altcodepro_polydb_python-2.6.0 → altcodepro_polydb_python-2.6.1}/tests/test_write_behind.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: altcodepro-polydb-python
3
- Version: 2.6.0
3
+ Version: 2.6.1
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.6.0"
7
+ version = "2.6.1"
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.6.0
3
+ Version: 2.6.1
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
@@ -100,6 +100,7 @@ tests/test_azure_table_id_property_persisted.py
100
100
  tests/test_azure_table_id_return_value_sanitization_mismatch.py
101
101
  tests/test_azure_table_key_field_filter.py
102
102
  tests/test_azure_table_large_record_patch_roundtrip.py
103
+ tests/test_azure_table_list_filter.py
103
104
  tests/test_azure_table_self_heal.py
104
105
  tests/test_azure_table_unpack_entity.py
105
106
  tests/test_blockchain.py
@@ -785,22 +785,34 @@ class AzureTableStorageAdapter(NoSQLKVAdapter):
785
785
  self._sanitize_prop_name(orig_k) if orig_k != _MODEL_FIELD else _MODEL_FIELD
786
786
  )
787
787
 
788
- ev = self._encode_value(orig_v)
789
-
790
- if ev is None:
791
- parts.append(f"{sk} eq null")
792
- elif isinstance(ev, bool):
793
- parts.append(f"{sk} eq {str(ev).lower()}")
794
- elif isinstance(ev, (int, float)):
795
- parts.append(f"{sk} eq {ev}")
796
- elif isinstance(ev, datetime):
797
- iso = ev.isoformat()
798
- if not iso.endswith("Z"):
799
- iso = iso + "Z"
800
- parts.append(f"{sk} eq datetime'{iso}'")
801
- else:
802
- sval = str(ev).replace("'", "''")
803
- parts.append(f"{sk} eq '{sval}'")
788
+ def _eq(prop: str, raw: Any) -> str:
789
+ ev = self._encode_value(raw)
790
+ if ev is None:
791
+ return f"{prop} eq null"
792
+ if isinstance(ev, bool):
793
+ return f"{prop} eq {str(ev).lower()}"
794
+ if isinstance(ev, (int, float)):
795
+ return f"{prop} eq {ev}"
796
+ if isinstance(ev, datetime):
797
+ iso = ev.isoformat()
798
+ if not iso.endswith("Z"):
799
+ iso = iso + "Z"
800
+ return f"{prop} eq datetime'{iso}'"
801
+ return f"{prop} eq '{str(ev).replace(chr(39), chr(39) * 2)}'"
802
+
803
+ if isinstance(orig_v, (list, tuple, set, frozenset)) and all(
804
+ isinstance(x, (str, int, float, bool)) for x in orig_v
805
+ ):
806
+ # A list of plain values means "equals any of them" (the SQL adapters already read it that way). Sent as
807
+ # one JSON-encoded string it matched no row at all, so every `field: [a, b]` lookup silently returned [].
808
+ if not orig_v:
809
+ return [] # IN () matches nothing
810
+ if len(orig_v) > 100:
811
+ raise NoSQLError("Azure Table filter: at most 100 values in a list")
812
+ parts.append("(" + " or ".join(_eq(sk, x) for x in orig_v) + ")")
813
+ continue
814
+
815
+ parts.append(_eq(sk, orig_v))
804
816
 
805
817
  # Empty-filter contract: if the caller passed filter keys but every
806
818
  # condition dropped out (e.g. all values None/unresolvable), the query
@@ -0,0 +1,53 @@
1
+ """A list of plain values in a filter means "equals any of them" (it used to be sent as one JSON string and matched nothing)."""
2
+ import pytest
3
+
4
+ pytest.importorskip("azure.data.tables")
5
+
6
+ from polydb.adapters.AzureTableStorageAdapter import AzureTableStorageAdapter # noqa: E402
7
+
8
+
9
+ class _Model:
10
+ __name__ = "artifacts"
11
+ __polydb__ = {}
12
+
13
+
14
+ class _Fake:
15
+ def __init__(self):
16
+ self.calls = []
17
+
18
+ def query_entities(self, query_filter=None, **kw):
19
+ self.calls.append(query_filter)
20
+ return []
21
+
22
+
23
+ def _adapter(fake):
24
+ a = object.__new__(AzureTableStorageAdapter)
25
+ a._get_table_client = lambda model: fake
26
+ a.partition_config = None
27
+ return a
28
+
29
+
30
+ def test_a_list_becomes_an_or_group():
31
+ f = _Fake()
32
+ _adapter(f)._query_raw(_Model, {"project_id": "p1", "artifact_definition_id": ["a.x", "b.y", "it's"]}, 50)
33
+ flt = f.calls[0]
34
+ assert "project_id eq 'p1'" in flt
35
+ assert "(artifact_definition_id eq 'a.x' or artifact_definition_id eq 'b.y' or artifact_definition_id eq 'it''s')" in flt
36
+ assert "polydb_json" not in flt
37
+
38
+
39
+ def test_numbers_and_a_single_item_list():
40
+ f = _Fake()
41
+ _adapter(f)._query_raw(_Model, {"version": [1, 2], "status": ["complete"]}, 50)
42
+ assert "(version eq 1 or version eq 2)" in f.calls[0] and "(status eq 'complete')" in f.calls[0]
43
+
44
+
45
+ def test_an_empty_list_matches_nothing_without_querying():
46
+ f = _Fake()
47
+ assert _adapter(f)._query_raw(_Model, {"status": []}, 50) == [] and f.calls == []
48
+
49
+
50
+ def test_a_scalar_filter_is_unchanged():
51
+ f = _Fake()
52
+ _adapter(f)._query_raw(_Model, {"status": "complete", "version": 3, "ok": True}, 50)
53
+ assert f.calls[0] == "status eq 'complete' and version eq 3 and ok eq true"