neues skript sql_dump_diff.py zum Vergleich von 2 sql-dumps.

- leere, frisch initialisierte Datenbanken der Versionen verglichen
- datasetprogramme erkennen jetzt auch suche nach standardtabellen wie uom
This commit is contained in:
2026-08-22 17:45:46 +02:00
parent c0dd24b6c5
commit a55774eff2
19 changed files with 78583 additions and 269 deletions
+42
View File
@@ -96,10 +96,35 @@ def resolve_model_get(node):
return node.args[0].value
def resolve_find_call(node, model_vars):
"""Erkennt `SomeModelVar.find([('feld', '=', 'wert'), ...])` bzw.
`.search(...)` - das Standardmuster, mit dem Tryton-Tests auf bereits
vorhandene Stammdaten zugreifen (Länder, Währungen, Einheiten,
Lagerorte, ... - i. d. R. per XML-Fixture beim Modul-Aktivieren
angelegt, nicht Teil des Testdatensatzes selbst). Liefert
(model_name, domain) oder None, wenn das Domain-Argument nicht rein
literal ist (z. B. eine Variable referenziert) oder das Muster nicht
passt."""
if not isinstance(node, ast.Call) or not isinstance(node.func, ast.Attribute):
return None
if node.func.attr not in ("find", "search"):
return None
if not isinstance(node.func.value, ast.Name) or node.func.value.id not in model_vars:
return None
if not node.args:
return None
try:
domain = ast.literal_eval(node.args[0])
except Exception:
return None
return model_vars[node.func.value.id], domain
class ScenarioParser:
def __init__(self):
self.model_vars = {} # Variable -> Modellname (aus Model.get(...))
self.record_vars = {} # Variable -> Record-Dict (key/model/fields)
self.search_vars = {} # Variable -> {"model": ..., "domain": ...} (aus X.find(...)/.search(...))
self.finalized = set() # Variablen, deren erster .save()-Aufruf schon verarbeitet wurde
self.output = [] # fertige Record-Dicts in Reihenfolge
self.manual_notes = [] # Zeilen, die nicht automatisch verstanden wurden
@@ -111,6 +136,8 @@ class ScenarioParser:
if isinstance(node, ast.Name):
if node.id in self.record_vars:
return {"$ref": self.record_vars[node.id]["key"]}
if node.id in self.search_vars:
return {"$search": self.search_vars[node.id]}
return self._manual(node)
if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub):
@@ -163,6 +190,21 @@ class ScenarioParser:
return
target = node.targets[0]
# x, = SomeModelVar.find([('feld', '=', 'wert')]) (Zugriff auf
# vorhandene Stammdaten statt Anlegen eines neuen Records)
if (
isinstance(target, ast.Tuple)
and len(target.elts) == 1
and isinstance(target.elts[0], ast.Name)
):
found = resolve_find_call(node.value, self.model_vars)
if found:
model_name, domain = found
self.search_vars[target.elts[0].id] = {"model": model_name, "domain": domain}
return
self._manual(node)
return
# X = Model.get('some.model')
if isinstance(target, ast.Name):
model_name = resolve_model_get(node.value)