Closes: #387 - Schema comparator tool#452
Closes: #387 - Schema comparator tool#452bctiemann wants to merge 11 commits into386-schema-exportfrom
Conversation
# Conflicts: # netbox_custom_objects/tests/test_schema_format.py
|
@claude /review |
|
Claude finished @bctiemann's task in 1m 53s —— View job Code Review: PR #452 — Schema Comparator Tool
OverviewThis PR adds a clean, well-architected read-only diff engine that sits between the schema exporter (#386) and the upcoming upgrade executor (#389). The design is solid: the data model is expressive, the tombstone rules are well-documented, and the test coverage is comprehensive. Strengths
IssuesMedium — Type-specific attrs compared against schema type, not DB type
type_specific = FIELD_TYPE_ATTRS.get(schema_type, set())When a field's type changes (e.g., This is probably fine since the executor is responsible for schema changes, but the module docstring says "Type changes are included in changed_attrs but are not validated here; the executor decides whether to allow or reject them." — it could be worth adding: "Type-specific attrs from the old DB type are not included in the diff when the type changes." Minor —
|
|
All issues identified by the agent review have been addressed. |
Closes: #387
Implements the COT schema comparator ("diff engine"): a pure-read public API that compares an incoming schema document against the live DB state of each referenced
CustomObjectTypeand returns a structured diff that the upgrade executor (#389, PR #453) can consume.Public API —
comparator.pyData model
COTDiffnamestrslugstris_newboolTrueif COT does not yet exist in DBcot_changesdict[str, tuple]{attr: (db_val, schema_val)}for top-level COT attribute differencesfield_changeslist[FieldChange]warningslist[str]Convenience properties:
has_changes,has_destructive_changes,adds,removes,alters.FieldChangeopFieldOpADD,REMOVE, orALTERschema_idintdb_namestr | NoneNoneforADD)schema_defdictchanged_attrsdict[str, tuple]{attr: (db_val, schema_val)}— populated forALTER; includes"name"if renamed,"type"if type differsProperties:
is_rename,is_type_change.Matching and tombstone rules
schema_id. DB fields without aschema_idare not tracked — they generate a warning, not aREMOVE.REMOVEis only emitted when the field'sschema_idappears inschema.removed_fields(tombstone list). A field absent from bothschema.fieldsandschema.removed_fieldsis ambiguous and generates a warning.related_object_typevalues are compared in their encoded schema form ("app_label/model"or"custom-objects/<slug>"), making diffs round-trip compatible with the schema format.Tests —
test_comparator.py(37 tests, 9 classes)ComparatorCleanDiffTestCaseComparatorNewCOTTestCaseADD,is_new=TrueComparatorCOTAttrsTestCaseComparatorFieldAddTestCaseschema_id→ADDComparatorFieldRemoveTestCaseREMOVE; untombstoned absence → warningComparatorFieldAlterTestCasechoice_set,related_object_type,related_object_filterComparatorWarningsTestCaseschema_id) and non-tombstoned absent fields produce warningsComparatorMultiCOTTestCaseComparatorHelperPropertiesTestCasehas_changes,has_destructive_changes,adds,removes,alters