Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
186
upgrade_analysis/models/upgrade_record.py
Executable file
186
upgrade_analysis/models/upgrade_record.py
Executable file
@@ -0,0 +1,186 @@
|
||||
# Copyright 2011-2015 Therp BV <https://therp.nl>
|
||||
# Copyright 2016-2020 Opener B.V. <https://opener.am>
|
||||
# Copyright 2019 ForgeFlow <https://forgeflow.com>
|
||||
# Copyright 2020 GRAP <https://grap.coop>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import ast
|
||||
import logging
|
||||
import os
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.modules.module import MANIFEST_NAMES, get_module_path
|
||||
from odoo.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpgradeRecord(models.Model):
|
||||
_name = "upgrade.record"
|
||||
_description = "Upgrade Record"
|
||||
|
||||
name = fields.Char(readonly=True)
|
||||
|
||||
module = fields.Char(readonly=True)
|
||||
|
||||
model = fields.Char(readonly=True)
|
||||
|
||||
field = fields.Char(readonly=True)
|
||||
|
||||
mode = fields.Selection(
|
||||
[("create", "Create"), ("modify", "Modify")],
|
||||
help="Set to Create if a field is newly created "
|
||||
"in this module. If this module modifies an attribute of an "
|
||||
"existing field, set to Modify.",
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
type = fields.Selection(
|
||||
[("field", "Field"), ("xmlid", "XML ID"), ("model", "Model")],
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
attribute_ids = fields.One2many(
|
||||
comodel_name="upgrade.attribute", inverse_name="record_id", readonly=True
|
||||
)
|
||||
|
||||
noupdate = fields.Boolean(readonly=True)
|
||||
|
||||
domain = fields.Char(readonly=True)
|
||||
|
||||
definition = fields.Char(readonly=True)
|
||||
|
||||
prefix = fields.Char(compute="_compute_prefix_and_suffix")
|
||||
|
||||
suffix = fields.Char(compute="_compute_prefix_and_suffix")
|
||||
|
||||
model_original_module = fields.Char(compute="_compute_model_original_module")
|
||||
|
||||
model_type = fields.Char(compute="_compute_model_type")
|
||||
|
||||
@api.depends("name")
|
||||
def _compute_prefix_and_suffix(self):
|
||||
for rec in self:
|
||||
rec.prefix, rec.suffix = rec.name.split(".", 1)
|
||||
|
||||
@api.depends("model", "type")
|
||||
def _compute_model_original_module(self):
|
||||
for rec in self:
|
||||
if rec.type == "model":
|
||||
rec.model_original_module = self.env[rec.model]._original_module
|
||||
else:
|
||||
rec.model_original_module = ""
|
||||
|
||||
@api.depends("model", "type")
|
||||
def _compute_model_type(self):
|
||||
for rec in self:
|
||||
if rec.type == "model":
|
||||
model = self.env[rec.model]
|
||||
if model._auto and model._transient:
|
||||
rec.model_type = "transient"
|
||||
elif model._auto:
|
||||
rec.model_type = ""
|
||||
elif not model._auto and model._abstract:
|
||||
rec.model_type = "abstract"
|
||||
else:
|
||||
rec.model_type = "sql_view"
|
||||
else:
|
||||
rec.model_type = ""
|
||||
|
||||
@api.model
|
||||
def field_dump(self):
|
||||
keys = [
|
||||
"attachment",
|
||||
"module",
|
||||
"mode",
|
||||
"model",
|
||||
"field",
|
||||
"type",
|
||||
"isfunction",
|
||||
"isproperty",
|
||||
"isrelated",
|
||||
"translate",
|
||||
"relation",
|
||||
"required",
|
||||
"stored",
|
||||
"selection_keys",
|
||||
"hasdefault",
|
||||
"table",
|
||||
"_inherits",
|
||||
"_order",
|
||||
]
|
||||
|
||||
template = {x: False for x in keys}
|
||||
data = []
|
||||
for record in self.search([("type", "=", "field")]):
|
||||
repre = template.copy()
|
||||
repre.update(
|
||||
{
|
||||
"module": record.module,
|
||||
"model": record.model,
|
||||
"field": record.field,
|
||||
"mode": record.mode,
|
||||
}
|
||||
)
|
||||
repre.update({x.name: x.value for x in record.attribute_ids})
|
||||
if repre["table"]:
|
||||
repre.update(
|
||||
{
|
||||
"column1": self.env[repre["model"]]
|
||||
._fields[repre["field"]]
|
||||
.column1,
|
||||
"column2": self.env[repre["model"]]
|
||||
._fields[repre["field"]]
|
||||
.column2,
|
||||
}
|
||||
)
|
||||
data.append(repre)
|
||||
return data
|
||||
|
||||
@api.model
|
||||
def list_modules(self):
|
||||
"""Return the set of covered modules"""
|
||||
self.env.cr.execute(
|
||||
"""SELECT DISTINCT(module) FROM upgrade_record
|
||||
ORDER BY module"""
|
||||
)
|
||||
return [module for (module,) in self.env.cr.fetchall()]
|
||||
|
||||
@staticmethod
|
||||
def _read_manifest(addon_dir):
|
||||
for manifest_name in MANIFEST_NAMES:
|
||||
if os.access(os.path.join(addon_dir, manifest_name), os.R_OK):
|
||||
with open(os.path.join(addon_dir, manifest_name)) as f:
|
||||
manifest_string = f.read()
|
||||
return ast.literal_eval(manifest_string)
|
||||
raise ValidationError(
|
||||
_("No manifest found in %(addon_dir)s") % {"addon_dir": addon_dir}
|
||||
)
|
||||
|
||||
@api.model
|
||||
def get_xml_records(self, module):
|
||||
"""Return all XML records from the given module"""
|
||||
addon_dir = get_module_path(module)
|
||||
manifest = self._read_manifest(addon_dir)
|
||||
# The order of the keys are important.
|
||||
# Load files in the same order as in
|
||||
# module/loading.py:load_module_graph
|
||||
files = []
|
||||
for key in ["init_xml", "update_xml", "data"]:
|
||||
if not manifest.get(key):
|
||||
continue
|
||||
for xml_file in manifest[key]:
|
||||
if not xml_file.lower().endswith(".xml"):
|
||||
continue
|
||||
parts = xml_file.split("/")
|
||||
try:
|
||||
with open(os.path.join(addon_dir, *parts)) as xml_handle:
|
||||
files.append(xml_handle.read())
|
||||
except UnicodeDecodeError:
|
||||
_logger.warning(
|
||||
"Encoding error: Unable to read %s",
|
||||
os.path.join(addon_dir, *parts),
|
||||
)
|
||||
continue
|
||||
return files
|
||||
Reference in New Issue
Block a user