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
3
4
4
- from diffsync .exceptions import ObjectNotFound , ObjectAlreadyExists
5
+ from diffsync .exceptions import ObjectNotFound
6
+
7
+ # TODO: find proper annotation for "DiffSyncModel" noqa: F821
5
8
6
9
7
10
class BaseStore :
11
+ """Reference store to be implemented in different backends."""
8
12
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."""
10
15
self .diffsync = diffsync
11
16
self .name = name if name else self .__class__ .__name__
17
+ self ._log = structlog .get_logger ().new (diffsync = self )
12
18
13
19
def __str__ (self ):
20
+ """Render store name."""
14
21
return self .name
15
22
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
+ """
17
44
raise NotImplementedError
18
45
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
+ """
20
55
raise NotImplementedError
21
56
22
57
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
+ """
25
69
raise NotImplementedError
26
70
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
+ """
28
81
raise NotImplementedError
29
82
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
+ """
31
92
raise NotImplementedError
32
93
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
+ """
34
100
raise NotImplementedError
35
101
36
102
def count (self , modelname ):
103
+ """Returns the number of elements of an specific model name."""
37
104
raise NotImplementedError
38
105
39
106
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
42
109
"""Attempt to get the object with provided identifiers or instantiate it with provided identifiers and attrs.
43
110
44
111
Args:
@@ -63,8 +130,8 @@ def get_or_instantiate(
63
130
return obj , created
64
131
65
132
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
68
135
"""Attempt to update an existing object with provided ids/attrs or instantiate it with provided identifiers and attrs.
69
136
70
137
Args:
@@ -90,158 +157,3 @@ def update_or_instantiate(
90
157
setattr (obj , attr , value )
91
158
92
159
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