0
# Model Definition
1
2
Core functionality for defining data models that represent your domain objects. Models specify unique identifiers, trackable attributes, and parent-child relationships between different object types.
3
4
## Capabilities
5
6
### DiffSyncModel Base Class
7
8
Base class for all DiffSync object models. Inherits from Pydantic's BaseModel and provides the foundation for defining structured data models with diffing and syncing capabilities.
9
10
```python { .api }
11
class DiffSyncModel(BaseModel):
12
"""Base class for all DiffSync object models."""
13
14
_modelname: ClassVar[str] = "diffsyncmodel"
15
_identifiers: ClassVar[Tuple[str, ...]] = ()
16
_shortname: ClassVar[Tuple[str, ...]] = ()
17
_attributes: ClassVar[Tuple[str, ...]] = ()
18
_children: ClassVar[Dict[str, str]] = {}
19
20
model_flags: DiffSyncModelFlags = DiffSyncModelFlags.NONE
21
adapter: Optional["Adapter"] = None
22
23
model_config = ConfigDict(arbitrary_types_allowed=True)
24
```
25
26
#### Usage Example
27
28
```python
29
from diffsync import DiffSyncModel
30
31
class Device(DiffSyncModel):
32
_modelname = "device"
33
_identifiers = ("name", "site")
34
_attributes = ("os_version", "vendor", "model")
35
_children = {"interface": "interfaces"}
36
37
name: str
38
site: str
39
os_version: str
40
vendor: str
41
model: str
42
interfaces: List[str] = []
43
44
class Interface(DiffSyncModel):
45
_modelname = "interface"
46
_identifiers = ("device_name", "name")
47
_attributes = ("ip_address", "status")
48
49
device_name: str
50
name: str
51
ip_address: str
52
status: str
53
```
54
55
### Model Class Variables
56
57
Class-level configuration that defines the structure and behavior of DiffSync models.
58
59
```python { .api }
60
_modelname: ClassVar[str]
61
```
62
63
Name of this model, used by DiffSync to store and look up instances. Lowercase by convention, typically corresponds to the class name.
64
65
```python { .api }
66
_identifiers: ClassVar[Tuple[str, ...]]
67
```
68
69
List of model fields which together uniquely identify an instance. This identifier must be globally unique among all instances of this class.
70
71
```python { .api }
72
_shortname: ClassVar[Tuple[str, ...]]
73
```
74
75
Optional list of model fields that together form a shorter identifier. Must be locally unique but doesn't need to be globally unique among all instances.
76
77
```python { .api }
78
_attributes: ClassVar[Tuple[str, ...]]
79
```
80
81
Optional list of additional model fields (beyond identifiers) that are relevant for diff calculation. Only fields in `_attributes` and `_children` are considered for diff purposes.
82
83
```python { .api }
84
_children: ClassVar[Dict[str, str]]
85
```
86
87
Optional dictionary mapping child model names to field names for storing child model references. Format: `{modelname: field_name}`.
88
89
### Instance Attributes
90
91
Runtime attributes that control model behavior and maintain state during operations.
92
93
```python { .api }
94
model_flags: DiffSyncModelFlags
95
```
96
97
Optional behavioral flags for this DiffSyncModel. Can be set as class attribute or instance attribute.
98
99
```python { .api }
100
adapter: Optional["Adapter"]
101
```
102
103
The Adapter instance that owns this model instance. Set automatically when models are added to adapters.
104
105
### CRUD Operations
106
107
Methods for creating, updating, and deleting model instances with platform-specific data operations.
108
109
```python { .api }
110
@classmethod
111
def create(cls, adapter: "Adapter", ids: Dict, attrs: Dict) -> Optional[Self]:
112
"""
113
Instantiate this class with platform-specific data creation.
114
115
Args:
116
adapter: The master data store for other DiffSyncModel instances
117
ids: Dictionary of unique-identifiers needed to create the new object
118
attrs: Dictionary of additional attributes to set on the new object
119
120
Returns:
121
DiffSyncModel instance if creation successful, None if failed
122
123
Raises:
124
ObjectNotCreated: if an error occurred
125
"""
126
```
127
128
```python { .api }
129
def update(self, attrs: Dict) -> Optional[Self]:
130
"""
131
Update the attributes of this instance with platform-specific data updates.
132
133
Args:
134
attrs: Dictionary of attributes to update on the object
135
136
Returns:
137
DiffSyncModel instance if update successful, None if failed
138
139
Raises:
140
ObjectNotUpdated: if an error occurred
141
"""
142
```
143
144
```python { .api }
145
def delete(self) -> Optional[Self]:
146
"""
147
Delete any platform-specific data corresponding to this instance.
148
149
Returns:
150
DiffSyncModel instance if deletion successful, None if failed
151
152
Raises:
153
ObjectNotDeleted: if an error occurred
154
"""
155
```
156
157
#### CRUD Usage Example
158
159
```python
160
class NetworkDevice(DiffSyncModel):
161
_modelname = "device"
162
_identifiers = ("name",)
163
_attributes = ("ip_address", "os_version")
164
165
name: str
166
ip_address: str
167
os_version: str
168
169
@classmethod
170
def create(cls, adapter, ids, attrs):
171
# Create device in actual network system
172
device = super().create(adapter, ids, attrs)
173
if device:
174
# Perform actual device provisioning
175
success = provision_device(device.name, device.ip_address)
176
if success:
177
device.set_status(DiffSyncStatus.SUCCESS, "Device provisioned")
178
else:
179
device.set_status(DiffSyncStatus.FAILURE, "Failed to provision")
180
return device
181
182
def update(self, attrs):
183
# Update device in actual network system
184
old_ip = self.ip_address
185
device = super().update(attrs)
186
if device and 'ip_address' in attrs:
187
# Perform actual IP address change
188
success = update_device_ip(self.name, old_ip, self.ip_address)
189
if success:
190
device.set_status(DiffSyncStatus.SUCCESS, "IP updated")
191
else:
192
device.set_status(DiffSyncStatus.FAILURE, "Failed to update IP")
193
return device
194
195
def delete(self):
196
# Delete device from actual network system
197
success = deprovision_device(self.name)
198
device = super().delete()
199
if success:
200
device.set_status(DiffSyncStatus.SUCCESS, "Device deprovisioned")
201
else:
202
device.set_status(DiffSyncStatus.FAILURE, "Failed to deprovision")
203
return device
204
```
205
206
### Model Inspection Methods
207
208
Methods for retrieving model metadata and current state information.
209
210
```python { .api }
211
@classmethod
212
def get_type(cls) -> str:
213
"""Return the type/modelname of the object or the class."""
214
```
215
216
```python { .api }
217
@classmethod
218
def create_unique_id(cls, **identifiers: Dict[str, Any]) -> str:
219
"""
220
Construct a unique identifier for this model class.
221
222
Args:
223
**identifiers: Dict of identifiers and their values, as in get_identifiers()
224
"""
225
```
226
227
```python { .api }
228
def get_identifiers(self) -> Dict:
229
"""Get a dict of all identifiers (primary keys) and their values for this object."""
230
```
231
232
```python { .api }
233
def get_attrs(self) -> Dict:
234
"""Get all the non-primary-key attributes or parameters for this object."""
235
```
236
237
```python { .api }
238
def get_unique_id(self) -> str:
239
"""Get the unique ID of an object."""
240
```
241
242
```python { .api }
243
def get_shortname(self) -> str:
244
"""Get the (not guaranteed-unique) shortname of an object, if any."""
245
```
246
247
```python { .api }
248
def get_status(self) -> Tuple[DiffSyncStatus, str]:
249
"""Get the status of the last create/update/delete operation on this object, and any associated message."""
250
```
251
252
### Child Relationship Management
253
254
Methods for managing parent-child relationships between model instances.
255
256
```python { .api }
257
def add_child(self, child: "DiffSyncModel") -> None:
258
"""
259
Add a child reference to an object.
260
261
The child object isn't stored, only its unique id.
262
The name of the target attribute is defined in _children per object type.
263
264
Raises:
265
ObjectStoreWrongType: if the type is not part of _children
266
ObjectAlreadyExists: if the unique id is already stored
267
"""
268
```
269
270
```python { .api }
271
def remove_child(self, child: "DiffSyncModel") -> None:
272
"""
273
Remove a child reference from an object.
274
275
Raises:
276
ObjectStoreWrongType: if the child model type is not part of _children
277
ObjectNotFound: if the child wasn't previously present
278
"""
279
```
280
281
### Status Management
282
283
Methods for tracking and reporting the status of operations performed on model instances.
284
285
```python { .api }
286
def set_status(self, status: DiffSyncStatus, message: str = "") -> None:
287
"""Update the status (and optionally status message) of this model in response to a create/update/delete call."""
288
```
289
290
### Serialization Methods
291
292
Methods for converting model instances to various serializable formats.
293
294
```python { .api }
295
def dict(self, **kwargs: Any) -> Dict:
296
"""Convert this DiffSyncModel to a dict, excluding the adapter field by default as it is not serializable."""
297
```
298
299
```python { .api }
300
def json(self, **kwargs: Any) -> str:
301
"""Convert this DiffSyncModel to a JSON string, excluding the adapter field by default as it is not serializable."""
302
```
303
304
```python { .api }
305
def str(self, include_children: bool = True, indent: int = 0) -> str:
306
"""Build a detailed string representation of this DiffSyncModel and optionally its children."""
307
```
308
309
## Types
310
311
```python { .api }
312
from enum import Enum
313
from typing import ClassVar, Dict, List, Optional, Tuple, Type, Union
314
315
class DiffSyncStatus(Enum):
316
UNKNOWN = "unknown"
317
SUCCESS = "success"
318
FAILURE = "failure"
319
ERROR = "error"
320
```