[REF] rename framework files, adapt to new module names, remove print (replaced by logger), apply pre-commit rules

pull/2417/head
Sylvain LE GAL 2020-11-07 15:52:29 +01:00 committed by Stefan Rijnhart
parent 8db67a09a0
commit b7a3528af8
21 changed files with 355 additions and 278 deletions

View File

@ -4,3 +4,5 @@ from . import wizards
from . import blacklist from . import blacklist
from . import apriori from . import apriori
from . import compare from . import compare
from . import upgrade_loading
from . import upgrade_log

View File

@ -13,8 +13,8 @@
"security/ir.model.access.csv", "security/ir.model.access.csv",
"views/menu.xml", "views/menu.xml",
"views/view_upgrade_comparison_config.xml", "views/view_upgrade_comparison_config.xml",
"views/view_upgrade_analysis.xml",
"views/view_upgrade_record.xml", "views/view_upgrade_record.xml",
"wizards/view_upgrade_analysis_wizard.xml",
"wizards/view_upgrade_generate_record_wizard.xml", "wizards/view_upgrade_generate_record_wizard.xml",
"wizards/view_upgrade_install_wizard.xml", "wizards/view_upgrade_install_wizard.xml",
], ],

View File

@ -1,4 +1,5 @@
from . import ir_module_module from . import ir_module_module
from . import upgrade_comparison_config from . import upgrade_comparison_config
from . import upgrade_analysis
from . import upgrade_attribute from . import upgrade_attribute
from . import upgrade_record from . import upgrade_record

View File

@ -7,42 +7,65 @@ import os
from odoo import fields, models from odoo import fields, models
from odoo.modules import get_module_path from odoo.modules import get_module_path
from odoo.tools import config
from .. import compare from .. import compare
_IGNORE_MODULES = ["openupgrade_records", "upgrade_analysis"]
class UpgradeAnalysisWizard(models.TransientModel):
_name = "upgrade.analysis.wizard"
_description = "upgrade Analysis Wizard"
server_config_id = fields.Many2one( class UpgradeAnalysis(models.Model):
"upgrade.comparison.config", "Configuration", required=True _name = "upgrade.analysis"
) _description = "Upgrade Analyses"
analysis_date = fields.Datetime(readonly=True)
state = fields.Selection( state = fields.Selection(
[("init", "Init"), ("ready", "Ready")], readonly=True, default="init" [("draft", "draft"), ("done", "Done")], readonly=True, default="draft"
) )
log = fields.Text() config_id = fields.Many2one(
string="Comparison Config",
comodel_name="upgrade.comparison.config",
readonly=True,
required=True,
)
log = fields.Text(readonly=True)
write_files = fields.Boolean( write_files = fields.Boolean(
help="Write analysis files to the module directories", default=True help="Write analysis files to the module directories", default=True
) )
def get_communication(self): def _get_remote_model(self, connection, model):
""" self.ensure_one()
Retrieve both sets of database representations, if model == "record":
perform the comparison and register the resulting if float(self.config_id.version) < 14:
change set return connection.env["openupgrade.record"]
""" else:
return connection.env["upgrade.record"]
return False
def write_file(module, version, content, filename="upgrade_analysis.txt"): def _write_file(
module_path = get_module_path(module) self, module_name, version, content, filename="upgrade_analysis.txt"
):
module = self.env["ir.module.module"].search([("name", "=", module_name)])[0]
if module.is_odoo_module:
upgrade_path = config.get("upgrade_path", False)
if not upgrade_path:
return "ERROR: could not find 'upgrade_path' config:\n"
module_path = os.path.join(upgrade_path, module_name)
else:
module_path = get_module_path(module_name)
if not module_path: if not module_path:
return "ERROR: could not find module path:\n" return "ERROR: could not find module path of '%s':\n" % (module_name)
full_path = os.path.join(module_path, "migrations", version) full_path = os.path.join(module_path, "migrations", version)
if not os.path.exists(full_path): if not os.path.exists(full_path):
try: try:
os.makedirs(full_path) os.makedirs(full_path)
except os.error: except os.error:
return "ERROR: could not create migrations directory:\n" return "ERROR: could not create migrations directory %s:\n" % (
full_path
)
logfile = os.path.join(full_path, filename) logfile = os.path.join(full_path, filename)
try: try:
f = open(logfile, "w") f = open(logfile, "w")
@ -52,14 +75,26 @@ class UpgradeAnalysisWizard(models.TransientModel):
f.close() f.close()
return None return None
def analyze(self):
"""
Retrieve both sets of database representations,
perform the comparison and register the resulting
change set
"""
self.ensure_one() self.ensure_one()
connection = self.server_config_id.get_connection() self.write(
remote_record_obj = connection.env["upgrade.record"] {
local_record_obj = self.env["upgrade.record"] "analysis_date": fields.Datetime.now(),
}
)
connection = self.config_id.get_connection()
RemoteRecord = self._get_remote_model(connection, "record")
LocalRecord = self.env["upgrade.record"]
# Retrieve field representations and compare # Retrieve field representations and compare
remote_records = remote_record_obj.field_dump() remote_records = RemoteRecord.field_dump()
local_records = local_record_obj.field_dump() local_records = LocalRecord.field_dump()
res = compare.compare_sets(remote_records, local_records) res = compare.compare_sets(remote_records, local_records)
# Retrieve xml id representations and compare # Retrieve xml id representations and compare
@ -74,12 +109,12 @@ class UpgradeAnalysisWizard(models.TransientModel):
] ]
local_xml_records = [ local_xml_records = [
{field: record[field] for field in flds} {field: record[field] for field in flds}
for record in local_record_obj.search([("type", "=", "xmlid")]) for record in LocalRecord.search([("type", "=", "xmlid")])
] ]
remote_xml_record_ids = remote_record_obj.search([("type", "=", "xmlid")]) remote_xml_record_ids = RemoteRecord.search([("type", "=", "xmlid")])
remote_xml_records = [ remote_xml_records = [
{field: record[field] for field in flds} {field: record[field] for field in flds}
for record in remote_record_obj.read(remote_xml_record_ids, flds) for record in RemoteRecord.read(remote_xml_record_ids, flds)
] ]
res_xml = compare.compare_xml_sets(remote_xml_records, local_xml_records) res_xml = compare.compare_xml_sets(remote_xml_records, local_xml_records)
@ -93,12 +128,12 @@ class UpgradeAnalysisWizard(models.TransientModel):
] ]
local_model_records = [ local_model_records = [
{field: record[field] for field in flds} {field: record[field] for field in flds}
for record in local_record_obj.search([("type", "=", "model")]) for record in LocalRecord.search([("type", "=", "model")])
] ]
remote_model_record_ids = remote_record_obj.search([("type", "=", "model")]) remote_model_record_ids = RemoteRecord.search([("type", "=", "model")])
remote_model_records = [ remote_model_records = [
{field: record[field] for field in flds} {field: record[field] for field in flds}
for record in remote_record_obj.read(remote_model_record_ids, flds) for record in RemoteRecord.read(remote_model_record_ids, flds)
] ]
res_model = compare.compare_model_sets( res_model = compare.compare_model_sets(
remote_model_records, local_model_records remote_model_records, local_model_records
@ -124,7 +159,12 @@ class UpgradeAnalysisWizard(models.TransientModel):
[("state", "=", "installed")] [("state", "=", "installed")]
) )
} }
general = "" general_log = ""
for ignore_module in _IGNORE_MODULES:
if ignore_module in keys:
keys.remove(ignore_module)
for key in keys: for key in keys:
contents = "---Models in module '%s'---\n" % key contents = "---Models in module '%s'---\n" % key
if key in res_model: if key in res_model:
@ -144,39 +184,35 @@ class UpgradeAnalysisWizard(models.TransientModel):
if key not in res and key not in res_xml and key not in res_model: if key not in res and key not in res_xml and key not in res_model:
contents += "---nothing has changed in this module--\n" contents += "---nothing has changed in this module--\n"
if key == "general": if key == "general":
general += contents general_log += contents
continue continue
if compare.module_map(key) not in modules: if compare.module_map(key) not in modules:
general += ( general_log += (
"ERROR: module not in list of installed modules:\n" + contents "ERROR: module not in list of installed modules:\n" + contents
) )
continue continue
if key not in modules: if key not in modules:
# no need to log in general the merged/renamed modules # no need to log in full log the merged/renamed modules
continue continue
if self.write_files: if self.write_files:
error = write_file(key, modules[key].installed_version, contents) error = self._write_file(key, modules[key].installed_version, contents)
if error: if error:
general += error general_log += error
general += contents general_log += contents
else: else:
general += contents general_log += contents
# Store the general log in as many places as possible ;-) # Store the full log
if self.write_files and "base" in modules: if self.write_files and "base" in modules:
write_file( self._write_file(
"base", "base",
modules["base"].installed_version, modules["base"].installed_version,
general, general_log,
"upgrade_general_log.txt", "upgrade_general_log.txt",
) )
self.server_config_id.write({"last_log": general}) self.write(
self.write({"state": "ready", "log": general}) {
"state": "done",
return { "log": general_log,
"name": self._description,
"view_mode": "form",
"res_model": self._name,
"type": "ir.actions.act_window",
"res_id": self.id,
} }
)

View File

@ -2,14 +2,12 @@
# Copyright 2016 Opener B.V. <https://opener.am> # Copyright 2016 Opener B.V. <https://opener.am>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging import odoorpc
from odoo import fields, models from odoo import api, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.tools.translate import _ from odoo.tools.translate import _
from .. import apriori
class UpgradeComparisonConfig(models.Model): class UpgradeComparisonConfig(models.Model):
_name = "upgrade.comparison.config" _name = "upgrade.comparison.config"
@ -27,14 +25,23 @@ class UpgradeComparisonConfig(models.Model):
password = fields.Char(required=True, default="admin") password = fields.Char(required=True, default="admin")
last_log = fields.Text() version = fields.Char()
analysis_ids = fields.One2many(
string="Analyses", comodel_name="upgrade.analysis", inverse_name="config_id"
)
analysis_qty = fields.Integer(compute="_compute_analysis_qty")
@api.depends("analysis_ids")
def _compute_analysis_qty(self):
for config in self:
config.analysis_qty = len(config.analysis_ids)
def get_connection(self): def get_connection(self):
self.ensure_one() self.ensure_one()
import odoorpc
remote = odoorpc.ODOO(self.server, port=self.port) remote = odoorpc.ODOO(self.server, port=self.port)
remote.login(self.database, self.username, self.password) remote.login(self.database, self.username, self.password)
self.version = remote.version
return remote return remote
def test_connection(self): def test_connection(self):
@ -46,43 +53,35 @@ class UpgradeComparisonConfig(models.Model):
user_info = user_model.read([ids[0]], ["name"])[0] user_info = user_model.read([ids[0]], ["name"])[0]
except Exception as e: except Exception as e:
raise UserError(_("Connection failed.\n\nDETAIL: %s") % e) raise UserError(_("Connection failed.\n\nDETAIL: %s") % e)
raise UserError(_("%s is connected.") % user_info["name"])
def analyze(self):
""" Run the analysis wizard """
self.ensure_one()
wizard = self.env["upgrade.analysis.wizard"].create(
{"server_config_id": self.id}
)
return { return {
"name": wizard._description, "type": "ir.actions.client",
"view_mode": "form", "tag": "display_notification",
"res_model": wizard._name, "params": {
"type": "ir.actions.act_window", "type": "info",
"target": "new", "message": _(
"res_id": wizard.id, "You are correctly connected to the server {server}"
"nodestroy": True, " (version {version}) with the user {user_name}"
).format(
server=self.server,
version=self.version,
user_name=user_info["name"],
),
},
} }
def install_modules(self): def new_analysis(self):
""" Install same modules as in source DB """
self.ensure_one() self.ensure_one()
connection = self.get_connection() analysis = self.env["upgrade.analysis"].create({"config_id": self.id})
remote_module_obj = connection.env["ir.module.module"] return {
remote_module_ids = remote_module_obj.search([("state", "=", "installed")]) "name": analysis._description,
"view_mode": "form",
"res_model": analysis._name,
"type": "ir.actions.act_window",
# "target": "new",
"res_id": analysis.id,
# "nodestroy": True,
}
modules = [] def action_show_analysis(self):
for module_id in remote_module_ids: self.ensure_one()
mod = remote_module_obj.read([module_id], ["name"])[0]
mod_name = mod["name"]
mod_name = apriori.renamed_modules.get(mod_name, mod_name)
modules.append(mod_name)
_logger = logging.getLogger(__name__)
_logger.debug("remote modules %s", modules)
local_modules = self.env["ir.module.module"].search(
[("name", "in", modules), ("state", "=", "uninstalled")]
)
_logger.debug("local modules %s", ",".join(local_modules.mapped("name")))
if local_modules:
local_modules.write({"state": "to install"})
return {} return {}

View File

@ -1,3 +1,2 @@
from . import odoo from . import odoo
from . import addons from . import addons

View File

@ -13,7 +13,6 @@ def _pre_init_mrp(cr):
# cr.execute("""ALTER TABLE "stock_move" ADD COLUMN "is_done" bool;""") # cr.execute("""ALTER TABLE "stock_move" ADD COLUMN "is_done" bool;""")
# cr.execute("""UPDATE stock_move # cr.execute("""UPDATE stock_move
# SET is_done=COALESCE(state in ('done', 'cancel'), FALSE);""") # SET is_done=COALESCE(state in ('done', 'cancel'), FALSE);""")
pass
# </OpenUpgrade> # </OpenUpgrade>

View File

@ -5,7 +5,7 @@ import odoo
import psycopg2 import psycopg2
from odoo import _ from odoo import _
from odoo.models import fix_import_export_id_paths, BaseModel, _logger from odoo.models import fix_import_export_id_paths, BaseModel, _logger
from odoo.addons.openupgrade_framework.openupgrade import openupgrade_log from ... import upgrade_log
if True: if True:
@ -154,7 +154,7 @@ if True:
batch_xml_ids.add(xid) batch_xml_ids.add(xid)
# <OpenUpgrade:ADD> # <OpenUpgrade:ADD>
# log csv records # log csv records
openupgrade_log.log_xml_id(self.env.cr, current_module, xid) upgrade_log.log_xml_id(self.env.cr, current_module, xid)
# </OpenUpgrade> # </OpenUpgrade>
elif id: elif id:
record['id'] = id record['id'] = id

View File

@ -13,7 +13,7 @@ from odoo.modules import loading
from odoo.modules.module import adapt_version, load_openerp_module, initialize_sys_path from odoo.modules.module import adapt_version, load_openerp_module, initialize_sys_path
from odoo.modules.loading import load_data, load_demo, _check_module_names from odoo.modules.loading import load_data, load_demo, _check_module_names
from odoo.addons.openupgrade_framework.openupgrade import openupgrade_loading from .... import upgrade_loading
import os import os
@ -118,8 +118,8 @@ def _load_module_graph(cr, graph, status=None, perform_checks=True,
for model in env.values(): for model in env.values():
if not model._auto: if not model._auto:
continue continue
openupgrade_loading.log_model(model, local_registry) upgrade_loading.log_model(model, local_registry)
openupgrade_loading.compare_registries( upgrade_loading.compare_registries(
cr, package.name, upg_registry, local_registry) cr, package.name, upg_registry, local_registry)
# </OpenUpgrade> # </OpenUpgrade>
@ -289,7 +289,7 @@ def _load_marked_modules(cr, graph, states, force, progressdict, report,
cr.execute("SELECT name from ir_module_module WHERE state IN %s" ,(tuple(states),)) cr.execute("SELECT name from ir_module_module WHERE state IN %s" ,(tuple(states),))
module_list = [name for (name,) in cr.fetchall() if name not in graph] module_list = [name for (name,) in cr.fetchall() if name not in graph]
# <OpenUpgrade:ADD> # <OpenUpgrade:ADD>
module_list = openupgrade_loading.add_module_dependencies(cr, module_list) module_list = upgrade_loading.add_module_dependencies(cr, module_list)
# </OpenUpgrade> # </OpenUpgrade>
if not module_list: if not module_list:
break break

View File

@ -18,6 +18,6 @@ form: module.record_id""" % (xml_id,)
assert modcnt == 1, """The ID "%s" refers to an uninstalled module""" % (xml_id,) assert modcnt == 1, """The ID "%s" refers to an uninstalled module""" % (xml_id,)
# OpenUpgrade: log entry of XML imports # OpenUpgrade: log entry of XML imports
openupgrade_log.log_xml_id(self.env.cr, self.module, xml_id) upgrade_log.log_xml_id(self.env.cr, self.module, xml_id)
xml_import._test_xml_id = __test_xml_id xml_import._test_xml_id = __test_xml_id

View File

@ -2,6 +2,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_upgrade_record,upgrade.record all,model_upgrade_record,,1,0,0,0 access_upgrade_record,upgrade.record all,model_upgrade_record,,1,0,0,0
access_upgrade_attribute,upgrade.attribute all,model_upgrade_attribute,,1,0,0,0 access_upgrade_attribute,upgrade.attribute all,model_upgrade_attribute,,1,0,0,0
access_upgrade_comparison_config,upgrade.comparison.config,model_upgrade_comparison_config,base.group_system,1,1,1,1 access_upgrade_comparison_config,upgrade.comparison.config,model_upgrade_comparison_config,base.group_system,1,1,1,1
access_upgrade_analysis_wizard,access_upgrade_analysis_wizard,model_upgrade_analysis_wizard,base.group_system,1,1,1,1 access_upgrade_analysis,access_upgrade_analysis,model_upgrade_analysis,base.group_system,1,1,1,1
access_upgrade_generate_record_wizard,access_upgrade_generate_record_wizard,model_upgrade_generate_record_wizard,base.group_system,1,1,1,1 access_upgrade_generate_record_wizard,access_upgrade_generate_record_wizard,model_upgrade_generate_record_wizard,base.group_system,1,1,1,1
access_upgrade_install_wizard,access_upgrade_install_wizard,model_upgrade_install_wizard,base.group_system,1,1,1,1 access_upgrade_install_wizard,access_upgrade_install_wizard,model_upgrade_install_wizard,base.group_system,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_upgrade_record upgrade.record all model_upgrade_record 1 0 0 0
3 access_upgrade_attribute upgrade.attribute all model_upgrade_attribute 1 0 0 0
4 access_upgrade_comparison_config upgrade.comparison.config model_upgrade_comparison_config base.group_system 1 1 1 1
5 access_upgrade_analysis_wizard access_upgrade_analysis access_upgrade_analysis_wizard access_upgrade_analysis model_upgrade_analysis_wizard model_upgrade_analysis base.group_system 1 1 1 1
6 access_upgrade_generate_record_wizard access_upgrade_generate_record_wizard model_upgrade_generate_record_wizard base.group_system 1 1 1 1
7 access_upgrade_install_wizard access_upgrade_install_wizard model_upgrade_install_wizard base.group_system 1 1 1 1

View File

@ -10,13 +10,13 @@ from openupgradelib.openupgrade_tools import table_exists
from odoo import release from odoo import release
from odoo.modules.module import get_module_path from odoo.modules.module import get_module_path
from odoo.tools.safe_eval import safe_eval
from odoo.tools.config import config from odoo.tools.config import config
from odoo.tools.safe_eval import safe_eval
# A collection of functions used in # A collection of functions used in
# odoo/modules/loading.py # odoo/modules/loading.py
logger = logging.getLogger("OpenUpgrade") _logger = logging.getLogger(__name__)
def add_module_dependencies(cr, module_list): def add_module_dependencies(cr, module_list):
@ -104,7 +104,7 @@ def add_module_dependencies(cr, module_list):
) )
auto_modules = [row[0] for row in cr.fetchall() if get_module_path(row[0])] auto_modules = [row[0] for row in cr.fetchall() if get_module_path(row[0])]
if auto_modules: if auto_modules:
logger.info("Selecting autoinstallable modules %s", ",".join(auto_modules)) _logger.info("Selecting autoinstallable modules %s", ",".join(auto_modules))
module_list += auto_modules module_list += auto_modules
# Set proper state for new dependencies so that any init scripts are run # Set proper state for new dependencies so that any init scripts are run
@ -213,7 +213,7 @@ def get_record_id(cr, module, model, field, mode):
the key parameter values the key parameter values
""" """
cr.execute( cr.execute(
"SELECT id FROM openupgrade_record " "SELECT id FROM upgrade_record "
"WHERE module = %s AND model = %s AND " "WHERE module = %s AND model = %s AND "
"field = %s AND mode = %s AND type = %s", "field = %s AND mode = %s AND type = %s",
(module, model, field, mode, "field"), (module, model, field, mode, "field"),
@ -222,13 +222,13 @@ def get_record_id(cr, module, model, field, mode):
if record: if record:
return record[0] return record[0]
cr.execute( cr.execute(
"INSERT INTO openupgrade_record " "INSERT INTO upgrade_record "
"(module, model, field, mode, type) " "(module, model, field, mode, type) "
"VALUES (%s, %s, %s, %s, %s)", "VALUES (%s, %s, %s, %s, %s)",
(module, model, field, mode, "field"), (module, model, field, mode, "field"),
) )
cr.execute( cr.execute(
"SELECT id FROM openupgrade_record " "SELECT id FROM upgrade_record "
"WHERE module = %s AND model = %s AND " "WHERE module = %s AND model = %s AND "
"field = %s AND mode = %s AND type = %s", "field = %s AND mode = %s AND type = %s",
(module, model, field, mode, "field"), (module, model, field, mode, "field"),
@ -242,7 +242,7 @@ def compare_registries(cr, module, registry, local_registry):
log any differences and merge the local registry with log any differences and merge the local registry with
the global one. the global one.
""" """
if not table_exists(cr, "openupgrade_record"): if not table_exists(cr, "upgrade_record"):
return return
for model, flds in local_registry.items(): for model, flds in local_registry.items():
registry.setdefault(model, {}) registry.setdefault(model, {})
@ -255,14 +255,14 @@ def compare_registries(cr, module, registry, local_registry):
if not record_id: if not record_id:
record_id = get_record_id(cr, module, model, field, mode) record_id = get_record_id(cr, module, model, field, mode)
cr.execute( cr.execute(
"SELECT id FROM openupgrade_attribute " "SELECT id FROM upgrade_attribute "
"WHERE name = %s AND value = %s AND " "WHERE name = %s AND value = %s AND "
"record_id = %s", "record_id = %s",
(key, value, record_id), (key, value, record_id),
) )
if not cr.fetchone(): if not cr.fetchone():
cr.execute( cr.execute(
"INSERT INTO openupgrade_attribute " "INSERT INTO upgrade_attribute "
"(name, value, record_id) VALUES (%s, %s, %s)", "(name, value, record_id) VALUES (%s, %s, %s)",
(key, value, record_id), (key, value, record_id),
) )
@ -295,7 +295,7 @@ def update_field_xmlid(model, field):
and rec["module"] != model.env.context["module"] and rec["module"] != model.env.context["module"]
and rec["module"] not in model.env.registry._init_modules and rec["module"] not in model.env.registry._init_modules
): ):
logging.getLogger(__name__).info( _logger.info(
"Moving XMLID for ir.model.fields record of %s#%s " "from %s to %s", "Moving XMLID for ir.model.fields record of %s#%s " "from %s to %s",
model._name, model._name,
rec["name"], rec["name"],
@ -308,9 +308,7 @@ def update_field_xmlid(model, field):
dict(rec, module=model.env.context["module"]), dict(rec, module=model.env.context["module"]),
) )
if model.env.cr.fetchone(): if model.env.cr.fetchone():
logging.getLogger(__name__).info( _logger.info("Aborting, an XMLID for this module already exists.")
"Aborting, an XMLID for this module already exists."
)
continue continue
model.env.cr.execute( model.env.cr.execute(
"UPDATE ir_model_data SET module=%(module)s " "WHERE id=%(xmlid_id)s", "UPDATE ir_model_data SET module=%(module)s " "WHERE id=%(xmlid_id)s",

View File

@ -1,10 +1,13 @@
# coding: utf-8
# Copyright 2011-2015 Therp BV <https://therp.nl> # Copyright 2011-2015 Therp BV <https://therp.nl>
# Copyright 2016 Opener B.V. <https://opener.am> # Copyright 2016 Opener B.V. <https://opener.am>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from openupgradelib.openupgrade_tools import table_exists from openupgradelib.openupgrade_tools import table_exists
_logger = logging.getLogger(__name__)
def log_xml_id(cr, module, xml_id): def log_xml_id(cr, module, xml_id):
""" """
@ -24,7 +27,7 @@ def log_xml_id(cr, module, xml_id):
get any meaningful results until the *second* time that you 'init' get any meaningful results until the *second* time that you 'init'
the module. the module.
- The good news is that the openupgrade_records module that comes - The good news is that the upgrade_analysis module that comes
with this distribution allows you to deal with all of this with with this distribution allows you to deal with all of this with
one click on the menu item Settings -> Customizations -> one click on the menu item Settings -> Customizations ->
Database Structure -> OpenUpgrade -> Generate Records Database Structure -> OpenUpgrade -> Generate Records
@ -36,25 +39,27 @@ def log_xml_id(cr, module, xml_id):
:param module: The module that contains the xml_id :param module: The module that contains the xml_id
:param xml_id: the xml_id, with or without 'module.' prefix :param xml_id: the xml_id, with or without 'module.' prefix
""" """
if not table_exists(cr, 'openupgrade_record'): if not table_exists(cr, "upgrade_record"):
return return
if '.' not in xml_id: if "." not in xml_id:
xml_id = '%s.%s' % (module, xml_id) xml_id = "{}.{}".format(module, xml_id)
cr.execute( cr.execute(
"SELECT model FROM ir_model_data " "SELECT model FROM ir_model_data " "WHERE module = %s AND name = %s",
"WHERE module = %s AND name = %s", xml_id.split("."),
xml_id.split('.')) )
record = cr.fetchone() record = cr.fetchone()
if not record: if not record:
print("Cannot find xml_id %s" % xml_id) _logger.warning("Cannot find xml_id %s" % xml_id)
return return
else: else:
cr.execute( cr.execute(
"SELECT id FROM openupgrade_record " "SELECT id FROM upgrade_record "
"WHERE module=%s AND model=%s AND name=%s AND type=%s", "WHERE module=%s AND model=%s AND name=%s AND type=%s",
(module, record[0], xml_id, 'xmlid')) (module, record[0], xml_id, "xmlid"),
)
if not cr.fetchone(): if not cr.fetchone():
cr.execute( cr.execute(
"INSERT INTO openupgrade_record " "INSERT INTO upgrade_record "
"(module, model, name, type) values(%s, %s, %s, %s)", "(module, model, name, type) values(%s, %s, %s, %s)",
(module, record[0], xml_id, 'xmlid')) (module, record[0], xml_id, "xmlid"),
)

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_upgrade_analysis_tree" model="ir.ui.view">
<field name="model">upgrade.analysis</field>
<field name="arch" type="xml">
<tree decoration-info="state == 'draft'">
<field name="config_id" />
<field name="analysis_date" />
<field name="state" />
</tree>
</field>
</record>
<record id="view_upgrade_analysis_form" model="ir.ui.view">
<field name="model">upgrade.analysis</field>
<field name="arch" type="xml">
<form create="false">
<header>
<field name="state" widget="statusbar" />
<button
name="analyze"
string="Perform Analysis"
type="object"
icon="fa-cogs"
colspan="2"
/>
</header>
<sheet>
<group col="4" colspan="4">
<field
name="config_id"
attrs="{'readonly': [('state', '=', 'done')]}"
/>
<field
name="write_files"
attrs="{'readonly': [('state', '=', 'done')]}"
/>
<field
name="analysis_date"
attrs="{'invisible': [('analysis_date', '=', False)]}"
/>
</group>
<group string="Log">
<field
name="log"
nolabel="1"
widget="ace"
options="{'mode': 'txt'}"
/>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_upgrade_analysis_tree" model="ir.actions.act_window">
<field name="name">Upgrade Analyses</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">upgrade.analysis</field>
</record>
<menuitem
action="action_upgrade_analysis_tree"
id="menu_upgrade_analysis"
name="Upgrade Analyses"
parent="menu_upgrade"
/>
</odoo>

View File

@ -17,6 +17,23 @@
<field name="model">upgrade.comparison.config</field> <field name="model">upgrade.comparison.config</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<header>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button
name="action_show_analysis"
type="object"
class="oe_stat_button"
icon="fa-users"
>
<field
string="Analyses"
name="analysis_qty"
widget="statinfo"
/>
</button>
</div>
<group> <group>
<field name="name" /> <field name="name" />
<field name="server" /> <field name="server" />
@ -24,6 +41,7 @@
<field name="database" /> <field name="database" />
<field name="username" /> <field name="username" />
<field name="password" /> <field name="password" />
<field name="version" />
</group> </group>
<button <button
name="test_connection" name="test_connection"
@ -34,22 +52,13 @@
/> />
<newline /> <newline />
<button <button
name="install_modules" name="new_analysis"
string="Mark uninstalled modules as in remote DB for installation, needs manual review and installation" string="New Analysis"
type="object"
icon="fa-cogs"
colspan="4"
/>
<newline />
<button
name="analyze"
string="Perform Analysis"
type="object" type="object"
icon="fa-cogs" icon="fa-cogs"
colspan="2" colspan="2"
/> />
<separator string="Last log" colspan="4" /> </sheet>
<field name="last_log" nolabel="1" colspan="4" />
</form> </form>
</field> </field>
</record> </record>

View File

@ -9,23 +9,18 @@
<field name="model" /> <field name="model" />
<field name="field" /> <field name="field" />
<field name="type" /> <field name="type" />
<separator />
<filter <filter
name="mode_create" name="filter_create"
string="Create mode" string="Create Mode"
domain="[('mode', '=', 'create')]" domain="[('mode', '=', 'create')]"
/> />
<filter <filter
name="mode_modify" name="filter_modify"
string="Modify mode" string="Modify Mode"
domain="[('mode', '=', 'modify')]" domain="[('mode', '=', 'modify')]"
/> />
<separator />
<group expand="1" string="Group By">
<filter name="group_by_module" context="{'group_by': 'module'}" /> <filter name="group_by_module" context="{'group_by': 'module'}" />
<filter name="group_by_model" context="{'group_by': 'model'}" /> <filter name="group_by_model" context="{'group_by': 'model'}" />
</group>
</search> </search>
</field> </field>
</record> </record>
@ -48,23 +43,24 @@
<field name="model">upgrade.record</field> <field name="model">upgrade.record</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<sheet>
<group col="4" colspan="4">
<field name="name" />
<field name="module" /> <field name="module" />
<field name="model" /> <field name="model" />
<field name="field" /> <field name="field" />
<field name="name" />
<field name="type" /> <field name="type" />
<field name="mode" /> <field name="mode" />
<separator string="Attributes" colspan="4" /> </group>
<field name="attribute_ids" mode="tree" nolabel="1" colspan="4"> <group string="Attributes">
<tree string="Attributes"> <field name="attribute_ids" nolabel="1" colspan="4">
<tree>
<field name="name" /> <field name="name" />
<field name="value" /> <field name="value" />
</tree> </tree>
<form string="Attribute">
<field name="name" />
<field name="value" />
</form>
</field> </field>
</group>
</sheet>
</form> </form>
</field> </field>
</record> </record>

View File

@ -1,3 +1,2 @@
from . import upgrade_analysis_wizard
from . import upgrade_generate_record_wizard from . import upgrade_generate_record_wizard
from . import upgrade_install_wizard from . import upgrade_install_wizard

View File

@ -2,7 +2,6 @@
# Copyright 2016 Opener B.V. <https://opener.am> # Copyright 2016 Opener B.V. <https://opener.am>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openupgradelib import openupgrade_tools
from odoo import _, fields, models from odoo import _, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
@ -12,44 +11,38 @@ from odoo.modules.registry import Registry
class GenerateWizard(models.TransientModel): class GenerateWizard(models.TransientModel):
_name = "upgrade.generate.record.wizard" _name = "upgrade.generate.record.wizard"
_description = "Upgrade Generate Record Wizard" _description = "Upgrade Generate Record Wizard"
_rec_name = "state"
state = fields.Selection([("init", "init"), ("ready", "ready")], default="init") state = fields.Selection([("draft", "Draft"), ("done", "Done")], default="draft")
def quirk_standard_calendar_attendances(self): # from openupgradelib import openupgrade_tools
"""Introduced in Odoo 13. The reinstallation causes a one2many value # TODO, SLG, make better a patch in odoo_patch
in [(0, 0, {})] format to be loaded on top of the first load, causing a # def quirk_standard_calendar_attendances(self):
violation of database constraint.""" # """Introduced in Odoo 13. The reinstallation causes a one2many value
for cal in ("resource_calendar_std_35h", "resource_calendar_std_38h"): # in [(0, 0, {})] format to be loaded on top of the first load, causing a
record = self.env.ref("resource.%s" % cal, False) # violation of database constraint."""
if record: # for cal in ("resource_calendar_std_35h", "resource_calendar_std_38h"):
record.attendance_ids.unlink() # record = self.env.ref("resource.%s" % cal, False)
# if record:
# record.attendance_ids.unlink()
# # Truncate the records table
# if openupgrade_tools.table_exists(
# self.env.cr, "upgrade_attribute"
# ) and openupgrade_tools.table_exists(self.env.cr, "upgrade_record"):
# self.env.cr.execute("TRUNCATE upgrade_attribute, upgrade_record;")
# # Run any quirks
# self.quirk_standard_calendar_attendances()
def generate(self): def generate(self):
"""Main wizard step. Make sure that all modules are up-to-date, """Reinitialize all installed modules.
then reinitialize all installed modules.
Equivalent of running the server with '-d <database> --init all' Equivalent of running the server with '-d <database> --init all'
The goal of this is to fill the records table. The goal of this is to fill the records table.
TODO: update module list and versions, then update all modules?""" TODO: update module list and versions, then update all modules?"""
# Truncate the records table
if openupgrade_tools.table_exists(
self.env.cr, "upgrade_attribute"
) and openupgrade_tools.table_exists(self.env.cr, "upgrade_record"):
self.env.cr.execute("TRUNCATE upgrade_attribute, upgrade_record;")
# Run any quirks # Check of all the modules are correctly installed
self.quirk_standard_calendar_attendances()
# Need to get all modules in state 'installed'
modules = self.env["ir.module.module"].search(
[("state", "in", ["to install", "to upgrade"])]
)
if modules:
self.env.cr.commit() # pylint: disable=invalid-commit
Registry.new(self.env.cr.dbname, update_module=True)
# Did we succeed above?
modules = self.env["ir.module.module"].search( modules = self.env["ir.module.module"].search(
[("state", "in", ["to install", "to upgrade"])] [("state", "in", ["to install", "to upgrade"])]
) )
@ -116,4 +109,4 @@ class GenerateWizard(models.TransientModel):
ORDER BY imd.name, imd.id""", ORDER BY imd.name, imd.id""",
) )
return self.write({"state": "ready"}) return self.write({"state": "done"})

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_upgrade_analysis_wizard_form" model="ir.ui.view">
<field name="model">upgrade.analysis.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<field name="server_config_id" readonly="1" />
<field name="state" />
<field
name="log"
colspan="4"
attrs="{'invisible': [('state', '!=', 'ready')]}"
/>
<field
name="write_files"
attrs="{'readonly': [('state', '!=', 'init')]}"
/>
</group>
<footer>
<button
string="Create"
name="get_communication"
type="object"
states="init"
class="btn-primary"
/>
<button special="cancel" string="Close" class="btn-default" />
</footer>
</form>
</field>
</record>
</odoo>

View File

@ -4,13 +4,15 @@
<record id="view_upgrade_generate_record_wizard_form" model="ir.ui.view"> <record id="view_upgrade_generate_record_wizard_form" model="ir.ui.view">
<field name="model">upgrade.generate.record.wizard</field> <field name="model">upgrade.generate.record.wizard</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="upgrade Generate Record Wizard"> <form>
<field name="state" invisible="1" /> <header>
<group states="init" colspan="4"> <field name="state" widget="statusbar" />
</header>
<group states="draft" colspan="4">
<p <p
>This will reinitialize all the modules installed on this database. Do not continue if you use this database in production.</p> >This will reinitialize all the modules installed on this database. Do not continue if you use this database in production.</p>
</group> </group>
<group states="ready" colspan="4"> <group states="done" colspan="4">
<p>Modules initialized and record created</p> <p>Modules initialized and record created</p>
</group> </group>
<footer> <footer>
@ -18,7 +20,7 @@
string="Continue" string="Continue"
name="generate" name="generate"
type="object" type="object"
states="init" states="draft"
class="btn-primary" class="btn-primary"
/> />
<button special="cancel" string="Close" class="btn-default" /> <button special="cancel" string="Close" class="btn-default" />

View File

@ -5,7 +5,9 @@
<field name="model">upgrade.install.wizard</field> <field name="model">upgrade.install.wizard</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<field name="state" /> <header>
<field name="state" widget="statusbar" />
</header>
<group states="draft"> <group states="draft">
<p <p
class="alert alert-warning" class="alert alert-warning"
@ -18,7 +20,7 @@
role="alert" role="alert"
>The modules have been installed successfuly</p> >The modules have been installed successfuly</p>
</group> </group>
<group col="5" states="draft"> <group col="4" states="draft">
<button <button
name="select_installable_modules" name="select_installable_modules"
type="object" type="object"
@ -27,7 +29,8 @@
<button <button
name="select_odoo_modules" name="select_odoo_modules"
type="object" type="object"
string="All Odoo SA Modules (OpenUpgrade)" string="All Odoo SA Modules"
class="btn-primary"
/> />
<button <button
name="select_oca_modules" name="select_oca_modules"
@ -39,11 +42,6 @@
type="object" type="object"
string="All Other Modules" string="All Other Modules"
/> />
<button
name="unselect_modules"
type="object"
string="Clear the list"
/>
</group> </group>
<group states="draft"> <group states="draft">
<field name="module_qty" /> <field name="module_qty" />
@ -52,6 +50,11 @@
widget="many2many_tags" widget="many2many_tags"
options="{'no_create': True}" options="{'no_create': True}"
/> />
<button
name="unselect_modules"
type="object"
string="Clear the list"
/>
</group> </group>
<footer> <footer>
<button <button