diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 97b9325df4e..0789d01b9f2 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -45,6 +45,12 @@ def ensure_module_state(env, modules, state): class Module(models.Model): _inherit = "ir.module.module" + def _module_exists_on_disk(self): + """Check if the module has a directory on the filesystem.""" + self.ensure_one() + module_path = get_module_path(self.name) + return bool(module_path and os.path.isdir(module_path)) + def _get_checksum_dir(self): self.ensure_one() @@ -84,6 +90,8 @@ def _save_installed_checksums(self): checksums = {} installed_modules = self.search([("state", "=", "installed")]) for module in installed_modules: + if not module._module_exists_on_disk(): + continue checksums[module.name] = module._get_checksum_dir() self._save_checksums(checksums) @@ -96,7 +104,8 @@ def _get_modules_with_changed_checksum(self): saved_checksums = self._get_saved_checksums() installed_modules = self.search([("state", "=", "installed")]) return installed_modules.filtered( - lambda r: r._get_checksum_dir() != saved_checksums.get(r.name), + lambda r: r._module_exists_on_disk() + and r._get_checksum_dir() != saved_checksums.get(r.name), ) @api.model diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index 6929b3cae53..a6233b20c13 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -80,6 +80,23 @@ def test_get_modules_with_changed_checksum(self): Imm._save_installed_checksums() self.assertFalse(Imm._get_modules_with_changed_checksum()) + def test_get_modules_with_changed_checksum_skips_db_only_modules(self): + """Skip modules that exist only in DB (no filesystem path).""" + Imm = self.env["ir.module.module"] + base_module = Imm.search([("name", "=", "base")]) + # Mock _module_exists_on_disk to simulate a diskless module + with mock.patch.object( + type(base_module), "_module_exists_on_disk", return_value=False + ): + self.assertFalse(base_module._module_exists_on_disk()) + # Save checksums — base should be skipped + Imm._save_installed_checksums() + saved_checksums = Imm._get_saved_checksums() + self.assertNotIn("base", saved_checksums) + # Changed checksum detection should not include it + changed = Imm._get_modules_with_changed_checksum() + self.assertNotIn(base_module, changed) + @odoo.tests.tagged("post_install", "-at_install") class TestModuleAfterInstall(TransactionCase):