1- from collections import defaultdict
2- from typing import Callable , ClassVar , Dict , List , Mapping , MutableMapping , Optional , Text , Tuple , Type , Union
1+ """BaseStore module."""
2+ from typing import Dict , List , Mapping , Text , Tuple , Type , Union
3+ import structlog # type: ignore
34
4- from diffsync .exceptions import ObjectNotFound , ObjectAlreadyExists
5+ from diffsync .exceptions import ObjectNotFound
6+
7+ # TODO: find proper annotation for "DiffSyncModel" noqa: F821
58
69
710class BaseStore :
11+ """Reference store to be implemented in different backends."""
812
9- def __init__ (self , diffsync = None , name = None , * args , ** kwargs ) -> None :
13+ def __init__ (self , diffsync = None , name = None , * args , ** kwargs ) -> None : # pylint: disable=unused-argument
14+ """Init method for BaseStore."""
1015 self .diffsync = diffsync
1116 self .name = name if name else self .__class__ .__name__
17+ self ._log = structlog .get_logger ().new (diffsync = self )
1218
1319 def __str__ (self ):
20+ """Render store name."""
1421 return self .name
1522
16- def get (self , obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]], identifier : Union [Text , Mapping ]):
23+ def get_all_model_names (self ):
24+ """Get all the model names stored.
25+
26+ Return:
27+ List[str]: List of all the model names.
28+ """
29+ raise NotImplementedError
30+
31+ def get (
32+ self , obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]], identifier : Union [Text , Mapping ] # noqa: F821
33+ ):
34+ """Get one object from the data store based on its unique id.
35+
36+ Args:
37+ obj: DiffSyncModel class or instance, or modelname string, that defines the type of the object to retrieve
38+ identifier: Unique ID of the object to retrieve, or dict of unique identifier keys/values
39+
40+ Raises:
41+ ValueError: if obj is a str and identifier is a dict (can't convert dict into a uid str without a model class)
42+ ObjectNotFound: if the requested object is not present
43+ """
1744 raise NotImplementedError
1845
19- def get_all (self , obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]]) -> List ["DiffSyncModel" ]:
46+ def get_all (self , obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]]) -> List ["DiffSyncModel" ]: # noqa: F821
47+ """Get all objects of a given type.
48+
49+ Args:
50+ obj: DiffSyncModel class or instance, or modelname string, that defines the type of the objects to retrieve
51+
52+ Returns:
53+ List[DiffSyncModel]: List of Object
54+ """
2055 raise NotImplementedError
2156
2257 def get_by_uids (
23- self , uids : List [Text ], obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]]
24- ) -> List ["DiffSyncModel" ]:
58+ self , uids : List [Text ], obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]] # noqa: F821
59+ ) -> List ["DiffSyncModel" ]: # noqa: F821
60+ """Get multiple objects from the store by their unique IDs/Keys and type.
61+
62+ Args:
63+ uids: List of unique id / key identifying object in the database.
64+ obj: DiffSyncModel class or instance, or modelname string, that defines the type of the objects to retrieve
65+
66+ Raises:
67+ ObjectNotFound: if any of the requested UIDs are not found in the store
68+ """
2569 raise NotImplementedError
2670
27- def remove (self , obj : "DiffSyncModel" , remove_children : bool = False ):
71+ def remove (self , obj : "DiffSyncModel" , remove_children : bool = False ): # noqa: F821
72+ """Remove a DiffSyncModel object from the store.
73+
74+ Args:
75+ obj (DiffSyncModel): object to remove
76+ remove_children (bool): If True, also recursively remove any children of this object
77+
78+ Raises:
79+ ObjectNotFound: if the object is not present
80+ """
2881 raise NotImplementedError
2982
30- def add (self , obj : "DiffSyncModel" ):
83+ def add (self , obj : "DiffSyncModel" ): # noqa: F821
84+ """Add a DiffSyncModel object to the store.
85+
86+ Args:
87+ obj (DiffSyncModel): Object to store
88+
89+ Raises:
90+ ObjectAlreadyExists: if a different object with the same uid is already present.
91+ """
3192 raise NotImplementedError
3293
33- def update (self , obj : "DiffSyncModel" ):
94+ def update (self , obj : "DiffSyncModel" ): # noqa: F821
95+ """Update a DiffSyncModel object to the store.
96+
97+ Args:
98+ obj (DiffSyncModel): Object to update
99+ """
34100 raise NotImplementedError
35101
36102 def count (self , modelname ):
103+ """Returns the number of elements of an specific model name."""
37104 raise NotImplementedError
38105
39106 def get_or_instantiate (
40- self , model : Type ["DiffSyncModel" ], ids : Dict , attrs : Dict = None
41- ) -> Tuple ["DiffSyncModel" , bool ]:
107+ self , model : Type ["DiffSyncModel" ], ids : Dict , attrs : Dict = None # noqa: F821
108+ ) -> Tuple ["DiffSyncModel" , bool ]: # noqa: F821
42109 """Attempt to get the object with provided identifiers or instantiate it with provided identifiers and attrs.
43110
44111 Args:
@@ -63,8 +130,8 @@ def get_or_instantiate(
63130 return obj , created
64131
65132 def update_or_instantiate (
66- self , model : Type ["DiffSyncModel" ], ids : Dict , attrs : Dict
67- ) -> Tuple ["DiffSyncModel" , bool ]:
133+ self , model : Type ["DiffSyncModel" ], ids : Dict , attrs : Dict # noqa: F821
134+ ) -> Tuple ["DiffSyncModel" , bool ]: # noqa: F821
68135 """Attempt to update an existing object with provided ids/attrs or instantiate it with provided identifiers and attrs.
69136
70137 Args:
@@ -90,158 +157,3 @@ def update_or_instantiate(
90157 setattr (obj , attr , value )
91158
92159 return obj , created
93-
94-
95- class LocalStore (BaseStore ):
96-
97- def __init__ (self , * args , ** kwargs ) -> None :
98- super ().__init__ (* args , ** kwargs )
99-
100- self ._data = defaultdict (dict )
101-
102- def get (self , obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]], identifier : Union [Text , Mapping ]):
103- """Get one object from the data store based on its unique id.
104-
105- Args:
106- obj: DiffSyncModel class or instance, or modelname string, that defines the type of the object to retrieve
107- identifier: Unique ID of the object to retrieve, or dict of unique identifier keys/values
108-
109- Raises:
110- ValueError: if obj is a str and identifier is a dict (can't convert dict into a uid str without a model class)
111- ObjectNotFound: if the requested object is not present
112- """
113- if isinstance (obj , str ):
114- modelname = obj
115- if not hasattr (self , obj ):
116- object_class = None
117- else :
118- object_class = getattr (self , obj )
119- else :
120- object_class = obj
121- modelname = obj .get_type ()
122-
123- if isinstance (identifier , str ):
124- uid = identifier
125- elif object_class :
126- uid = object_class .create_unique_id (** identifier )
127- else :
128- raise ValueError (
129- f"Invalid args: ({ obj } , { identifier } ): "
130- f"either { obj } should be a class/instance or { identifier } should be a str"
131- )
132-
133- if uid not in self ._data [modelname ]:
134- raise ObjectNotFound (f"{ modelname } { uid } not present in { str (self )} " )
135- return self ._data [modelname ][uid ]
136-
137- def get_all (self , obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]]) -> List ["DiffSyncModel" ]:
138- """Get all objects of a given type.
139-
140- Args:
141- obj: DiffSyncModel class or instance, or modelname string, that defines the type of the objects to retrieve
142-
143- Returns:
144- List[DiffSyncModel]: List of Object
145- """
146- if isinstance (obj , str ):
147- modelname = obj
148- else :
149- modelname = obj .get_type ()
150-
151- return list (self ._data [modelname ].values ())
152-
153- def get_by_uids (
154- self , uids : List [Text ], obj : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ]]
155- ) -> List ["DiffSyncModel" ]:
156- """Get multiple objects from the store by their unique IDs/Keys and type.
157-
158- Args:
159- uids: List of unique id / key identifying object in the database.
160- obj: DiffSyncModel class or instance, or modelname string, that defines the type of the objects to retrieve
161-
162- Raises:
163- ObjectNotFound: if any of the requested UIDs are not found in the store
164- """
165- if isinstance (obj , str ):
166- modelname = obj
167- else :
168- modelname = obj .get_type ()
169-
170- results = []
171- for uid in uids :
172- if uid not in self ._data [modelname ]:
173- raise ObjectNotFound (f"{ modelname } { uid } not present in { str (self )} " )
174- results .append (self ._data [modelname ][uid ])
175- return results
176-
177- def add (self , obj : "DiffSyncModel" ):
178- """Add a DiffSyncModel object to the store.
179-
180- Args:
181- obj (DiffSyncModel): Object to store
182-
183- Raises:
184- ObjectAlreadyExists: if a different object with the same uid is already present.
185- """
186- modelname = obj .get_type ()
187- uid = obj .get_unique_id ()
188-
189- existing_obj = self ._data [modelname ].get (uid )
190- if existing_obj :
191- if existing_obj is not obj :
192- raise ObjectAlreadyExists (f"Object { uid } already present" , obj )
193- # Return so we don't have to change anything on the existing object and underlying data
194- return
195-
196- if not obj .diffsync :
197- obj .diffsync = self .diffsync
198-
199- self ._data [modelname ][uid ] = obj
200-
201- def update (self , obj : "DiffSyncModel" ):
202- modelname = obj .get_type ()
203- uid = obj .get_unique_id ()
204-
205- existing_obj = self ._data [modelname ].get (uid )
206- if existing_obj is obj :
207- return
208-
209- self ._data [modelname ][uid ] = obj
210-
211- def remove (self , obj : "DiffSyncModel" , remove_children : bool = False ):
212- """Remove a DiffSyncModel object from the store.
213-
214- Args:
215- obj (DiffSyncModel): object to remove
216- remove_children (bool): If True, also recursively remove any children of this object
217-
218- Raises:
219- ObjectNotFound: if the object is not present
220- """
221- modelname = obj .get_type ()
222- uid = obj .get_unique_id ()
223-
224- if uid not in self ._data [modelname ]:
225- raise ObjectNotFound (f"{ modelname } { uid } not present in { str (self )} " )
226-
227- if obj .diffsync :
228- obj .diffsync = None
229-
230- del self ._data [modelname ][uid ]
231-
232- if remove_children :
233- for child_type , child_fieldname in obj .get_children_mapping ().items ():
234- for child_id in getattr (obj , child_fieldname ):
235- try :
236- child_obj = self .get (child_type , child_id )
237- self .remove (child_obj , remove_children = remove_children )
238- except ObjectNotFound :
239- pass
240- # Since this is "cleanup" code, log an error and continue, instead of letting the exception raise
241- # self._log.error(f"Unable to remove child {child_id} of {modelname} {uid} - not found!")
242-
243- def count (self , modelname = None ):
244- if not modelname :
245- return sum (len (entries ) for entries in self ._data .values ())
246- else :
247- return len (self ._data [modelname ])
0 commit comments