Skip to content

Commit de386d3

Browse files
andrewmathew1Andrew Mathewtvaron3annatisch
authored
Added Response Headers to Control Plane Operations (#41742)
* added response headers to control plane operations * test cleanup * corrected response headers and added return type of cosmosDict * added response headers to throughputProperties class * edited getting response headers for thread safety * added overload methods and tests for control plane operations * changed return_type to return_header boolean to simplify code * added headers for replace throughput * added create container and database if not exists negative handling and tests * changed return_headers to return_properties * added changes from git comments * returns tuple for previous container and db proxy operations, added samples * matching sync and async positional parameters * Update sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client.py Co-authored-by: Tomas Varon <[email protected]> * Update sdk/cosmos/azure-cosmos/azure/cosmos/aio/_database.py Co-authored-by: Tomas Varon <[email protected]> * added changes from pr comments * bug fix for replace_container * fixed pylint errors * fixed positional arg errors * fixed pylint errors * fixed pos args ttl test * changed back positional parameters to avoid breaking changes * fixed return typing errors * bugfixes from mypy pipeline * testing changes for mypy errors * testing type change for mypy errors * testing fix for mypy errors * database fixes for mypy errors * testing mypy/pylint fixes for overloads * adding docstring changes for overloaded functions * pylint fixes * fixing pylint errors for param types * testing changes for return value error in mypy and pylint fixes * reverting return type back to dict[str, Any] for get_client_container_caches * testing variable changes for mypy * testing changes for mypy * testing changes for mypy back to original dict * got rid of extra library import * fixed indent issue * reverted back to original type of Dict for get_properties() * minor fixes * Update sdk/cosmos/azure-cosmos/azure/cosmos/offer.py Co-authored-by: Anna Tisch <[email protected]> * made suggested changes * added suggestions for sync and async methods * added to docstring for overloaded methods * changed wording for return_properties in docstring * added suggested docstring changes * wording change for database proxy return type * minor bugfix for docstring * added to changelog --------- Co-authored-by: Andrew Mathew <[email protected]> Co-authored-by: Tomas Varon <[email protected]> Co-authored-by: Anna Tisch <[email protected]>
1 parent 7b2e6de commit de386d3

18 files changed

+1936
-125
lines changed

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
### 4.14.0b5 (Unreleased)
44

55
#### Features Added
6-
6+
* Added ability to return a tuple of a DatabaseProxy/ContainerProxy with the associated database/container properties when creating or reading databases/containers through `return_properties` parameter. See [PR 41742](https://github.com/Azure/azure-sdk-for-python/pull/41742)
77
#### Breaking Changes
88

99
#### Bugs Fixed

sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def CreateDatabase(
370370
database: Dict[str, Any],
371371
options: Optional[Mapping[str, Any]] = None,
372372
**kwargs: Any
373-
) -> Dict[str, Any]:
373+
) -> CosmosDict:
374374
"""Creates a database.
375375
376376
:param dict database:
@@ -393,7 +393,7 @@ def ReadDatabase(
393393
database_link: str,
394394
options: Optional[Mapping[str, Any]] = None,
395395
**kwargs: Any
396-
) -> Dict[str, Any]:
396+
) -> CosmosDict:
397397
"""Reads a database.
398398
399399
:param str database_link:
@@ -527,7 +527,7 @@ def CreateContainer(
527527
collection: Dict[str, Any],
528528
options: Optional[Mapping[str, Any]] = None,
529529
**kwargs: Any
530-
) -> Dict[str, Any]:
530+
) -> CosmosDict:
531531
"""Creates a collection in a database.
532532
533533
:param str database_link:
@@ -556,7 +556,7 @@ def ReplaceContainer(
556556
collection: Dict[str, Any],
557557
options: Optional[Mapping[str, Any]] = None,
558558
**kwargs: Any
559-
) -> Dict[str, Any]:
559+
) -> CosmosDict:
560560
"""Replaces a collection and return it.
561561
562562
:param str collection_link:
@@ -586,7 +586,7 @@ def ReadContainer(
586586
collection_link: str,
587587
options: Optional[Mapping[str, Any]] = None,
588588
**kwargs: Any
589-
) -> Dict[str, Any]:
589+
) -> CosmosDict:
590590
"""Reads a collection.
591591
592592
:param str collection_link:
@@ -2554,7 +2554,7 @@ def ReplaceOffer(
25542554
offer_link: str,
25552555
offer: Dict[str, Any],
25562556
**kwargs: Any
2557-
) -> Dict[str, Any]:
2557+
) -> CosmosDict:
25582558
"""Replaces an offer and returns it.
25592559
25602560
:param str offer_link:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ async def read(
172172
priority: Optional[Literal["High", "Low"]] = None,
173173
initial_headers: Optional[Dict[str, str]] = None,
174174
**kwargs: Any
175-
) -> Dict[str, Any]:
175+
) -> CosmosDict:
176176
"""Read the container properties.
177177
178178
:keyword bool populate_partition_key_range_statistics: Enable returning partition key

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

Lines changed: 178 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"""Create, read, and delete databases in the Azure Cosmos DB SQL API service.
2323
"""
2424

25-
from typing import Any, Dict, List, Optional, Union, cast, Mapping, Iterable, Callable
25+
from typing import Any, Dict, List, Optional, Union, cast, Mapping, Iterable, Callable, overload, Literal
2626
import warnings
2727
from azure.core.async_paging import AsyncItemPaged
2828
from azure.core.credentials import TokenCredential
@@ -41,6 +41,7 @@
4141
from ._database import DatabaseProxy, _get_database_link
4242
from ..documents import ConnectionPolicy, DatabaseAccount
4343
from ..exceptions import CosmosResourceNotFoundError
44+
from .._cosmos_responses import CosmosDict
4445

4546
# pylint: disable=docstring-keyword-should-match-keyword-only
4647

@@ -255,14 +256,15 @@ def from_connection_string(
255256
**kwargs
256257
)
257258

258-
@distributed_trace_async
259+
@overload
259260
async def create_database(
260261
self,
261262
id: str,
262263
*,
263264
offer_throughput: Optional[Union[int, ThroughputProperties]] = None,
264265
initial_headers: Optional[Dict[str, str]] = None,
265266
throughput_bucket: Optional[int] = None,
267+
return_properties: Literal[False] = False,
266268
**kwargs: Any
267269
) -> DatabaseProxy:
268270
"""
@@ -275,8 +277,10 @@ async def create_database(
275277
:keyword response_hook: A callable invoked with the response metadata.
276278
:keyword int throughput_bucket: The desired throughput bucket for the client
277279
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
280+
:keyword bool return_properties: Specifies whether to return either a DatabaseProxy
281+
or a Tuple containing a DatabaseProxy and the associated database properties.
278282
:raises ~azure.cosmos.exceptions.CosmosResourceExistsError: Database with the given ID already exists.
279-
:returns: A DatabaseProxy instance representing the new database.
283+
:returns: A `DatabaseProxy` instance representing the database.
280284
:rtype: ~azure.cosmos.aio.DatabaseProxy
281285
282286
.. admonition:: Example:
@@ -289,6 +293,84 @@ async def create_database(
289293
:caption: Create a database in the Cosmos DB account:
290294
:name: create_database
291295
"""
296+
...
297+
298+
@overload
299+
async def create_database(
300+
self,
301+
id: str,
302+
*,
303+
offer_throughput: Optional[Union[int, ThroughputProperties]] = None,
304+
initial_headers: Optional[Dict[str, str]] = None,
305+
throughput_bucket: Optional[int] = None,
306+
return_properties: Literal[True],
307+
**kwargs: Any
308+
) -> tuple[DatabaseProxy, CosmosDict]:
309+
"""
310+
Create a new database with the given ID (name).
311+
312+
:param str id: ID (name) of the database to create.
313+
:keyword offer_throughput: The provisioned throughput for this offer.
314+
:paramtype offer_throughput: Union[int, ~azure.cosmos.ThroughputProperties]
315+
:keyword dict[str, str] initial_headers: Initial headers to be sent as part of the request.
316+
:keyword response_hook: A callable invoked with the response metadata.
317+
:keyword int throughput_bucket: The desired throughput bucket for the client
318+
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
319+
:keyword bool return_properties: Specifies whether to return either a DatabaseProxy
320+
or a Tuple containing a DatabaseProxy and the associated database properties.
321+
:raises ~azure.cosmos.exceptions.CosmosResourceExistsError: Database with the given ID already exists.
322+
:returns: A tuple of `DatabaseProxy` and CosmosDict with the database properties.
323+
:rtype: tuple [~azure.cosmos.aio.DatabaseProxy, ~azure.cosmos.CosmosDict]
324+
325+
.. admonition:: Example:
326+
327+
.. literalinclude:: ../samples/examples_async.py
328+
:start-after: [START create_database]
329+
:end-before: [END create_database]
330+
:language: python
331+
:dedent: 0
332+
:caption: Create a database in the Cosmos DB account:
333+
:name: create_database
334+
"""
335+
...
336+
337+
@distributed_trace_async
338+
async def create_database( # pylint:disable=docstring-should-be-keyword
339+
self,
340+
*args: Any,
341+
**kwargs: Any
342+
) -> Union[DatabaseProxy, tuple[DatabaseProxy, CosmosDict]]:
343+
"""
344+
Create a new database with the given ID (name).
345+
346+
:param Any args: args
347+
:param str id: ID (name) of the database to read or create.
348+
:keyword offer_throughput: The provisioned throughput for this offer.
349+
:paramtype offer_throughput: Union[int, ~azure.cosmos.ThroughputProperties]
350+
:keyword dict[str, str] initial_headers: Initial headers to be sent as part of the request.
351+
:keyword response_hook: A callable invoked with the response metadata.
352+
:keyword int throughput_bucket: The desired throughput bucket for the client
353+
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
354+
:keyword bool return_properties: Specifies whether to return either a DatabaseProxy
355+
or a Tuple containing a DatabaseProxy and the associated database properties.
356+
:raises ~azure.cosmos.exceptions.CosmosResourceExistsError: Database with the given ID already exists.
357+
:returns: A DatabaseProxy instance representing the database or a tuple of DatabaseProxy
358+
and CosmosDict with the database properties.
359+
:rtype: ~azure.cosmos.aio.DatabaseProxy or tuple [~azure.cosmos.aio.DatabaseProxy, ~azure.cosmos.CosmosDict]
360+
361+
.. admonition:: Example:
362+
363+
.. literalinclude:: ../samples/examples_async.py
364+
:start-after: [START create_database]
365+
:end-before: [END create_database]
366+
:language: python
367+
:dedent: 0
368+
:caption: Create a database in the Cosmos DB account:
369+
:name: create_database
370+
"""
371+
id = args[0] if args else kwargs.pop("id")
372+
if len(args) > 1:
373+
raise TypeError(f"Unexpected positional parameters: {args[1:]}")
292374
session_token = kwargs.get('session_token')
293375
if session_token is not None:
294376
warnings.warn(
@@ -307,24 +389,27 @@ async def create_database(
307389
"The 'match_condition' flag does not apply to this method and is always ignored even if passed."
308390
" It will now be removed in the future.",
309391
DeprecationWarning)
310-
if initial_headers is not None:
311-
kwargs["initial_headers"] = initial_headers
312-
if throughput_bucket is not None:
313-
kwargs["throughput_bucket"] = throughput_bucket
392+
393+
offer_throughput = kwargs.pop("offer_throughput", None)
394+
return_properties = kwargs.pop("return_properties", False)
395+
314396
request_options = _build_options(kwargs)
315397
_set_throughput_options(offer=offer_throughput, request_options=request_options)
316398

317399
result = await self.client_connection.CreateDatabase(database={"id": id}, options=request_options, **kwargs)
318-
return DatabaseProxy(self.client_connection, id=result["id"], properties=result)
400+
if not return_properties:
401+
return DatabaseProxy(self.client_connection, id=result["id"], properties=result)
402+
return DatabaseProxy(self.client_connection, id=result["id"], properties=result), result
319403

320-
@distributed_trace_async
404+
@overload
321405
async def create_database_if_not_exists( # pylint: disable=redefined-builtin
322406
self,
323407
id: str,
324408
*,
325409
offer_throughput: Optional[Union[int, ThroughputProperties]] = None,
326410
initial_headers: Optional[Dict[str, str]] = None,
327411
throughput_bucket: Optional[int] = None,
412+
return_properties: Literal[False] = False,
328413
**kwargs: Any
329414
) -> DatabaseProxy:
330415
"""
@@ -343,10 +428,84 @@ async def create_database_if_not_exists( # pylint: disable=redefined-builtin
343428
:keyword response_hook: A callable invoked with the response metadata.
344429
:keyword int throughput_bucket: The desired throughput bucket for the client
345430
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
431+
:keyword bool return_properties: Specifies whether to return either a DatabaseProxy
432+
or a Tuple containing a DatabaseProxy and the associated database properties.
346433
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The database read or creation failed.
347434
:returns: A DatabaseProxy instance representing the database.
348-
:rtype: ~azure.cosmos.DatabaseProxy
435+
:rtype: ~azure.cosmos.aio.DatabaseProxy
436+
"""
437+
...
438+
439+
@overload
440+
async def create_database_if_not_exists( # pylint: disable=redefined-builtin
441+
self,
442+
id: str,
443+
*,
444+
offer_throughput: Optional[Union[int, ThroughputProperties]] = None,
445+
initial_headers: Optional[Dict[str, str]] = None,
446+
throughput_bucket: Optional[int] = None,
447+
return_properties: Literal[True],
448+
**kwargs: Any
449+
) -> tuple[DatabaseProxy, CosmosDict]:
450+
"""
451+
Create the database if it does not exist already.
452+
453+
If the database already exists, the existing settings are returned.
454+
455+
..note::
456+
This function does not check or update existing database settings or
457+
offer throughput if they differ from what is passed in.
458+
459+
:param str id: ID (name) of the database to read or create.
460+
:keyword offer_throughput: The provisioned throughput for this offer.
461+
:paramtype offer_throughput: Union[int, ~azure.cosmos.ThroughputProperties]
462+
:keyword dict[str, str] initial_headers: Initial headers to be sent as part of the request.
463+
:keyword response_hook: A callable invoked with the response metadata.
464+
:keyword int throughput_bucket: The desired throughput bucket for the client
465+
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
466+
:keyword bool return_properties: Specifies whether to return either a DatabaseProxy
467+
or a Tuple containing a DatabaseProxy and the associated database properties.
468+
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The database read or creation failed.
469+
:returns: A tuple of DatabaseProxy and CosmosDict with the database properties.
470+
:rtype: tuple [~azure.cosmos.aio.DatabaseProxy, ~azure.cosmos.CosmosDict]
471+
"""
472+
...
473+
474+
@distributed_trace_async
475+
async def create_database_if_not_exists( # pylint:disable=docstring-should-be-keyword
476+
self,
477+
*args: Any,
478+
**kwargs: Any
479+
) -> Union[DatabaseProxy, tuple[DatabaseProxy, CosmosDict]]:
349480
"""
481+
Create the database if it does not exist already.
482+
483+
If the database already exists, the existing settings are returned.
484+
485+
..note::
486+
This function does not check or update existing database settings or
487+
offer throughput if they differ from what is passed in.
488+
489+
:param Any args: args
490+
:param str id: ID (name) of the database to read or create.
491+
:keyword offer_throughput: The provisioned throughput for this offer.
492+
:paramtype offer_throughput: Union[int, ~azure.cosmos.ThroughputProperties]
493+
:keyword dict[str, str] initial_headers: Initial headers to be sent as part of the request.
494+
:keyword response_hook: A callable invoked with the response metadata.
495+
:keyword int throughput_bucket: The desired throughput bucket for the client
496+
:paramtype response_hook: Callable[[Dict[str, str], Dict[str, Any]], None]
497+
:keyword bool return_properties: Specifies whether to return either a DatabaseProxy
498+
or a Tuple containing a DatabaseProxy and the associated database properties.
499+
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: The database read or creation failed.
500+
:returns: A DatabaseProxy instance representing the database or a tuple of DatabaseProxy
501+
and CosmosDict with the database properties.
502+
:rtype: ~azure.cosmos.aio.DatabaseProxy or tuple [~azure.cosmos.aio.DatabaseProxy, ~azure.cosmos.CosmosDict]
503+
"""
504+
505+
id = args[0] if args else kwargs.pop("id")
506+
if len(args) > 1:
507+
raise TypeError(f"Unexpected positional parameters: {args[1:]}")
508+
350509
session_token = kwargs.get('session_token')
351510
if session_token is not None:
352511
warnings.warn(
@@ -365,18 +524,21 @@ async def create_database_if_not_exists( # pylint: disable=redefined-builtin
365524
"The 'match_condition' flag does not apply to this method and is always ignored even if passed."
366525
" It will now be removed in the future.",
367526
DeprecationWarning)
368-
if throughput_bucket is not None:
369-
kwargs["throughput_bucket"] = throughput_bucket
370-
if initial_headers is not None:
371-
kwargs["initial_headers"] = initial_headers
527+
528+
offer_throughput = kwargs.pop("offer_throughput", None)
529+
return_properties = kwargs.pop("return_properties", False)
530+
372531
try:
373532
database_proxy = self.get_database_client(id)
374-
await database_proxy.read(**kwargs)
375-
return database_proxy
533+
result = await database_proxy.read(**kwargs)
534+
if not return_properties:
535+
return database_proxy
536+
return database_proxy, result
376537
except CosmosResourceNotFoundError:
377538
return await self.create_database(
378539
id,
379540
offer_throughput=offer_throughput,
541+
return_properties=return_properties,
380542
**kwargs
381543
)
382544

0 commit comments

Comments
 (0)