Public Access
extract gets and saves most tables worked on
some cases still need some work...
This commit is contained in:
+216
-3
@@ -31,6 +31,16 @@ class RegisterExtractor(ast.NodeVisitor):
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.results = []
|
||||
self.model_names = {}
|
||||
|
||||
def visit_Module(self, node):
|
||||
for item in node.body:
|
||||
if isinstance(item, ast.ClassDef):
|
||||
model_name = self.get_model_name(item)
|
||||
if model_name:
|
||||
self.model_names[item.name] = model_name
|
||||
|
||||
self.generic_visit(node)
|
||||
|
||||
def visit_ClassDef(self, node):
|
||||
for item in node.body:
|
||||
@@ -42,6 +52,15 @@ class RegisterExtractor(ast.NodeVisitor):
|
||||
def extract_register(self, cls, func):
|
||||
|
||||
operations = []
|
||||
self.table_vars = {}
|
||||
self.current_class = cls
|
||||
|
||||
model_name = self.model_names.get(cls)
|
||||
if model_name:
|
||||
self.table_vars["cls"] = model_name
|
||||
|
||||
for stmt in func.body:
|
||||
self.collect_table_assignment(stmt)
|
||||
|
||||
self.walk_statements(func.body, operations, "before_super", None)
|
||||
|
||||
@@ -54,6 +73,159 @@ class RegisterExtractor(ast.NodeVisitor):
|
||||
})
|
||||
|
||||
|
||||
def get_model_name(self, node):
|
||||
for item in node.body:
|
||||
if not isinstance(item, ast.Assign):
|
||||
continue
|
||||
|
||||
for target in item.targets:
|
||||
if (
|
||||
isinstance(target, ast.Name)
|
||||
and target.id == "__name__"
|
||||
):
|
||||
try:
|
||||
return ast.literal_eval(item.value)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def collect_table_assignment(self, stmt):
|
||||
for node in ast.walk(stmt):
|
||||
if not isinstance(node, ast.Assign):
|
||||
continue
|
||||
|
||||
if len(node.targets) != 1:
|
||||
continue
|
||||
|
||||
target = node.targets[0]
|
||||
if not isinstance(target, ast.Name):
|
||||
continue
|
||||
|
||||
table = self.resolve_table_call(node.value)
|
||||
if table:
|
||||
self.table_vars[target.id] = table
|
||||
elif isinstance(node.value, ast.Constant):
|
||||
self.table_vars[target.id] = node.value.value
|
||||
|
||||
def resolve_table_call(self, node):
|
||||
if not isinstance(node, ast.Call):
|
||||
return None
|
||||
|
||||
# ModelClass = pool.get('ir.model.data')
|
||||
if (
|
||||
isinstance(node.func, ast.Attribute)
|
||||
and node.func.attr == "get"
|
||||
and isinstance(node.func.value, ast.Name)
|
||||
and node.func.value.id == "pool"
|
||||
and len(node.args) == 1
|
||||
and isinstance(node.args[0], ast.Constant)
|
||||
and isinstance(node.args[0].value, str)
|
||||
):
|
||||
return node.args[0].value
|
||||
|
||||
|
||||
if not (
|
||||
isinstance(node.func, ast.Attribute)
|
||||
and node.func.attr in ("__table__", "__table_handler__")
|
||||
):
|
||||
return None
|
||||
|
||||
receiver = node.func.value
|
||||
# ModelClass = pool.get('ir.model.data')
|
||||
if (
|
||||
isinstance(receiver, ast.Name)
|
||||
and receiver.id == "pool"
|
||||
):
|
||||
return None
|
||||
|
||||
if (
|
||||
isinstance(node.func, ast.Attribute)
|
||||
and node.func.attr == "get"
|
||||
and isinstance(node.func.value, ast.Name)
|
||||
and node.func.value.id == "pool"
|
||||
and len(node.args) == 1
|
||||
and isinstance(node.args[0], ast.Constant)
|
||||
and isinstance(node.args[0].value, str)
|
||||
):
|
||||
return node.args[0].value
|
||||
if isinstance(receiver, ast.Name):
|
||||
if receiver.id == "cls":
|
||||
model_name = self.model_names.get(self.current_class)
|
||||
else:
|
||||
model_name = (
|
||||
self.model_names.get(receiver.id)
|
||||
or self.table_vars.get(receiver.id)
|
||||
)
|
||||
|
||||
if model_name:
|
||||
return model_name.replace(".", "_")
|
||||
|
||||
return None
|
||||
|
||||
def resolve_table_object(self, node):
|
||||
if isinstance(node, ast.Name):
|
||||
return self.table_vars.get(node.id)
|
||||
|
||||
if (
|
||||
isinstance(node, ast.Attribute)
|
||||
and node.attr == "_table"
|
||||
and isinstance(node.value, ast.Name)
|
||||
and node.value.id == "cls"
|
||||
):
|
||||
model_name = self.model_names.get(self.current_class)
|
||||
if model_name:
|
||||
return model_name.replace(".", "_")
|
||||
|
||||
return self.resolve_table_call(node)
|
||||
|
||||
def find_tables(self, node):
|
||||
tables = []
|
||||
|
||||
for child in ast.walk(node):
|
||||
if not isinstance(child, ast.Call):
|
||||
continue
|
||||
|
||||
if not (
|
||||
isinstance(child.func, ast.Attribute)
|
||||
and child.func.attr in {
|
||||
"column_rename",
|
||||
"drop_column",
|
||||
"add_column",
|
||||
"drop_constraint",
|
||||
"add_constraint",
|
||||
"not_null_action",
|
||||
"index_action",
|
||||
"alter_size",
|
||||
"update",
|
||||
"insert",
|
||||
"delete",
|
||||
"select",
|
||||
"table_exist",
|
||||
}
|
||||
):
|
||||
continue
|
||||
|
||||
# backend.TableHandler.table_exist(cls._table)
|
||||
if (
|
||||
isinstance(child.func.value, ast.Attribute)
|
||||
and child.func.value.attr == "TableHandler"
|
||||
and isinstance(child.func.value.value, ast.Name)
|
||||
and child.func.value.value.id == "backend"
|
||||
and child.func.attr == "table_exist"
|
||||
and child.args
|
||||
):
|
||||
table = self.resolve_table_object(child.args[0])
|
||||
if table and table not in tables:
|
||||
tables.append(table)
|
||||
|
||||
continue
|
||||
table = self.resolve_table_object(child.func.value)
|
||||
if table and table not in tables:
|
||||
tables.append(table)
|
||||
|
||||
return tables
|
||||
|
||||
def walk_statements(self, statements, operations, phase, condition):
|
||||
|
||||
for stmt in statements:
|
||||
@@ -84,6 +256,9 @@ class RegisterExtractor(ast.NodeVisitor):
|
||||
if condition:
|
||||
op["condition"] = condition
|
||||
operations.append(op)
|
||||
|
||||
if not op['tables']:
|
||||
print(op)
|
||||
|
||||
for child in ast.iter_child_nodes(node):
|
||||
self.walk_expression(child, operations, phase, condition)
|
||||
@@ -138,9 +313,46 @@ class RegisterExtractor(ast.NodeVisitor):
|
||||
|
||||
operation = call.func.attr
|
||||
|
||||
if operation not in interesting:
|
||||
is_table_handler = (
|
||||
isinstance(call.func.value, ast.Attribute)
|
||||
and call.func.value.attr == "TableHandler"
|
||||
and isinstance(call.func.value.value, ast.Name)
|
||||
and call.func.value.value.id == "backend"
|
||||
)
|
||||
|
||||
if operation not in interesting and not is_table_handler:
|
||||
return None
|
||||
|
||||
|
||||
tables = self.find_tables(call)
|
||||
|
||||
if (
|
||||
isinstance(call.func, ast.Attribute)
|
||||
and call.func.attr == "table_rename"
|
||||
and isinstance(call.func.value, ast.Attribute)
|
||||
and isinstance(call.func.value.value, ast.Name)
|
||||
and call.func.value.value.id == "backend"
|
||||
and isinstance(call.args, list)
|
||||
):
|
||||
for arg in call.args[:2]:
|
||||
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
|
||||
table = arg.value
|
||||
elif isinstance(arg, ast.Name):
|
||||
table = self.table_vars.get(arg.id)
|
||||
elif (
|
||||
isinstance(arg, ast.Attribute)
|
||||
and isinstance(arg.value, ast.Name)
|
||||
and arg.value.id == "cls"
|
||||
and arg.attr == "_table"
|
||||
):
|
||||
table = self.model_names.get(self.current_class)
|
||||
if table:
|
||||
table = table.replace(".", "_")
|
||||
else:
|
||||
table = None
|
||||
|
||||
if table and table not in tables:
|
||||
tables.append(table)
|
||||
|
||||
# Wer wird aufgerufen?
|
||||
if isinstance(call.func.value, ast.Name):
|
||||
obj = call.func.value.id
|
||||
@@ -162,10 +374,11 @@ class RegisterExtractor(ast.NodeVisitor):
|
||||
kwargs[kw.arg] = ast.unparse(kw.value)
|
||||
except Exception:
|
||||
kwargs[kw.arg] = "<unknown>"
|
||||
|
||||
|
||||
return {
|
||||
"object": obj,
|
||||
"operation": operation,
|
||||
"tables": tables,
|
||||
"line": call.lineno,
|
||||
"args": args,
|
||||
"kwargs": kwargs,
|
||||
|
||||
Reference in New Issue
Block a user