Skip to content

Commit 65edd73

Browse files
authored
Fix: Allow tuples to be used for hierarchical partition key values. (Azure#38136)
* Fix support for allowing tuples to be used for subapartition Allows the usage of tuples alongside lists to be used for hierarchical partition key values. Both get serialized to json arrays. Previous behaviour would give an error that a prefix query was attempted which is incorrect behaviour. * update docstrings * Update CHANGELOG.md * Update partition_key.py * Update partition_key.py optimization * Update partition_key.py * Update partition_key.py * Update partition_key.py * Update type hint of partition key Changes the type hint of partition key to be sequence instead of explicitly tuple and list. * update version update version to 4.8.0
1 parent 38421d9 commit 65edd73

File tree

8 files changed

+83
-31
lines changed

8 files changed

+83
-31
lines changed

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Release History
22

3-
### 4.7.1 (Unreleased)
3+
### 4.8.0 (2024-11-12)
44
This version and all future versions will support Python 3.13.
55

66
#### Features Added
@@ -24,6 +24,7 @@ For more information on this, see our README section [here](https://github.com/A
2424
* Added retry handling logic for DatabaseAccountNotFound exceptions. See [PR 36514](https://github.com/Azure/azure-sdk-for-python/pull/36514).
2525
* Fixed SDK regex validation that would not allow for item ids to be longer than 255 characters. See [PR 36569](https://github.com/Azure/azure-sdk-for-python/pull/36569).
2626
* Fixed issue where 'NoneType' object has no attribute error was raised when a session retry happened during a query. See [PR 37578](https://github.com/Azure/azure-sdk-for-python/pull/37578).
27+
* Fixed issue where passing subpartition partition key values as a tuple in a query would raise an error. See [PR 38136](https://github.com/Azure/azure-sdk-for-python/pull/38136)
2728
* Batch requests will now be properly considered as Write operation. See [PR 38365](https://github.com/Azure/azure-sdk-for-python/pull/38365).
2829

2930
#### Other Changes

sdk/cosmos/azure-cosmos/azure/cosmos/_base.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,11 @@ def GetHeaders( # pylint: disable=too-many-statements,too-many-branches
227227
# else serialize using json dumps method which apart from regular values will serialize None into null
228228
else:
229229
# single partitioning uses a string and needs to be turned into a list
230-
if isinstance(options["partitionKey"], list) and options["partitionKey"]:
231-
pk_val = json.dumps(options["partitionKey"], separators=(',', ':'))
230+
is_sequence_not_string = (isinstance(options["partitionKey"], Sequence) and
231+
not isinstance(options["partitionKey"], str))
232+
233+
if is_sequence_not_string and options["partitionKey"]:
234+
pk_val = json.dumps(list(options["partitionKey"]), separators=(',', ':'))
232235
else:
233236
pk_val = json.dumps([options["partitionKey"]])
234237
headers[http_constants.HttpHeaders.PartitionKey] = pk_val

sdk/cosmos/azure-cosmos/azure/cosmos/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
# SOFTWARE.
2121

22-
VERSION = "4.7.1"
22+
VERSION = "4.8.0"

sdk/cosmos/azure-cosmos/azure/cosmos/aio/_container.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ async def read_item(
283283
:param item: The ID (name) or dict representing item to retrieve.
284284
:type item: Union[str, Dict[str, Any]]
285285
:param partition_key: Partition key for the item to retrieve.
286-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
286+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
287287
:keyword str post_trigger_include: trigger id to be used as post operation trigger.
288288
:keyword str session_token: Token for use with Session consistency.
289289
:keyword dict[str, str] initial_headers: Initial headers to be sent as part of the request.
@@ -413,7 +413,7 @@ def query_items(
413413
:paramtype parameters: List[Dict[str, Any]]
414414
:keyword partition_key: Specifies the partition key value for the item. If none is provided,
415415
a cross-partition query will be executed.
416-
:paramtype partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
416+
:paramtype partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
417417
:keyword int max_item_count: Max number of items to be returned in the enumeration operation.
418418
:keyword bool enable_scan_in_query: Allow scan on the queries which couldn't be served as
419419
indexing was opted out on the requested paths.
@@ -521,7 +521,7 @@ def query_items_change_feed(
521521
:type start_time: Union[~datetime.datetime, Literal["Now", "Beginning"]]
522522
:keyword partition_key: The partition key that is used to define the scope
523523
(logical partition or a subset of a container)
524-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
524+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
525525
:keyword Literal["High", "Low"] priority: Priority based execution allows users to set a priority for each
526526
request. Once the user has reached their provisioned throughput, low priority requests are throttled
527527
before high priority requests start getting throttled. Feature must first be enabled at the account level.
@@ -623,7 +623,7 @@ def query_items_change_feed( # pylint: disable=unused-argument
623623
:keyword Dict[str, Any] feed_range: The feed range that is used to define the scope.
624624
:keyword partition_key: The partition key that is used to define the scope
625625
(logical partition or a subset of a container)
626-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
626+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
627627
:keyword int max_item_count: Max number of items to be returned in the enumeration operation.
628628
:keyword start_time: The start time to start processing chang feed items.
629629
Beginning: Processing the change feed items from the beginning of the change feed.
@@ -877,7 +877,7 @@ async def patch_item(
877877
:param item: The ID (name) or dict representing item to be patched.
878878
:type item: Union[str, Dict[str, Any]]
879879
:param partition_key: The partition key of the object to patch.
880-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
880+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
881881
:param patch_operations: The list of patch operations to apply to the item.
882882
:type patch_operations: List[Dict[str, Any]]
883883
:keyword str filter_predicate: conditional filter to apply to Patch operations.
@@ -949,7 +949,7 @@ async def delete_item(
949949
:param item: The ID (name) or dict representing item to be deleted.
950950
:type item: Union[str, Dict[str, Any]]
951951
:param partition_key: Specifies the partition key value for the item.
952-
:type partition_key: Union[str, int, float, bool]
952+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
953953
:keyword str pre_trigger_include: trigger id to be used as pre operation trigger.
954954
:keyword str post_trigger_include: trigger id to be used as post operation trigger.
955955
:keyword str session_token: Token for use with Session consistency.
@@ -1102,7 +1102,7 @@ def query_conflicts(
11021102
:paramtype parameters: List[Dict[str, Any]]
11031103
:keyword partition_key: Specifies the partition key value for the item. If none is passed in, a
11041104
cross partition query will be executed.
1105-
:paramtype partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1105+
:paramtype partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
11061106
:keyword int max_item_count: Max number of items to be returned in the enumeration operation.
11071107
:keyword response_hook: A callable invoked with the response metadata.
11081108
:paramtype response_hook: Callable[[Dict[str, str], AsyncItemPaged[Dict[str, Any]]], None]
@@ -1142,7 +1142,7 @@ async def get_conflict(
11421142
:param conflict: The ID (name) or dict representing the conflict to retrieve.
11431143
:type conflict: Union[str, Dict[str, Any]]
11441144
:param partition_key: Partition key for the conflict to retrieve.
1145-
:type partition_key: Union[str, int, float, bool]
1145+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
11461146
:keyword response_hook: A callable invoked with the response metadata.
11471147
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
11481148
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The given conflict couldn't be retrieved.
@@ -1172,7 +1172,7 @@ async def delete_conflict(
11721172
:param conflict: The ID (name) or dict representing the conflict to retrieve.
11731173
:type conflict: Union[str, Dict[str, Any]]
11741174
:param partition_key: Partition key for the conflict to retrieve.
1175-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1175+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
11761176
:keyword response_hook: A callable invoked with the response metadata.
11771177
:paramtype response_hook: Callable[[Dict[str, str], None], None]
11781178
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The conflict wasn't deleted successfully.
@@ -1205,7 +1205,7 @@ async def delete_all_items_by_partition_key(
12051205
this background task.
12061206
12071207
:param partition_key: Partition key for the items to be deleted.
1208-
:type partition_key: Any
1208+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
12091209
:keyword str pre_trigger_include: trigger id to be used as pre operation trigger.
12101210
:keyword str post_trigger_include: trigger id to be used as post operation trigger.
12111211
:keyword str session_token: Token for use with Session consistency.
@@ -1253,7 +1253,7 @@ async def execute_item_batch(
12531253
:param batch_operations: The batch of operations to be executed.
12541254
:type batch_operations: List[Tuple[Any]]
12551255
:param partition_key: The partition key value of the batch operations.
1256-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1256+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
12571257
:keyword str pre_trigger_include: trigger id to be used as pre operation trigger.
12581258
:keyword str post_trigger_include: trigger id to be used as post operation trigger.
12591259
:keyword str session_token: Token for use with Session consistency.

sdk/cosmos/azure-cosmos/azure/cosmos/container.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def read_item( # pylint:disable=docstring-missing-param
212212
:param item: The ID (name) or dict representing item to retrieve.
213213
:type item: Union[str, Dict[str, Any]]
214214
:param partition_key: Partition key for the item to retrieve.
215-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
215+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
216216
:param str post_trigger_include: trigger id to be used as post operation trigger.
217217
:keyword str session_token: Token for use with Session consistency.
218218
:keyword Dict[str, str] initial_headers: Initial headers to be sent as part of the request.
@@ -341,7 +341,7 @@ def query_items_change_feed(
341341
:type start_time: Union[~datetime.datetime, Literal["Now", "Beginning"]]
342342
:keyword partition_key: The partition key that is used to define the scope
343343
(logical partition or a subset of a container)
344-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
344+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
345345
:keyword Literal["High", "Low"] priority: Priority based execution allows users to set a priority for each
346346
request. Once the user has reached their provisioned throughput, low priority requests are throttled
347347
before high priority requests start getting throttled. Feature must first be enabled at the account level.
@@ -444,7 +444,7 @@ def query_items_change_feed(
444444
:keyword Dict[str, Any] feed_range: The feed range that is used to define the scope.
445445
:keyword partition_key: The partition key that is used to define the scope
446446
(logical partition or a subset of a container)
447-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
447+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
448448
:keyword int max_item_count: Max number of items to be returned in the enumeration operation.
449449
:keyword start_time: The start time to start processing chang feed items.
450450
Beginning: Processing the change feed items from the beginning of the change feed.
@@ -576,7 +576,7 @@ def query_items( # pylint:disable=docstring-missing-param
576576
Ignored if no query is provided.
577577
:type parameters: [List[Dict[str, object]]]
578578
:param partition_key: partition key at which the query request is targeted.
579-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
579+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
580580
:param bool enable_cross_partition_query: Allows sending of more than one request to
581581
execute the query in the Azure Cosmos DB service.
582582
More than one request is necessary if the query is not scoped to single partition key value.
@@ -933,7 +933,7 @@ def patch_item(
933933
:param item: The ID (name) or dict representing item to be patched.
934934
:type item: Union[str, Dict[str, Any]]
935935
:param partition_key: The partition key of the object to patch.
936-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
936+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
937937
:param patch_operations: The list of patch operations to apply to the item.
938938
:type patch_operations: List[Dict[str, Any]]
939939
:keyword str filter_predicate: conditional filter to apply to Patch operations.
@@ -1002,7 +1002,7 @@ def execute_item_batch(
10021002
:param batch_operations: The batch of operations to be executed.
10031003
:type batch_operations: List[Tuple[Any]]
10041004
:param partition_key: The partition key value of the batch operations.
1005-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1005+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
10061006
:keyword str pre_trigger_include: trigger id to be used as pre operation trigger.
10071007
:keyword str post_trigger_include: trigger id to be used as post operation trigger.
10081008
:keyword str session_token: Token for use with Session consistency.
@@ -1060,7 +1060,7 @@ def delete_item( # pylint:disable=docstring-missing-param
10601060
:param item: The ID (name) or dict representing item to be deleted.
10611061
:type item: Union[str, Dict[str, Any]]
10621062
:param partition_key: Specifies the partition key value for the item.
1063-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1063+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
10641064
:param str pre_trigger_include: trigger id to be used as pre operation trigger.
10651065
:param str post_trigger_include: trigger id to be used as post operation trigger.
10661066
:keyword str session_token: Token for use with Session consistency.
@@ -1229,7 +1229,7 @@ def query_conflicts(
12291229
the query in the Azure Cosmos DB service.
12301230
More than one request is necessary if the query is not scoped to single partition key value.
12311231
:param partition_key: Specifies the partition key value for the item.
1232-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1232+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
12331233
:param int max_item_count: Max number of items to be returned in the enumeration operation.
12341234
:keyword Callable response_hook: A callable invoked with the response metadata.
12351235
:returns: An Iterable of conflicts (dicts).
@@ -1268,7 +1268,7 @@ def get_conflict(
12681268
:param conflict: The ID (name) or dict representing the conflict to retrieve.
12691269
:type conflict: Union[str, Dict[str, Any]]
12701270
:param partition_key: Partition key for the conflict to retrieve.
1271-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1271+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
12721272
:keyword Callable response_hook: A callable invoked with the response metadata.
12731273
:returns: A dict representing the retrieved conflict.
12741274
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The given conflict couldn't be retrieved.
@@ -1298,7 +1298,7 @@ def delete_conflict(
12981298
:param conflict: The ID (name) or dict representing the conflict to be deleted.
12991299
:type conflict: Union[str, Dict[str, Any]]
13001300
:param partition_key: Partition key for the conflict to delete.
1301-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1301+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
13021302
:keyword Callable response_hook: A callable invoked with the response metadata.
13031303
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The conflict wasn't deleted successfully.
13041304
:raises ~azure.cosmos.exceptions.CosmosResourceNotFoundError: The conflict does not exist in the container.
@@ -1333,7 +1333,7 @@ def delete_all_items_by_partition_key(
13331333
this background task.
13341334
13351335
:param partition_key: Partition key for the items to be deleted.
1336-
:type partition_key: Union[str, int, float, bool, List[Union[str, int, float, bool]]]
1336+
:type partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]]]
13371337
:keyword str pre_trigger_include: trigger id to be used as pre operation trigger.
13381338
:keyword str post_trigger_include: trigger id to be used as post operation trigger.
13391339
:keyword str session_token: Token for use with Session consistency.

sdk/cosmos/azure-cosmos/azure/cosmos/partition_key.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,12 @@ def _get_effective_partition_key_for_multi_hash_partitioning_v2(
281281

282282
def _is_prefix_partition_key(
283283
self,
284-
partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]], Type[NonePartitionKeyValue]]) -> bool: # pylint: disable=line-too-long
285-
if self.kind!= "MultiHash":
286-
return False
287-
if isinstance(partition_key, list) and len(self['paths']) == len(partition_key):
284+
partition_key: Union[str, int, float, bool, Sequence[Union[str, int, float, bool, None]], Type[NonePartitionKeyValue]]) -> bool: # pylint: disable=line-too-long
285+
if self.kind != "MultiHash":
288286
return False
289-
return True
287+
ret = ((isinstance(partition_key, Sequence) and
288+
not isinstance(partition_key, str)) and len(self['paths']) != len(partition_key))
289+
return ret
290290

291291

292292
def _return_undefined_or_empty_partition_key(is_system_key: bool) -> Union[_Empty, _Undefined]:

0 commit comments

Comments
 (0)