[MIG] module_auto_update from 11 to 12
Use tagged to mark post install tests as previous mechanism seems to be broken.pull/2248/head
parent
f4588878da
commit
4fe1c0a110
|
@ -1,5 +1,4 @@
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
from . import wizards
|
|
||||||
from .hooks import uninstall_hook
|
from .hooks import uninstall_hook
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
{
|
{
|
||||||
'name': 'Module Auto Update',
|
'name': 'Module Auto Update',
|
||||||
'summary': 'Automatically update Odoo modules',
|
'summary': 'Automatically update Odoo modules',
|
||||||
'version': '11.0.2.0.4',
|
'version': '12.0.2.0.4',
|
||||||
'category': 'Extra Tools',
|
'category': 'Extra Tools',
|
||||||
'website': 'https://github.com/OCA/server-tools',
|
'website': 'https://github.com/OCA/server-tools',
|
||||||
'author': 'LasLabs, '
|
'author': 'LasLabs, '
|
||||||
|
@ -19,9 +19,6 @@
|
||||||
'depends': [
|
'depends': [
|
||||||
'base',
|
'base',
|
||||||
],
|
],
|
||||||
'data': [
|
|
||||||
'data/cron_data_deprecated.xml',
|
|
||||||
],
|
|
||||||
'development_status': 'Production/Stable',
|
'development_status': 'Production/Stable',
|
||||||
'maintainers': ['sbidoul'],
|
'maintainers': ['sbidoul'],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright 2017 LasLabs - Dave Lasley
|
|
||||||
Copyright 2017 Tecnativa - Jairo Llopis
|
|
||||||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
|
|
||||||
|
|
||||||
<odoo noupdate="1">
|
|
||||||
<record model="ir.cron" id="module_check_upgrades_cron">
|
|
||||||
<field name="name">Perform Module Upgrades</field>
|
|
||||||
<field name="active" eval="False"/>
|
|
||||||
<field name="user_id" ref="base.user_root"/>
|
|
||||||
<field name="interval_number">1</field>
|
|
||||||
<field name="interval_type">days</field>
|
|
||||||
<field name="numbercall">-1</field>
|
|
||||||
<field name="nextcall" eval="(DateTime.now() + timedelta(days= +1)).strftime('%Y-%m-%d 3:00:00')"/>
|
|
||||||
<field name="model_id" ref="base.model_base_module_upgrade"/>
|
|
||||||
<field name="state">code</field>
|
|
||||||
<field name="code">model.upgrade_module()</field>
|
|
||||||
|
|
||||||
</record>
|
|
||||||
</odoo>
|
|
|
@ -4,14 +4,8 @@
|
||||||
from odoo import SUPERUSER_ID, api
|
from odoo import SUPERUSER_ID, api
|
||||||
|
|
||||||
from .models.module import PARAM_INSTALLED_CHECKSUMS
|
from .models.module import PARAM_INSTALLED_CHECKSUMS
|
||||||
from .models.module_deprecated import PARAM_DEPRECATED
|
|
||||||
|
|
||||||
|
|
||||||
def uninstall_hook(cr, registry):
|
def uninstall_hook(cr, registry):
|
||||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
env["ir.config_parameter"].set_param(PARAM_INSTALLED_CHECKSUMS, False)
|
env["ir.config_parameter"].set_param(PARAM_INSTALLED_CHECKSUMS, False)
|
||||||
# TODO Remove from here when removing deprecated features
|
|
||||||
env["ir.config_parameter"].set_param(PARAM_DEPRECATED, False)
|
|
||||||
prefix = "module_auto_update.field_ir_module_module_checksum_%s"
|
|
||||||
fields = env.ref(prefix % "dir") | env.ref(prefix % "installed")
|
|
||||||
fields.with_context(_force_unlink=True).unlink()
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
# Copyright 2018 Tecnativa - Jairo Llopis
|
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
|
||||||
import logging
|
|
||||||
from psycopg2 import IntegrityError
|
|
||||||
from odoo.addons.module_auto_update.models.module_deprecated import \
|
|
||||||
PARAM_DEPRECATED
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate(cr, version):
|
|
||||||
"""Autoenable deprecated behavior."""
|
|
||||||
try:
|
|
||||||
with cr.savepoint():
|
|
||||||
cr.execute(
|
|
||||||
"""INSERT INTO ir_config_parameter (key, value)
|
|
||||||
VALUES (%s, '1')""",
|
|
||||||
(PARAM_DEPRECATED,)
|
|
||||||
)
|
|
||||||
_logger.warn("Deprecated features have been autoenabled, see "
|
|
||||||
"addon's README to know how to upgrade to the new "
|
|
||||||
"supported autoupdate mechanism.")
|
|
||||||
except IntegrityError:
|
|
||||||
_logger.info("Deprecated features setting exists, not autoenabling")
|
|
|
@ -1,4 +1,3 @@
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
from . import module
|
from . import module
|
||||||
from . import module_deprecated
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
# Copyright 2017 LasLabs Inc.
|
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
||||||
# pylint: disable=consider-merging-classes-inherited
|
|
||||||
|
|
||||||
from odoo import api, fields, models
|
|
||||||
|
|
||||||
PARAM_DEPRECATED = "module_auto_update.enable_deprecated"
|
|
||||||
|
|
||||||
|
|
||||||
class Module(models.Model):
|
|
||||||
_inherit = 'ir.module.module'
|
|
||||||
|
|
||||||
checksum_dir = fields.Char(
|
|
||||||
deprecated=True,
|
|
||||||
compute='_compute_checksum_dir',
|
|
||||||
)
|
|
||||||
checksum_installed = fields.Char(
|
|
||||||
deprecated=True,
|
|
||||||
compute='_compute_checksum_installed',
|
|
||||||
inverse='_inverse_checksum_installed',
|
|
||||||
store=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
@api.depends('name')
|
|
||||||
def _compute_checksum_dir(self):
|
|
||||||
for rec in self:
|
|
||||||
rec.checksum_dir = rec._get_checksum_dir()
|
|
||||||
|
|
||||||
def _compute_checksum_installed(self):
|
|
||||||
saved_checksums = self._get_saved_checksums()
|
|
||||||
for rec in self:
|
|
||||||
rec.checksum_installed = saved_checksums.get(rec.name, False)
|
|
||||||
|
|
||||||
def _inverse_checksum_installed(self):
|
|
||||||
checksums = self._get_saved_checksums()
|
|
||||||
for rec in self:
|
|
||||||
checksums[rec.name] = rec.checksum_installed
|
|
||||||
self._save_checksums(checksums)
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _store_checksum_installed(self, vals):
|
|
||||||
"""Store the right installed checksum, if addon is installed."""
|
|
||||||
if not self.env["base.module.upgrade"]._autoupdate_deprecated():
|
|
||||||
# Skip if deprecated features are disabled
|
|
||||||
return
|
|
||||||
if 'checksum_installed' not in vals:
|
|
||||||
try:
|
|
||||||
version = vals["latest_version"]
|
|
||||||
except KeyError:
|
|
||||||
return # Not [un]installing/updating any addon
|
|
||||||
if version is False:
|
|
||||||
# Uninstalling
|
|
||||||
self.write({'checksum_installed': False})
|
|
||||||
else:
|
|
||||||
# Installing or updating
|
|
||||||
for one in self:
|
|
||||||
one.checksum_installed = one.checksum_dir
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def create(self, vals):
|
|
||||||
res = super(Module, self).create(vals)
|
|
||||||
res._store_checksum_installed(vals)
|
|
||||||
return res
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def write(self, vals):
|
|
||||||
res = super(Module, self).write(vals)
|
|
||||||
self._store_checksum_installed(vals)
|
|
||||||
return res
|
|
|
@ -1,17 +0,0 @@
|
||||||
* Since version ``2.0.0``, some features have been deprecated.
|
|
||||||
When you upgrade from previous versions, these features will be kept for
|
|
||||||
backwards compatibility, but beware! They are buggy!
|
|
||||||
|
|
||||||
If you install this addon from scratch, these features are disabled by
|
|
||||||
default.
|
|
||||||
|
|
||||||
To force enabling or disabling the deprecated features, set a configuration
|
|
||||||
parameter called ``module_auto_update.enable_deprecated`` to either ``1``
|
|
||||||
or ``0``. It is recommended that you disable them.
|
|
||||||
|
|
||||||
Keep in mind that from this version, all upgrades are assumed to run in a
|
|
||||||
separate odoo instance, dedicated exclusively to upgrade Odoo.
|
|
||||||
|
|
||||||
* When migrating the addon to new versions, the deprecated features should be
|
|
||||||
removed. To make it simple all deprecated features are found in files
|
|
||||||
suffixed with ``_deprecated``.
|
|
|
@ -2,5 +2,3 @@
|
||||||
|
|
||||||
from . import test_addon_hash
|
from . import test_addon_hash
|
||||||
from . import test_module
|
from . import test_module
|
||||||
from . import test_module_deprecated
|
|
||||||
from . import test_module_upgrade_deprecated
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import tempfile
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
import odoo
|
||||||
from odoo.modules import get_module_path
|
from odoo.modules import get_module_path
|
||||||
from odoo.tests import common
|
from odoo.tests import TransactionCase
|
||||||
from odoo.tests.common import TransactionCase
|
|
||||||
|
|
||||||
from ..addon_hash import addon_hash
|
from ..addon_hash import addon_hash
|
||||||
from ..models.module import IncompleteUpgradeError, DEFAULT_EXCLUDE_PATTERNS
|
from ..models.module import IncompleteUpgradeError, DEFAULT_EXCLUDE_PATTERNS
|
||||||
|
@ -79,8 +79,7 @@ class TestModule(TransactionCase):
|
||||||
self.assertFalse(Imm._get_modules_with_changed_checksum())
|
self.assertFalse(Imm._get_modules_with_changed_checksum())
|
||||||
|
|
||||||
|
|
||||||
@common.at_install(False)
|
@odoo.tests.tagged('post_install', '-at_install')
|
||||||
@common.post_install(True)
|
|
||||||
class TestModuleAfterInstall(TransactionCase):
|
class TestModuleAfterInstall(TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -1,209 +0,0 @@
|
||||||
# Copyright 2017 LasLabs Inc.
|
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import mock
|
|
||||||
|
|
||||||
from odoo.modules import get_module_path
|
|
||||||
from odoo.tests.common import TransactionCase
|
|
||||||
from odoo.tools import mute_logger
|
|
||||||
|
|
||||||
from .. addon_hash import addon_hash
|
|
||||||
from ..models.module_deprecated import PARAM_DEPRECATED
|
|
||||||
|
|
||||||
|
|
||||||
model = 'odoo.addons.module_auto_update.models.module'
|
|
||||||
|
|
||||||
|
|
||||||
class EndTestException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TestModule(TransactionCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestModule, self).setUp()
|
|
||||||
module_name = 'module_auto_update'
|
|
||||||
self.env["ir.config_parameter"].set_param(PARAM_DEPRECATED, "1")
|
|
||||||
self.own_module = self.env['ir.module.module'].search([
|
|
||||||
('name', '=', module_name),
|
|
||||||
])
|
|
||||||
self.own_dir_path = get_module_path(module_name)
|
|
||||||
keep_langs = self.env['res.lang'].search([]).mapped('code')
|
|
||||||
self.own_checksum = addon_hash(
|
|
||||||
self.own_dir_path,
|
|
||||||
exclude_patterns=['*.pyc', '*.pyo', '*.pot', 'static/*'],
|
|
||||||
keep_langs=keep_langs,
|
|
||||||
)
|
|
||||||
self.own_writeable = os.access(self.own_dir_path, os.W_OK)
|
|
||||||
|
|
||||||
@mock.patch('%s.get_module_path' % model)
|
|
||||||
def create_test_module(self, vals, get_module_path_mock):
|
|
||||||
get_module_path_mock.return_value = self.own_dir_path
|
|
||||||
test_module = self.env['ir.module.module'].create(vals)
|
|
||||||
return test_module
|
|
||||||
|
|
||||||
def test_store_checksum_installed_state_installed(self):
|
|
||||||
"""It should set the module's checksum_installed equal to
|
|
||||||
checksum_dir when vals contain a ``latest_version`` str."""
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.own_module._store_checksum_installed({'latest_version': '1.0'})
|
|
||||||
self.assertEqual(
|
|
||||||
self.own_module.checksum_installed, self.own_module.checksum_dir,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_store_checksum_installed_state_uninstalled(self):
|
|
||||||
"""It should clear the module's checksum_installed when vals
|
|
||||||
contain ``"latest_version": False``"""
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.own_module._store_checksum_installed({'latest_version': False})
|
|
||||||
self.assertIs(self.own_module.checksum_installed, False)
|
|
||||||
|
|
||||||
def test_store_checksum_installed_vals_contain_checksum_installed(self):
|
|
||||||
"""It should not set checksum_installed to False or checksum_dir when
|
|
||||||
a checksum_installed is included in vals"""
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.own_module._store_checksum_installed({
|
|
||||||
'state': 'installed',
|
|
||||||
'checksum_installed': 'test',
|
|
||||||
})
|
|
||||||
self.assertEqual(
|
|
||||||
self.own_module.checksum_installed, 'test',
|
|
||||||
'Providing checksum_installed in vals did not prevent overwrite',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_store_checksum_installed_with_retain_context(self):
|
|
||||||
"""It should not set checksum_installed to False or checksum_dir when
|
|
||||||
self has context retain_checksum_installed=True"""
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.own_module.with_context(
|
|
||||||
retain_checksum_installed=True,
|
|
||||||
)._store_checksum_installed({'state': 'installed'})
|
|
||||||
self.assertEqual(
|
|
||||||
self.own_module.checksum_installed, 'test',
|
|
||||||
'Providing retain_checksum_installed context did not prevent '
|
|
||||||
'overwrite',
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch('%s.get_module_path' % model)
|
|
||||||
def test_button_uninstall_no_recompute(self, module_path_mock):
|
|
||||||
"""It should not attempt update on `button_uninstall`."""
|
|
||||||
module_path_mock.return_value = self.own_dir_path
|
|
||||||
vals = {
|
|
||||||
'name': 'module_auto_update_test_module',
|
|
||||||
'state': 'installed',
|
|
||||||
}
|
|
||||||
test_module = self.create_test_module(vals)
|
|
||||||
test_module.checksum_installed = 'test'
|
|
||||||
uninstall_module = self.env['ir.module.module'].search([
|
|
||||||
('name', '=', 'web'),
|
|
||||||
])
|
|
||||||
uninstall_module.button_uninstall()
|
|
||||||
self.assertNotEqual(
|
|
||||||
test_module.state, 'to upgrade',
|
|
||||||
'Auto update logic was triggered during uninstall.',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_button_immediate_uninstall_no_recompute(self):
|
|
||||||
"""It should not attempt update on `button_immediate_uninstall`."""
|
|
||||||
|
|
||||||
uninstall_module = self.env['ir.module.module'].search([
|
|
||||||
('name', '=', 'web'),
|
|
||||||
])
|
|
||||||
|
|
||||||
try:
|
|
||||||
mk = mock.MagicMock()
|
|
||||||
uninstall_module._patch_method('button_uninstall', mk)
|
|
||||||
mk.side_effect = EndTestException
|
|
||||||
with self.assertRaises(EndTestException):
|
|
||||||
uninstall_module.button_immediate_uninstall()
|
|
||||||
finally:
|
|
||||||
uninstall_module._revert_method('button_uninstall')
|
|
||||||
|
|
||||||
def test_button_uninstall_cancel(self):
|
|
||||||
"""It should preserve checksum_installed when cancelling uninstall"""
|
|
||||||
self.own_module.write({'state': 'to remove'})
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.own_module.button_uninstall_cancel()
|
|
||||||
self.assertEqual(
|
|
||||||
self.own_module.checksum_installed, 'test',
|
|
||||||
'Uninstall cancellation does not preserve checksum_installed',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_button_upgrade_cancel(self):
|
|
||||||
"""It should preserve checksum_installed when cancelling upgrades"""
|
|
||||||
self.own_module.write({'state': 'to upgrade'})
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.own_module.button_upgrade_cancel()
|
|
||||||
self.assertEqual(
|
|
||||||
self.own_module.checksum_installed, 'test',
|
|
||||||
'Upgrade cancellation does not preserve checksum_installed',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_create(self):
|
|
||||||
"""It should call _store_checksum_installed method"""
|
|
||||||
_store_checksum_installed_mock = mock.MagicMock()
|
|
||||||
try:
|
|
||||||
self.env['ir.module.module']._patch_method(
|
|
||||||
'_store_checksum_installed',
|
|
||||||
_store_checksum_installed_mock,
|
|
||||||
)
|
|
||||||
vals = {
|
|
||||||
'name': 'module_auto_update_test_module',
|
|
||||||
'state': 'installed',
|
|
||||||
}
|
|
||||||
self.create_test_module(vals)
|
|
||||||
_store_checksum_installed_mock.assert_called_once_with(vals)
|
|
||||||
finally:
|
|
||||||
self.env['ir.module.module']._revert_method(
|
|
||||||
'_store_checksum_installed',
|
|
||||||
)
|
|
||||||
|
|
||||||
@mute_logger("openerp.modules.module")
|
|
||||||
@mock.patch('%s.get_module_path' % model)
|
|
||||||
def test_get_module_list(self, module_path_mock):
|
|
||||||
"""It should change the state of modules with different
|
|
||||||
checksum_dir and checksum_installed to 'to upgrade'"""
|
|
||||||
module_path_mock.return_value = self.own_dir_path
|
|
||||||
vals = {
|
|
||||||
'name': 'module_auto_update_test_module',
|
|
||||||
'state': 'installed',
|
|
||||||
}
|
|
||||||
test_module = self.create_test_module(vals)
|
|
||||||
test_module.checksum_installed = 'test'
|
|
||||||
self.env['base.module.upgrade'].get_module_list()
|
|
||||||
self.assertEqual(
|
|
||||||
test_module.state, 'to upgrade',
|
|
||||||
'List update does not mark upgradeable modules "to upgrade"',
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch('%s.get_module_path' % model)
|
|
||||||
def test_get_module_list_only_changes_installed(self, module_path_mock):
|
|
||||||
"""It should not change the state of a module with a former state
|
|
||||||
other than 'installed' to 'to upgrade'"""
|
|
||||||
module_path_mock.return_value = self.own_dir_path
|
|
||||||
vals = {
|
|
||||||
'name': 'module_auto_update_test_module',
|
|
||||||
'state': 'uninstalled',
|
|
||||||
}
|
|
||||||
test_module = self.create_test_module(vals)
|
|
||||||
self.env['base.module.upgrade'].get_module_list()
|
|
||||||
self.assertNotEqual(
|
|
||||||
test_module.state, 'to upgrade',
|
|
||||||
'List update changed state of an uninstalled module',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_write(self):
|
|
||||||
"""It should call _store_checksum_installed method"""
|
|
||||||
_store_checksum_installed_mock = mock.MagicMock()
|
|
||||||
self.env['ir.module.module']._patch_method(
|
|
||||||
'_store_checksum_installed',
|
|
||||||
_store_checksum_installed_mock,
|
|
||||||
)
|
|
||||||
vals = {'state': 'installed'}
|
|
||||||
self.own_module.write(vals)
|
|
||||||
_store_checksum_installed_mock.assert_called_once_with(vals)
|
|
||||||
self.env['ir.module.module']._revert_method(
|
|
||||||
'_store_checksum_installed',
|
|
||||||
)
|
|
|
@ -1,46 +0,0 @@
|
||||||
# Copyright 2017 LasLabs Inc.
|
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
||||||
|
|
||||||
import mock
|
|
||||||
|
|
||||||
from odoo.modules import get_module_path
|
|
||||||
from odoo.modules.registry import Registry
|
|
||||||
from odoo.tests.common import TransactionCase
|
|
||||||
|
|
||||||
from ..models.module_deprecated import PARAM_DEPRECATED
|
|
||||||
|
|
||||||
|
|
||||||
class TestModuleUpgrade(TransactionCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestModuleUpgrade, self).setUp()
|
|
||||||
module_name = 'module_auto_update'
|
|
||||||
self.env["ir.config_parameter"].set_param(PARAM_DEPRECATED, "1")
|
|
||||||
self.own_module = self.env['ir.module.module'].search([
|
|
||||||
('name', '=', module_name),
|
|
||||||
])
|
|
||||||
self.own_dir_path = get_module_path(module_name)
|
|
||||||
|
|
||||||
def test_upgrade_module_cancel(self):
|
|
||||||
"""It should preserve checksum_installed when cancelling upgrades"""
|
|
||||||
self.own_module.write({'state': 'to upgrade'})
|
|
||||||
self.own_module.checksum_installed = 'test'
|
|
||||||
self.env['base.module.upgrade'].upgrade_module_cancel()
|
|
||||||
self.assertEqual(
|
|
||||||
self.own_module.checksum_installed, 'test',
|
|
||||||
'Upgrade cancellation does not preserve checksum_installed',
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch.object(Registry, 'new')
|
|
||||||
def test_upgrade_module(self, new_mock):
|
|
||||||
"""Calls get_module_list when upgrading in api.model mode"""
|
|
||||||
get_module_list_mock = mock.MagicMock()
|
|
||||||
try:
|
|
||||||
self.env['base.module.upgrade']._patch_method(
|
|
||||||
'get_module_list',
|
|
||||||
get_module_list_mock,
|
|
||||||
)
|
|
||||||
self.env['base.module.upgrade'].upgrade_module()
|
|
||||||
get_module_list_mock.assert_called_once_with()
|
|
||||||
finally:
|
|
||||||
self.env['base.module.upgrade']._revert_method('get_module_list')
|
|
|
@ -1,3 +0,0 @@
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
||||||
|
|
||||||
from . import module_upgrade_deprecated
|
|
|
@ -1,84 +0,0 @@
|
||||||
# Copyright 2017 LasLabs Inc.
|
|
||||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from odoo import api, models
|
|
||||||
|
|
||||||
from ..models.module_deprecated import PARAM_DEPRECATED
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleUpgrade(models.TransientModel):
|
|
||||||
_inherit = 'base.module.upgrade'
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _autoupdate_deprecated(self):
|
|
||||||
"""Know if we should enable deprecated features."""
|
|
||||||
deprecated = (
|
|
||||||
self.env["ir.config_parameter"].get_param(PARAM_DEPRECATED))
|
|
||||||
if deprecated is False:
|
|
||||||
# Enable deprecated features if this is the 1st automated update
|
|
||||||
# after the version that deprecated them (X.Y.2.0.0)
|
|
||||||
own_module = self.env["ir.module.module"].search([
|
|
||||||
("name", "=", "module_auto_update"),
|
|
||||||
])
|
|
||||||
try:
|
|
||||||
if own_module.latest_version.split(".")[2] == "1":
|
|
||||||
deprecated = "1"
|
|
||||||
except AttributeError:
|
|
||||||
pass # 1st install, there's no latest_version
|
|
||||||
return deprecated == "1"
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def get_module_list(self):
|
|
||||||
"""Set modules to upgrade searching by their dir checksum."""
|
|
||||||
if self._autoupdate_deprecated():
|
|
||||||
Module = self.env["ir.module.module"]
|
|
||||||
installed_modules = Module.search([('state', '=', 'installed')])
|
|
||||||
upgradeable_modules = installed_modules.filtered(
|
|
||||||
lambda r: r.checksum_dir != r.checksum_installed,
|
|
||||||
)
|
|
||||||
upgradeable_modules.button_upgrade()
|
|
||||||
return super(ModuleUpgrade, self).get_module_list()
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def upgrade_module(self):
|
|
||||||
"""Make a fully automated addon upgrade."""
|
|
||||||
if self._autoupdate_deprecated():
|
|
||||||
_logger.warning(
|
|
||||||
"You are possibly using an unsupported upgrade system; "
|
|
||||||
"set '%s' system parameter to '0' and start calling "
|
|
||||||
"`env['ir.module.module'].upgrade_changed_checksum()` from "
|
|
||||||
"now on to get rid of this message. See module's README's "
|
|
||||||
"Known Issues section for further information on the matter."
|
|
||||||
)
|
|
||||||
# Compute updates by checksum when called in @api.model fashion
|
|
||||||
self.env.cr.autocommit(True) # Avoid transaction lock
|
|
||||||
if not self:
|
|
||||||
self.get_module_list()
|
|
||||||
Module = self.env["ir.module.module"]
|
|
||||||
# Get every addon state before updating
|
|
||||||
pre_states = {addon["name"]: addon["state"] for addon
|
|
||||||
in Module.search_read([], ["name", "state"])}
|
|
||||||
# Perform upgrades, possibly in a limited graph that excludes me
|
|
||||||
result = super(ModuleUpgrade, self).upgrade_module()
|
|
||||||
if self._autoupdate_deprecated():
|
|
||||||
self.env.cr.autocommit(False)
|
|
||||||
# Reload environments, anything may have changed
|
|
||||||
self.env.clear()
|
|
||||||
# Update addons checksum if state changed and I wasn't uninstalled
|
|
||||||
own = Module.search_read(
|
|
||||||
[("name", "=", "module_auto_update")],
|
|
||||||
["state"],
|
|
||||||
limit=1)
|
|
||||||
if own and own[0]["state"] != "uninstalled":
|
|
||||||
for addon in Module.search([]):
|
|
||||||
if addon.state != pre_states.get(addon.name):
|
|
||||||
# Trigger the write hook that should have been
|
|
||||||
# triggered when the module was [un]installed/updated
|
|
||||||
# in the limited module graph inside above call to
|
|
||||||
# super(), and updates its dir checksum as needed
|
|
||||||
addon.latest_version = addon.latest_version
|
|
||||||
return result
|
|
Loading…
Reference in New Issue