or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-management.mddiff-calculation.mdflags-configuration.mdindex.mdmodel-definition.mdstorage-backends.mdsynchronization.md

flags-configuration.mddocs/

0

# Flags and Configuration

1

2

Behavioral control flags and configuration options for customizing diff calculation and synchronization behavior, including error handling, skipping patterns, and logging verbosity.

3

4

## Capabilities

5

6

### DiffSyncFlags

7

8

Flags that can be passed to sync_* or diff_* calls to affect their behavior.

9

10

```python { .api }

11

class DiffSyncFlags(enum.Flag):

12

"""Flags that can be passed to a sync_* or diff_* call to affect its behavior."""

13

14

NONE = 0

15

CONTINUE_ON_FAILURE = 0b1

16

SKIP_UNMATCHED_SRC = 0b10

17

SKIP_UNMATCHED_DST = 0b100

18

SKIP_UNMATCHED_BOTH = SKIP_UNMATCHED_SRC | SKIP_UNMATCHED_DST

19

LOG_UNCHANGED_RECORDS = 0b1000

20

```

21

22

#### Flag Descriptions

23

24

```python { .api }

25

NONE = 0

26

```

27

No special flags - default behavior.

28

29

```python { .api }

30

CONTINUE_ON_FAILURE = 0b1

31

```

32

Continue synchronizing even if failures are encountered when syncing individual models. Without this flag, any failure will stop the entire sync operation.

33

34

```python { .api }

35

SKIP_UNMATCHED_SRC = 0b10

36

```

37

Ignore objects that only exist in the source/"from" DiffSync when determining diffs and syncing. If this flag is set, no new objects will be created in the target/"to" DiffSync.

38

39

```python { .api }

40

SKIP_UNMATCHED_DST = 0b100

41

```

42

Ignore objects that only exist in the target/"to" DiffSync when determining diffs and syncing. If this flag is set, no objects will be deleted from the target/"to" DiffSync.

43

44

```python { .api }

45

SKIP_UNMATCHED_BOTH = SKIP_UNMATCHED_SRC | SKIP_UNMATCHED_DST

46

```

47

Combination flag - ignore objects that exist only in source OR only in target. Only update existing objects that are present in both.

48

49

```python { .api }

50

LOG_UNCHANGED_RECORDS = 0b1000

51

```

52

If this flag is set, a log message will be generated during synchronization for each model, even unchanged ones. By default, only models that have actual changes to synchronize will be logged. This flag is off by default to reduce verbosity but can be enabled for debugging.

53

54

#### DiffSyncFlags Usage Examples

55

56

```python

57

from diffsync import DiffSyncFlags

58

59

# Basic synchronization with default behavior

60

diff = target.sync_from(source)

61

62

# Continue sync even if some operations fail

63

diff = target.sync_from(source, flags=DiffSyncFlags.CONTINUE_ON_FAILURE)

64

65

# Only update existing objects, don't create new ones

66

diff = target.sync_from(source, flags=DiffSyncFlags.SKIP_UNMATCHED_SRC)

67

68

# Only update existing objects, don't delete missing ones

69

diff = target.sync_from(source, flags=DiffSyncFlags.SKIP_UNMATCHED_DST)

70

71

# Only update objects that exist in both source and target

72

diff = target.sync_from(source, flags=DiffSyncFlags.SKIP_UNMATCHED_BOTH)

73

74

# Enable verbose logging for debugging

75

diff = target.sync_from(source, flags=DiffSyncFlags.LOG_UNCHANGED_RECORDS)

76

77

# Combine multiple flags using bitwise OR

78

diff = target.sync_from(source,

79

flags=DiffSyncFlags.CONTINUE_ON_FAILURE | DiffSyncFlags.LOG_UNCHANGED_RECORDS)

80

```

81

82

### DiffSyncModelFlags

83

84

Flags that can be set on a DiffSyncModel class or instance to affect its usage during diff and sync operations.

85

86

```python { .api }

87

class DiffSyncModelFlags(enum.Flag):

88

"""Flags that can be set on a DiffSyncModel class or instance to affect its usage."""

89

90

NONE = 0

91

IGNORE = 0b1

92

SKIP_CHILDREN_ON_DELETE = 0b10

93

SKIP_UNMATCHED_SRC = 0b100

94

SKIP_UNMATCHED_DST = 0b1000

95

NATURAL_DELETION_ORDER = 0b10000

96

SKIP_UNMATCHED_BOTH = SKIP_UNMATCHED_SRC | SKIP_UNMATCHED_DST

97

```

98

99

#### Model Flag Descriptions

100

101

```python { .api }

102

NONE = 0

103

```

104

No special flags - default behavior.

105

106

```python { .api }

107

IGNORE = 0b1

108

```

109

Do not render diffs containing this model; do not make any changes to this model when synchronizing. Can be used to indicate a model instance that exists but should not be changed by DiffSync.

110

111

```python { .api }

112

SKIP_CHILDREN_ON_DELETE = 0b10

113

```

114

When deleting this model, do not recursively delete its children. Can be used for the case where deletion of a model results in the automatic deletion of all its children.

115

116

```python { .api }

117

SKIP_UNMATCHED_SRC = 0b100

118

```

119

Ignore the model if it only exists in the source/"from" DiffSync when determining diffs and syncing. If this flag is set, no new model will be created in the target/"to" DiffSync.

120

121

```python { .api }

122

SKIP_UNMATCHED_DST = 0b1000

123

```

124

Ignore the model if it only exists in the target/"to" DiffSync when determining diffs and syncing. If this flag is set, the model will not be deleted from the target/"to" DiffSync.

125

126

```python { .api }

127

NATURAL_DELETION_ORDER = 0b10000

128

```

129

When deleting, delete children before instances of this element. If this flag is set, the model's children will be deleted from the target/"to" DiffSync before the model instances themselves.

130

131

```python { .api }

132

SKIP_UNMATCHED_BOTH = SKIP_UNMATCHED_SRC | SKIP_UNMATCHED_DST

133

```

134

Combination flag - ignore the model if it exists only in source OR only in target.

135

136

#### DiffSyncModelFlags Usage Examples

137

138

```python

139

from diffsync import DiffSyncModel, DiffSyncModelFlags

140

141

# Set flags as class attribute

142

class ReadOnlyDevice(DiffSyncModel):

143

_modelname = "readonly_device"

144

_identifiers = ("name",)

145

_attributes = ("status",)

146

147

# This model will be ignored during sync operations

148

model_flags = DiffSyncModelFlags.IGNORE

149

150

name: str

151

status: str

152

153

# Set flags dynamically on instance

154

device = Device(name="critical_device", vendor="cisco")

155

device.model_flags = DiffSyncModelFlags.IGNORE

156

157

# Model that automatically deletes children when deleted

158

class Site(DiffSyncModel):

159

_modelname = "site"

160

_identifiers = ("name",)

161

_children = {"device": "devices"}

162

163

# When site is deleted, devices are automatically removed by the system

164

model_flags = DiffSyncModelFlags.SKIP_CHILDREN_ON_DELETE

165

166

name: str

167

devices: List[str] = []

168

169

# Model with natural deletion order

170

class Database(DiffSyncModel):

171

_modelname = "database"

172

_identifiers = ("name",)

173

_children = {"table": "tables"}

174

175

# Delete tables before deleting database

176

model_flags = DiffSyncModelFlags.NATURAL_DELETION_ORDER

177

178

name: str

179

tables: List[str] = []

180

181

# Conditional flags based on instance state

182

class Device(DiffSyncModel):

183

_modelname = "device"

184

_identifiers = ("name",)

185

_attributes = ("status", "maintenance_mode")

186

187

name: str

188

status: str

189

maintenance_mode: bool = False

190

191

def __post_init__(self):

192

# Don't sync devices in maintenance mode

193

if self.maintenance_mode:

194

self.model_flags = DiffSyncModelFlags.IGNORE

195

```

196

197

### DiffSyncStatus

198

199

Enumeration of status values that can be set on a DiffSyncModel's status to indicate the result of create/update/delete operations.

200

201

```python { .api }

202

class DiffSyncStatus(enum.Enum):

203

"""Flag values to set as a DiffSyncModel's _status when performing a sync; values are logged by DiffSyncSyncer."""

204

205

UNKNOWN = "unknown"

206

SUCCESS = "success"

207

FAILURE = "failure"

208

ERROR = "error"

209

```

210

211

#### Status Usage Examples

212

213

```python

214

from diffsync import DiffSyncStatus

215

216

class NetworkDevice(DiffSyncModel):

217

_modelname = "device"

218

_identifiers = ("name",)

219

_attributes = ("ip_address",)

220

221

name: str

222

ip_address: str

223

224

@classmethod

225

def create(cls, adapter, ids, attrs):

226

device = super().create(adapter, ids, attrs)

227

228

try:

229

# Attempt to configure device

230

result = configure_network_device(device.name, device.ip_address)

231

if result.success:

232

device.set_status(DiffSyncStatus.SUCCESS, "Device configured successfully")

233

else:

234

device.set_status(DiffSyncStatus.FAILURE, f"Configuration failed: {result.error}")

235

except Exception as e:

236

device.set_status(DiffSyncStatus.ERROR, f"Unexpected error: {e}")

237

238

return device

239

240

def update(self, attrs):

241

device = super().update(attrs)

242

243

if 'ip_address' in attrs:

244

try:

245

update_device_ip(self.name, self.ip_address)

246

device.set_status(DiffSyncStatus.SUCCESS, "IP address updated")

247

except ValidationError:

248

device.set_status(DiffSyncStatus.FAILURE, "Invalid IP address")

249

except NetworkError as e:

250

device.set_status(DiffSyncStatus.ERROR, f"Network error: {e}")

251

252

return device

253

254

# Check status after sync operations

255

diff = target.sync_from(source)

256

for element in diff.get_children():

257

if element.action:

258

try:

259

obj = target.get(element.type, element.keys)

260

status, message = obj.get_status()

261

print(f"{element.type} {element.name}: {status.value} - {message}")

262

except ObjectNotFound:

263

print(f"{element.type} {element.name}: Object not found after sync")

264

```

265

266

### Configuration Patterns

267

268

#### Environment-Based Configuration

269

270

```python

271

import os

272

from diffsync import DiffSyncFlags

273

274

def get_sync_flags():

275

"""Get sync flags based on environment variables."""

276

flags = DiffSyncFlags.NONE

277

278

if os.getenv("DIFFSYNC_CONTINUE_ON_FAILURE", "false").lower() == "true":

279

flags |= DiffSyncFlags.CONTINUE_ON_FAILURE

280

281

if os.getenv("DIFFSYNC_SKIP_CREATES", "false").lower() == "true":

282

flags |= DiffSyncFlags.SKIP_UNMATCHED_SRC

283

284

if os.getenv("DIFFSYNC_SKIP_DELETES", "false").lower() == "true":

285

flags |= DiffSyncFlags.SKIP_UNMATCHED_DST

286

287

if os.getenv("DIFFSYNC_VERBOSE", "false").lower() == "true":

288

flags |= DiffSyncFlags.LOG_UNCHANGED_RECORDS

289

290

return flags

291

292

# Usage

293

flags = get_sync_flags()

294

diff = target.sync_from(source, flags=flags)

295

```

296

297

#### Configuration Classes

298

299

```python

300

from dataclasses import dataclass

301

from diffsync import DiffSyncFlags, DiffSyncModelFlags

302

303

@dataclass

304

class SyncConfig:

305

"""Configuration for DiffSync operations."""

306

continue_on_failure: bool = False

307

skip_creates: bool = False

308

skip_deletes: bool = False

309

verbose_logging: bool = False

310

dry_run: bool = False

311

312

@property

313

def flags(self) -> DiffSyncFlags:

314

"""Convert configuration to DiffSyncFlags."""

315

flags = DiffSyncFlags.NONE

316

317

if self.continue_on_failure:

318

flags |= DiffSyncFlags.CONTINUE_ON_FAILURE

319

if self.skip_creates:

320

flags |= DiffSyncFlags.SKIP_UNMATCHED_SRC

321

if self.skip_deletes:

322

flags |= DiffSyncFlags.SKIP_UNMATCHED_DST

323

if self.verbose_logging:

324

flags |= DiffSyncFlags.LOG_UNCHANGED_RECORDS

325

326

return flags

327

328

# Usage

329

config = SyncConfig(

330

continue_on_failure=True,

331

verbose_logging=True

332

)

333

334

if config.dry_run:

335

# Just calculate diff without applying

336

diff = target.diff_from(source)

337

print("Dry run - would apply these changes:")

338

print(diff.str())

339

else:

340

# Apply changes

341

diff = target.sync_from(source, flags=config.flags)

342

```

343

344

#### Conditional Flag Application

345

346

```python

347

def smart_sync(source_adapter, target_adapter, safety_mode=True):

348

"""Perform sync with intelligent flag selection based on conditions."""

349

350

# Start with basic flags

351

flags = DiffSyncFlags.NONE

352

353

# In safety mode, be more conservative

354

if safety_mode:

355

flags |= DiffSyncFlags.CONTINUE_ON_FAILURE

356

flags |= DiffSyncFlags.LOG_UNCHANGED_RECORDS

357

358

# Calculate diff first to analyze changes

359

diff = target_adapter.diff_from(source_adapter)

360

summary = diff.summary()

361

362

# If there are many deletions, ask for confirmation

363

if summary['delete'] > 10:

364

print(f"Warning: {summary['delete']} objects will be deleted")

365

if input("Continue? (y/n): ").lower() != 'y':

366

flags |= DiffSyncFlags.SKIP_UNMATCHED_DST

367

368

# If there are many creates, be cautious about resources

369

if summary['create'] > 100:

370

print(f"Warning: {summary['create']} objects will be created")

371

# Could add resource checks here

372

373

# Perform sync with selected flags

374

return target_adapter.sync_from(source_adapter, flags=flags, diff=diff)

375

```

376

377

### Logging Configuration

378

379

DiffSync uses structured logging through the `structlog` library. Configure logging verbosity and format using the logging utilities.

380

381

```python { .api }

382

def enable_console_logging(verbosity: int = 0) -> None:

383

"""

384

Enable formatted logging to console with the specified verbosity.

385

386

Args:

387

verbosity: 0 for WARNING logs, 1 for INFO logs, 2 for DEBUG logs

388

"""

389

```

390

391

#### Logging Usage Examples

392

393

```python

394

from diffsync.logging import enable_console_logging

395

396

# Enable INFO level logging

397

enable_console_logging(verbosity=1)

398

399

# Enable DEBUG level logging for detailed troubleshooting

400

enable_console_logging(verbosity=2)

401

402

# Perform sync with verbose logging

403

diff = target.sync_from(source, flags=DiffSyncFlags.LOG_UNCHANGED_RECORDS)

404

```

405

406

### DiffSyncActions

407

408

Constants representing valid actions for DiffSyncModel operations during synchronization.

409

410

```python { .api }

411

class DiffSyncActions:

412

"""List of valid Action for DiffSyncModel."""

413

414

CREATE = "create"

415

UPDATE = "update"

416

DELETE = "delete"

417

SKIP = "skip"

418

NO_CHANGE = None

419

```

420

421

These constants are used internally by DiffSync to represent the different types of operations that can be performed on models during synchronization. Import from the enum module:

422

423

```python

424

from diffsync.enum import DiffSyncActions

425

426

# Usage example - these values appear in DiffElement.action property

427

for element in diff.get_children():

428

if element.action == DiffSyncActions.CREATE:

429

print(f"Will create {element.name}")

430

elif element.action == DiffSyncActions.UPDATE:

431

print(f"Will update {element.name}")

432

elif element.action == DiffSyncActions.DELETE:

433

print(f"Will delete {element.name}")

434

```

435

436

## Types

437

438

```python { .api }

439

import enum

440

from typing import Union

441

442

# Flag types for type hints

443

SyncFlags = Union[DiffSyncFlags, int]

444

ModelFlags = Union[DiffSyncModelFlags, int]

445

446

# Status enumeration

447

StatusValue = DiffSyncStatus

448

```