11import dataclasses
2+ import logging
23import uuid
34from typing import Callable
45
56import azure .cosmos .cosmos_client as cosmos_client
67import azure .cosmos .exceptions as exceptions
7- from azure .cosmos import ContainerProxy
8+ from azure .cosmos import ContainerProxy , PartitionKey
89from flask import Flask
910
1011
1112class CosmosDBFacade :
12- def __init__ (self , app : Flask ): # pragma: no cover
13- self .app = app
13+ def __init__ (self , client , db_id : str , logger = None ): # pragma: no cover
14+ self .client = client
15+ self .db = self .client .get_database_client (db_id )
16+ if logger is None :
17+ self .logger = logging .getLogger (CosmosDBFacade .__name__ )
18+ else :
19+ self .logger = logger
1420
15- db_uri = app .config .get ('DATABASE_URI' )
21+ @classmethod
22+ def from_flask_config (cls , app : Flask ):
23+ db_uri = app .config .get ('COSMOS_DATABASE_URI' )
1624 if db_uri is None :
17- app .logger .warn ("DATABASE_URI was not found. Looking for alternative variables." )
25+ app .logger .warn ("COSMOS_DATABASE_URI was not found. Looking for alternative variables." )
1826 account_uri = app .config .get ('DATABASE_ACCOUNT_URI' )
1927 if account_uri is None :
2028 raise EnvironmentError ("DATABASE_ACCOUNT_URI is not defined in the environment" )
@@ -23,31 +31,26 @@ def __init__(self, app: Flask): # pragma: no cover
2331 if master_key is None :
2432 raise EnvironmentError ("DATABASE_MASTER_KEY is not defined in the environment" )
2533
26- self . client = cosmos_client .CosmosClient (account_uri , {'masterKey' : master_key },
27- user_agent = "CosmosDBDotnetQuickstart" ,
28- user_agent_overwrite = True )
34+ client = cosmos_client .CosmosClient (account_uri , {'masterKey' : master_key },
35+ user_agent = "CosmosDBDotnetQuickstart" ,
36+ user_agent_overwrite = True )
2937 else :
30- self . client = cosmos_client .CosmosClient .from_connection_string (db_uri )
38+ client = cosmos_client .CosmosClient .from_connection_string (db_uri )
3139
3240 db_id = app .config .get ('DATABASE_NAME' )
3341 if db_id is None :
3442 raise EnvironmentError ("DATABASE_NAME is not defined in the environment" )
3543
36- self . db = self . client . get_database_client ( db_id )
44+ return cls ( client , db_id , logger = app . logger )
3745
3846 def create_container (self , container_definition : dict ):
39- try :
40- return self .db .create_container (** container_definition )
47+ return self .db .create_container (** container_definition )
4148
42- except exceptions . CosmosResourceExistsError : # pragma: no cover
43- self .app . logger . info ( 'Container with id \' {0} \' was found' . format ( container_definition [ "id" ]) )
49+ def create_container_if_not_exists ( self , container_definition : dict ):
50+ return self .db . create_container_if_not_exists ( ** container_definition )
4451
4552 def delete_container (self , container_id : str ):
46- try :
47- return self .db .delete_container (container_id )
48-
49- except exceptions .CosmosHttpResponseError : # pragma: no cover
50- self .app .logger .info ('Container with id \' {0}\' was not deleted' .format (container_id ))
53+ return self .db .delete_container (container_id )
5154
5255
5356cosmos_helper : CosmosDBFacade = None
@@ -61,8 +64,13 @@ def __init__(self, data):
6164 setattr (self , k , v )
6265
6366
67+ def partition_key_attribute (pk : PartitionKey ) -> str :
68+ return pk .path .strip ('/' )
69+
70+
6471class CosmosDBRepository :
6572 def __init__ (self , container_id : str ,
73+ partition_key_attribute : str ,
6674 mapper : Callable = None ,
6775 custom_cosmos_helper : CosmosDBFacade = None ):
6876 global cosmos_helper
@@ -71,12 +79,16 @@ def __init__(self, container_id: str,
7179 raise ValueError ("The cosmos_db module has not been initialized!" )
7280 self .mapper = mapper
7381 self .container : ContainerProxy = self .cosmos_helper .db .get_container_client (container_id )
82+ self .partition_key_attribute : str = partition_key_attribute
7483
7584 @classmethod
7685 def from_definition (cls , container_definition : dict ,
7786 mapper : Callable = None ,
7887 custom_cosmos_helper : CosmosDBFacade = None ):
79- return cls (container_definition ['id' ], mapper , custom_cosmos_helper )
88+ pk_attrib = partition_key_attribute (container_definition ['partition_key' ])
89+ return cls (container_definition ['id' ], pk_attrib ,
90+ mapper = mapper ,
91+ custom_cosmos_helper = custom_cosmos_helper )
8092
8193 def create (self , data : dict , mapper : Callable = None ):
8294 function_mapper = self .get_mapper_or_dict (mapper )
@@ -93,11 +105,12 @@ def find_all(self, partition_key_value: str, max_count=None, offset=0,
93105 max_count = self .get_page_size_or (max_count )
94106 result = self .container .query_items (
95107 query = """
96- SELECT * FROM c WHERE c.tenant_id=@tenant_id AND {visibility_condition}
108+ SELECT * FROM c WHERE c.{partition_key_attribute}=@partition_key_value AND {visibility_condition}
97109 OFFSET @offset LIMIT @max_count
98- """ .format (visibility_condition = self .create_sql_condition_for_visibility (visible_only )),
110+ """ .format (partition_key_attribute = self .partition_key_attribute ,
111+ visibility_condition = self .create_sql_condition_for_visibility (visible_only )),
99112 parameters = [
100- {"name" : "@tenant_id " , "value" : partition_key_value },
113+ {"name" : "@partition_key_value " , "value" : partition_key_value },
101114 {"name" : "@offset" , "value" : offset },
102115 {"name" : "@max_count" , "value" : max_count },
103116 ],
@@ -122,6 +135,9 @@ def delete(self, id: str, partition_key_value: str, mapper: Callable = None):
122135 'deleted' : str (uuid .uuid4 ())
123136 }, partition_key_value , visible_only = True , mapper = mapper )
124137
138+ def delete_permanently (self , id : str , partition_key_value : str ) -> None :
139+ self .container .delete_item (id , partition_key_value )
140+
125141 def check_visibility (self , item , throw_not_found_if_deleted ):
126142 if throw_not_found_if_deleted and item .get ('deleted' ) is not None :
127143 raise exceptions .CosmosResourceNotFoundError (message = 'Deleted item' ,
@@ -146,4 +162,4 @@ def get_page_size_or(self, custom_page_size: int) -> int:
146162
147163def init_app (app : Flask ) -> None :
148164 global cosmos_helper
149- cosmos_helper = CosmosDBFacade (app )
165+ cosmos_helper = CosmosDBFacade . from_flask_config (app )
0 commit comments