Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions module_auto_update/models/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def ensure_module_state(env, modules, state):
if not modules:
return
env.cr.execute(
"SELECT name FROM ir_module_module " "WHERE id IN %s AND state != %s",
"SELECT name FROM ir_module_module WHERE id IN %s AND state != %s",
(tuple(modules.ids), state),
)
names = [r[0] for r in env.cr.fetchall()]
Expand Down Expand Up @@ -78,22 +78,47 @@ def _save_checksums(self, checksums):
Icp.set_param(PARAM_INSTALLED_CHECKSUMS, json.dumps(checksums))
Icp.flush_model()

@api.model
def _not_imported_domain(self):
"""Domain excluding modules that only exist in the database.

Imported modules (Odoo Studio customizations, modules uploaded through
the web interface) have no counterpart on the file system, so no
checksum can be computed for them.

The ``imported`` field is added by ``base_import_module``, which is not
a dependency of this module. When it is not installed, no module can be
imported in the first place, so no filtering is needed.
"""
if "imported" in self._fields:
return [("imported", "=", False)]
return []

@api.model
def _save_installed_checksums(self):
checksums = {}
installed_modules = self.search([("state", "=", "installed")])
installed_modules = self.search(
[("state", "=", "installed"), *self._not_imported_domain()]
)
for module in installed_modules:
checksums[module.name] = module._get_checksum_dir()
self._save_checksums(checksums)

@api.model
def _get_modules_partially_installed(self):
return self.search([("state", "in", ("to install", "to remove", "to upgrade"))])
return self.search(
[
("state", "in", ["to install", "to remove", "to upgrade"]),
*self._not_imported_domain(),
]
)

@api.model
def _get_modules_with_changed_checksum(self):
saved_checksums = self._get_saved_checksums()
installed_modules = self.search([("state", "=", "installed")])
installed_modules = self.search(
[("state", "=", "installed"), *self._not_imported_domain()]
)
return installed_modules.filtered(
lambda r: r._get_checksum_dir() != saved_checksums.get(r.name),
)
Expand Down
36 changes: 36 additions & 0 deletions module_auto_update/tests/test_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,42 @@ def test_get_modules_with_changed_checksum(self):
self.assertFalse(Imm._get_modules_with_changed_checksum())


class TestImportedModules(TransactionCase):
def setUp(self):
super().setUp()
self.Imm = self.env["ir.module.module"]
# Skip test if base_import_module is not installed (OCB)
if "imported" not in self.Imm._fields:
self.skipTest("base_import_module is not installed")
# Modules imported into the database (e.g. Odoo Studio customizations)
# have no counterpart on the file system, so no checksum can be
# computed for them.
self.imported_module = self.Imm.create(
{
"name": "test_imported_module",
"state": "installed",
"imported": True,
}
)

def test_save_installed_checksums_skips_imported(self):
self.Imm._save_installed_checksums()
self.assertNotIn("test_imported_module", self.Imm._get_saved_checksums())

def test_changed_checksum_skips_imported(self):
# no checksum was ever saved for the imported module
self.Imm._save_checksums({})
self.assertNotIn(
self.imported_module, self.Imm._get_modules_with_changed_checksum()
)

def test_partially_installed_skips_imported(self):
self.imported_module.state = "to upgrade"
self.assertNotIn(
self.imported_module, self.Imm._get_modules_partially_installed()
)


@odoo.tests.tagged("post_install", "-at_install")
class TestModuleAfterInstall(TransactionCase):
def setUp(self):
Expand Down
Loading