diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index e2cdbc414439..d25e3b97934b 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -1,13 +1,16 @@ ## 4.0.1 (Unreleased) - Added deprecation warning for "lazy" indexing mode. The backend no longer allows creating containers with this mode and will set them to consistent instead. -- Fix for bug where options headers were not added to upsert_item function. Issue #11791 - thank you @aalapatirvbd. -- Fixed error raised when a non string ID is used in an item. It now raises TypeError rather than AttributeError. Issue #11793 - thank you @Rabbit994. -- Fixed #12570 - Thanks @sl-sandy. -** Bug fixes ** +**New features** +- Added the ability to set the analytical storage TTL when creating a new container. + +**Bug fixes** - Fixed support for dicts as inputs for get_client APIs. - Fixed Python 2/3 compatibility in query iterators. +- Fixed type hint error. Issue #12570 - Thanks @sl-sandy. +- Fixed bug where options headers were not added to upsert_item function. Issue #11791 - thank you @aalapatirvbd. +- Fixed error raised when a non string ID is used in an item. It now raises TypeError rather than AttributeError. Issue #11793 - thank you @Rabbit994. ## 4.0.0 (2020-05-20) @@ -247,4 +250,3 @@ Version 4.0.0b1 is the first preview of our efforts to create a user-friendly an - Supports proxy connection - diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/database.py b/sdk/cosmos/azure-cosmos/azure/cosmos/database.py index e69ab1f251e7..bd0798128770 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/database.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/database.py @@ -177,6 +177,9 @@ def create_container( has changed, and act according to the condition specified by the `match_condition` parameter. :keyword ~azure.core.MatchConditions match_condition: The match condition to use upon the etag. :keyword Callable response_hook: A callable invoked with the response metadata. + :keyword analytical_storage_ttl: Analytical store time to live (TTL) for items in the container. A value of + None leaves analytical storage off and a value of -1 turns analytical storage on with no TTL. Please + note that analytical storage can only be enabled on Synapse Link enabled accounts. :returns: A `ContainerProxy` instance representing the new container. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The container creation failed. :rtype: ~azure.cosmos.ContainerProxy @@ -216,6 +219,10 @@ def create_container( if conflict_resolution_policy is not None: definition["conflictResolutionPolicy"] = conflict_resolution_policy + analytical_storage_ttl = kwargs.pop("analytical_storage_ttl", None) + if analytical_storage_ttl is not None: + definition["analyticalStorageTtl"] = analytical_storage_ttl + request_options = build_options(kwargs) response_hook = kwargs.pop('response_hook', None) if populate_query_metrics is not None: @@ -266,11 +273,15 @@ def create_container_if_not_exists( has changed, and act according to the condition specified by the `match_condition` parameter. :keyword ~azure.core.MatchConditions match_condition: The match condition to use upon the etag. :keyword Callable response_hook: A callable invoked with the response metadata. + :keyword analytical_storage_ttl: Analytical store time to live (TTL) for items in the container. A value of + None leaves analytical storage off and a value of -1 turns analytical storage on with no TTL. Please + note that analytical storage can only be enabled on Synapse Link enabled accounts. :returns: A `ContainerProxy` instance representing the container. :raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The container read or creation failed. :rtype: ~azure.cosmos.ContainerProxy """ + analytical_storage_ttl = kwargs.pop("analytical_storage_ttl", None) try: container_proxy = self.get_container_client(id) container_proxy.read( @@ -287,7 +298,8 @@ def create_container_if_not_exists( populate_query_metrics=populate_query_metrics, offer_throughput=offer_throughput, unique_key_policy=unique_key_policy, - conflict_resolution_policy=conflict_resolution_policy + conflict_resolution_policy=conflict_resolution_policy, + analytical_storage_ttl=analytical_storage_ttl ) @distributed_trace diff --git a/sdk/cosmos/azure-cosmos/test/test_crud.py b/sdk/cosmos/azure-cosmos/test/test_crud.py index 977120df66f2..0a1a75cfebc9 100644 --- a/sdk/cosmos/azure-cosmos/test/test_crud.py +++ b/sdk/cosmos/azure-cosmos/test/test_crud.py @@ -2605,6 +2605,71 @@ def test_get_resource_with_dictionary_and_object(self): read_permission = created_user.get_permission(created_permission.properties) self.assertEqual(read_permission.id, created_permission.id) + # Temporarily commenting analytical storage tests until emulator support comes. + # def test_create_container_with_analytical_store_off(self): + # # don't run test, for the time being, if running against the emulator + # if 'localhost' in self.host or '127.0.0.1' in self.host: + # return + + # created_db = self.databaseForTest + # collection_id = 'test_create_container_with_analytical_store_off_' + str(uuid.uuid4()) + # collection_indexing_policy = {'indexingMode': 'consistent'} + # created_recorder = RecordDiagnostics() + # created_collection = created_db.create_container(id=collection_id, + # indexing_policy=collection_indexing_policy, + # partition_key=PartitionKey(path="/pk", kind="Hash"), + # response_hook=created_recorder) + # properties = created_collection.read() + # ttl_key = "analyticalStorageTtl" + # self.assertTrue(ttl_key not in properties or properties[ttl_key] == None) + + # def test_create_container_with_analytical_store_on(self): + # # don't run test, for the time being, if running against the emulator + # if 'localhost' in self.host or '127.0.0.1' in self.host: + # return + + # created_db = self.databaseForTest + # collection_id = 'test_create_container_with_analytical_store_on_' + str(uuid.uuid4()) + # collection_indexing_policy = {'indexingMode': 'consistent'} + # created_recorder = RecordDiagnostics() + # created_collection = created_db.create_container(id=collection_id, + # analytical_storage_ttl=-1, + # indexing_policy=collection_indexing_policy, + # partition_key=PartitionKey(path="/pk", kind="Hash"), + # response_hook=created_recorder) + # properties = created_collection.read() + # ttl_key = "analyticalStorageTtl" + # self.assertTrue(ttl_key in properties and properties[ttl_key] == -1) + + # def test_create_container_if_not_exists_with_analytical_store_on(self): + # # don't run test, for the time being, if running against the emulator + # if 'localhost' in self.host or '127.0.0.1' in self.host: + # return + + # # first, try when we know the container doesn't exist. + # created_db = self.databaseForTest + # collection_id = 'test_create_container_if_not_exists_with_analytical_store_on_' + str(uuid.uuid4()) + # collection_indexing_policy = {'indexingMode': 'consistent'} + # created_recorder = RecordDiagnostics() + # created_collection = created_db.create_container_if_not_exists(id=collection_id, + # analytical_storage_ttl=-1, + # indexing_policy=collection_indexing_policy, + # partition_key=PartitionKey(path="/pk", kind="Hash"), + # response_hook=created_recorder) + # properties = created_collection.read() + # ttl_key = "analyticalStorageTtl" + # self.assertTrue(ttl_key in properties and properties[ttl_key] == -1) + + # # next, try when we know the container DOES exist. This way both code paths are tested. + # created_collection = created_db.create_container_if_not_exists(id=collection_id, + # analytical_storage_ttl=-1, + # indexing_policy=collection_indexing_policy, + # partition_key=PartitionKey(path="/pk", kind="Hash"), + # response_hook=created_recorder) + # properties = created_collection.read() + # ttl_key = "analyticalStorageTtl" + # self.assertTrue(ttl_key in properties and properties[ttl_key] == -1) + def _MockExecuteFunction(self, function, *args, **kwargs): self.last_headers.append(args[4].headers[HttpHeaders.PartitionKey] if HttpHeaders.PartitionKey in args[4].headers else '')