From d020e4477bbdd78ed2278ddc667a9071ef2a6461 Mon Sep 17 00:00:00 2001 From: Brenton Hughes Date: Thu, 20 Jul 2017 00:28:37 -0700 Subject: [PATCH 1/6] [ADD] module_auto_update: Create module (#882) * [IMP] module_auto_update: Create new module * Add checksum_dir and checksum_installed fields to ir.module.module * Add checksum_dir to compute current checksum of module directory in addons path * Add checksum_installed to store checksum of module directory when module was last installed or upgraded * Use checksumdir Python library to compute module directory sha1 hashes, ignoring pyc and pyo extensions * Extend update_list method to compare modules' checksum_dir and checksum_installed, then change state of modules with differing checksums to 'to upgrade' * Replace Apps/Updates menu item with menu item of same name, which updates apps list and displays tree view of ir.module.module records with state 'to upgrade' * Extend create and write methods to store computed checksum_dir as checksum_installed during module installation and upgrade, and set checksum_installed to False on uninstall * Use context to stop checksum_installed from being updated during upgrade/uninstall cancellation * Add cron job to periodically check for module upgrades by comparing checksums, then perform any available upgrades * Extend upgrade_module method (called by cron and 'Apply Scheduled Upgrades' menu item) to call update_list * Add post_init_hook to store checksum_installed of existing modules * Add test coverage * [FIX] module_auto_update: Fix test broken by changes * Use dummy module to test update_list method instead of module_auto_update --- module_auto_update/README.rst | 76 +++++++ module_auto_update/__init__.py | 7 + module_auto_update/__manifest__.py | 30 +++ module_auto_update/data/cron_data.xml | 15 ++ module_auto_update/hooks.py | 14 ++ module_auto_update/models/__init__.py | 5 + module_auto_update/models/module.py | 83 +++++++ module_auto_update/tests/__init__.py | 6 + module_auto_update/tests/test_module.py | 212 ++++++++++++++++++ .../tests/test_module_upgrade.py | 42 ++++ module_auto_update/views/module_views.xml | 49 ++++ module_auto_update/wizards/__init__.py | 5 + module_auto_update/wizards/module_upgrade.py | 21 ++ 13 files changed, 565 insertions(+) create mode 100644 module_auto_update/README.rst create mode 100644 module_auto_update/__init__.py create mode 100644 module_auto_update/__manifest__.py create mode 100644 module_auto_update/data/cron_data.xml create mode 100644 module_auto_update/hooks.py create mode 100644 module_auto_update/models/__init__.py create mode 100644 module_auto_update/models/module.py create mode 100644 module_auto_update/tests/__init__.py create mode 100644 module_auto_update/tests/test_module.py create mode 100644 module_auto_update/tests/test_module_upgrade.py create mode 100644 module_auto_update/views/module_views.xml create mode 100644 module_auto_update/wizards/__init__.py create mode 100644 module_auto_update/wizards/module_upgrade.py diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst new file mode 100644 index 000000000..3535f4fb2 --- /dev/null +++ b/module_auto_update/README.rst @@ -0,0 +1,76 @@ +.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +================== +Module Auto Update +================== + +This module will automatically check for and apply module upgrades on a schedule. + +Upgrade checking is accomplished by comparing the SHA1 checksums of currently-installed modules to the checksums of corresponding modules in the addons directories. + +Installation +============ + +Prior to installing this module, you need to: + +#. Install checksumdir with `pip install checksumdir` +#. Ensure all installed modules are up-to-date. When installed, this module will assume the versions found in the addons directories are currently installed. + +Configuration +============= + +The default time for checking and applying upgrades is 3:00 AM (UTC). To change this schedule, modify the "Perform Module Upgrades" scheduled action. + +This module will ignore .pyc and .pyo file extensions by default. To modify this, create a module_auto_update.checksum_excluded_extensions system parameter with the desired extensions listed as comma-separated values. + +Usage +===== + +Modules scheduled for upgrade can be viewed by clicking the "Updates" menu item in the Apps sidebar. + +To perform upgrades manually, click the "Apply Scheduled Upgrades" menu item in the Apps sidebar. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/149/10.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Brent Hughes +* Juan José Scarafía + +Do not contact contributors directly about support or help with technical issues. + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/module_auto_update/__init__.py b/module_auto_update/__init__.py new file mode 100644 index 000000000..36f555442 --- /dev/null +++ b/module_auto_update/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import models +from . import wizards +from .hooks import post_init_hook diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py new file mode 100644 index 000000000..db65d269a --- /dev/null +++ b/module_auto_update/__manifest__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + 'name': 'Module Auto Update', + 'summary': 'Automatically update Odoo modules', + 'version': '10.0.1.0.0', + 'category': 'Extra Tools', + 'website': 'https://odoo-community.org/', + 'author': 'LasLabs, ' + 'Juan José Scarafía, ' + 'Odoo Community Association (OCA)', + 'license': 'LGPL-3', + 'application': False, + 'installable': True, + 'post_init_hook': 'post_init_hook', + 'external_dependencies': { + 'python': [ + 'checksumdir', + ], + }, + 'depends': [ + 'base', + ], + 'data': [ + 'views/module_views.xml', + 'data/cron_data.xml', + ], +} diff --git a/module_auto_update/data/cron_data.xml b/module_auto_update/data/cron_data.xml new file mode 100644 index 000000000..1745fe0c9 --- /dev/null +++ b/module_auto_update/data/cron_data.xml @@ -0,0 +1,15 @@ + + + + Perform Module Upgrades + + + 1 + days + -1 + + base.module.upgrade + upgrade_module + + + diff --git a/module_auto_update/hooks.py b/module_auto_update/hooks.py new file mode 100644 index 000000000..f062966c3 --- /dev/null +++ b/module_auto_update/hooks.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import SUPERUSER_ID, api + + +def post_init_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + installed_modules = env['ir.module.module'].search([ + ('state', '=', 'installed'), + ]) + for r in installed_modules: + r.checksum_installed = r.checksum_dir diff --git a/module_auto_update/models/__init__.py b/module_auto_update/models/__init__.py new file mode 100644 index 000000000..b27944126 --- /dev/null +++ b/module_auto_update/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import module diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py new file mode 100644 index 000000000..4d9ccec59 --- /dev/null +++ b/module_auto_update/models/module.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging + +from odoo import api, fields, models +from odoo.modules.module import get_module_path + +_logger = logging.getLogger(__name__) +try: + from checksumdir import dirhash +except ImportError: + _logger.debug('Cannot `import checksumdir`.') + + +class Module(models.Model): + _inherit = 'ir.module.module' + + checksum_dir = fields.Char( + compute='_compute_checksum_dir', + ) + checksum_installed = fields.Char() + + @api.depends('name') + def _compute_checksum_dir(self): + exclude = self.env["ir.config_parameter"].get_param( + "module_auto_update.checksum_excluded_extensions", + "pyc,pyo", + ).split(",") + + for r in self: + r.checksum_dir = dirhash( + get_module_path(r.name), + 'sha1', + excluded_extensions=exclude, + ) + + def _store_checksum_installed(self, vals): + if self.env.context.get('retain_checksum_installed'): + return + if 'checksum_installed' not in vals: + if vals.get('state') == 'installed': + for r in self: + r.checksum_installed = r.checksum_dir + elif vals.get('state') == 'uninstalled': + self.write({'checksum_installed': False}) + + @api.multi + def button_uninstall_cancel(self): + return super( + Module, + self.with_context(retain_checksum_installed=True), + ).button_uninstall_cancel() + + @api.multi + def button_upgrade_cancel(self): + return super( + Module, + self.with_context(retain_checksum_installed=True), + ).button_upgrade_cancel() + + @api.model + def create(self, vals): + res = super(Module, self).create(vals) + res._store_checksum_installed(vals) + return res + + @api.model + def update_list(self): + res = super(Module, self).update_list() + installed_modules = self.search([('state', '=', 'installed')]) + upgradeable_modules = installed_modules.filtered( + lambda r: r.checksum_dir != r.checksum_installed, + ) + upgradeable_modules.write({'state': "to upgrade"}) + return res + + @api.multi + def write(self, vals): + res = super(Module, self).write(vals) + self._store_checksum_installed(vals) + return res diff --git a/module_auto_update/tests/__init__.py b/module_auto_update/tests/__init__.py new file mode 100644 index 000000000..237970451 --- /dev/null +++ b/module_auto_update/tests/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import test_module +from . import test_module_upgrade diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py new file mode 100644 index 000000000..5d499fc27 --- /dev/null +++ b/module_auto_update/tests/test_module.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging +import tempfile + +import mock + +from odoo.modules import get_module_path +from odoo.tests.common import TransactionCase + +from .. import post_init_hook + +_logger = logging.getLogger(__name__) +try: + from checksumdir import dirhash +except ImportError: + _logger.debug('Cannot `import checksumdir`.') + +model = 'odoo.addons.module_auto_update.models.module' + + +class TestModule(TransactionCase): + + def setUp(self): + super(TestModule, self).setUp() + module_name = 'module_auto_update' + self.own_module = self.env['ir.module.module'].search([ + ('name', '=', module_name), + ]) + self.own_dir_path = get_module_path(module_name) + self.own_checksum = dirhash( + self.own_dir_path, + 'sha1', + excluded_extensions=['pyc', 'pyo'], + ) + + @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_compute_checksum_dir(self): + """It should compute the directory's SHA-1 hash""" + self.assertEqual( + self.own_module.checksum_dir, self.own_checksum, + 'Module directory checksum not computed properly', + ) + + def test_compute_checksum_dir_ignore_excluded(self): + """It should exclude .pyc/.pyo extensions from checksum + calculations""" + with tempfile.NamedTemporaryFile( + suffix='.pyc', dir=self.own_dir_path): + self.assertEqual( + self.own_module.checksum_dir, self.own_checksum, + 'SHA1 checksum does not ignore excluded extensions', + ) + + def test_compute_checksum_dir_recomputes_when_file_added(self): + """It should return a different value when a non-.pyc/.pyo file is + added to the module directory""" + with tempfile.NamedTemporaryFile( + suffix='.py', dir=self.own_dir_path): + self.assertNotEqual( + self.own_module.checksum_dir, self.own_checksum, + 'SHA1 checksum not recomputed', + ) + + def test_store_checksum_installed_state_installed(self): + """It should set the module's checksum_installed equal to + checksum_dir when vals contain state 'installed'""" + self.own_module.checksum_installed = 'test' + self.own_module._store_checksum_installed({'state': 'installed'}) + self.assertEqual( + self.own_module.checksum_installed, self.own_module.checksum_dir, + 'Setting state to installed does not store checksum_dir ' + 'as checksum_installed', + ) + + def test_store_checksum_installed_state_uninstalled(self): + """It should clear the module's checksum_installed when vals + contain state 'uninstalled'""" + self.own_module.checksum_installed = 'test' + self.own_module._store_checksum_installed({'state': 'uninstalled'}) + self.assertEqual( + self.own_module.checksum_installed, False, + 'Setting state to uninstalled does not clear checksum_installed', + ) + + 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', + ) + + 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() + 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) + self.env['ir.module.module']._revert_method( + '_store_checksum_installed', + ) + + @mock.patch('%s.get_module_path' % model) + def test_update_list(self, get_module_path_mock): + """It should change the state of modules with different + checksum_dir and checksum_installed to 'to upgrade'""" + get_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['ir.module.module'].update_list() + self.assertEqual( + test_module.state, 'to upgrade', + 'List update does not mark upgradeable modules "to upgrade"', + ) + + def test_update_list_only_changes_installed(self): + """It should not change the state of a module with a former state + other than 'installed' to 'to upgrade'""" + vals = { + 'name': 'module_auto_update_test_module', + 'state': 'uninstalled', + } + test_module = self.create_test_module(vals) + self.env['ir.module.module'].update_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', + ) + + def test_post_init_hook(self): + """It should set checksum_installed equal to checksum_dir for all + installed modules""" + installed_modules = self.env['ir.module.module'].search([ + ('state', '=', 'installed'), + ]) + post_init_hook(self.env.cr, None) + self.assertListEqual( + installed_modules.mapped('checksum_dir'), + installed_modules.mapped('checksum_installed'), + 'Installed modules did not have checksum_installed stored', + ) diff --git a/module_auto_update/tests/test_module_upgrade.py b/module_auto_update/tests/test_module_upgrade.py new file mode 100644 index 000000000..edc24fd8e --- /dev/null +++ b/module_auto_update/tests/test_module_upgrade.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# 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 + + +class TestModuleUpgrade(TransactionCase): + + def setUp(self): + super(TestModuleUpgrade, self).setUp() + module_name = 'module_auto_update' + 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): + """It should call update_list method on ir.module.module""" + update_list_mock = mock.MagicMock() + self.env['ir.module.module']._patch_method( + 'update_list', + update_list_mock, + ) + self.env['base.module.upgrade'].upgrade_module() + update_list_mock.assert_called_once_with() + self.env['ir.module.module']._revert_method('update_list') diff --git a/module_auto_update/views/module_views.xml b/module_auto_update/views/module_views.xml new file mode 100644 index 000000000..78a0be51e --- /dev/null +++ b/module_auto_update/views/module_views.xml @@ -0,0 +1,49 @@ + + + + + updates.module.search + ir.module.module + + + + + + + + + + + Open Updates and Update Apps List Server Action + + + if model.update_list(): + action = { + 'name': 'Updates', + 'type': 'ir.actions.act_window', + 'res_model': 'ir.module.module', + 'view_type': 'form', + 'view_mode': 'tree,form', + 'target': 'main', + 'context': '{"search_default_scheduled_upgrades": 1}', + } + + + + + + + + + + + + + + diff --git a/module_auto_update/wizards/__init__.py b/module_auto_update/wizards/__init__.py new file mode 100644 index 000000000..58cb00103 --- /dev/null +++ b/module_auto_update/wizards/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import module_upgrade diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py new file mode 100644 index 000000000..e9b69e07c --- /dev/null +++ b/module_auto_update/wizards/module_upgrade.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import api, models + + +class ModuleUpgrade(models.TransientModel): + _inherit = 'base.module.upgrade' + + @api.multi + def upgrade_module_cancel(self): + return super( + ModuleUpgrade, + self.with_context(retain_checksum_installed=True), + ).upgrade_module_cancel() + + @api.multi + def upgrade_module(self): + self.env['ir.module.module'].update_list() + super(ModuleUpgrade, self).upgrade_module() From 6e41b7b932854b946f298ab5ec232d25d21db567 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 22 Jul 2017 10:29:49 +0200 Subject: [PATCH 2/6] OCA Transbot updated translations from Transifex --- module_auto_update/i18n/ca.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/de.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/es.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/es_MX.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/hr.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/it.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/nl_NL.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/pt_BR.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/sl.po | 59 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/tr.po | 59 ++++++++++++++++++++++++++++++++ 10 files changed, 590 insertions(+) create mode 100644 module_auto_update/i18n/ca.po create mode 100644 module_auto_update/i18n/de.po create mode 100644 module_auto_update/i18n/es.po create mode 100644 module_auto_update/i18n/es_MX.po create mode 100644 module_auto_update/i18n/hr.po create mode 100644 module_auto_update/i18n/it.po create mode 100644 module_auto_update/i18n/nl_NL.po create mode 100644 module_auto_update/i18n/pt_BR.po create mode 100644 module_auto_update/i18n/sl.po create mode 100644 module_auto_update/i18n/tr.po diff --git a/module_auto_update/i18n/ca.po b/module_auto_update/i18n/ca.po new file mode 100644 index 000000000..90b967e03 --- /dev/null +++ b/module_auto_update/i18n/ca.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Catalan (https://www.transifex.com/oca/teams/23907/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Mòdul" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/de.po b/module_auto_update/i18n/de.po new file mode 100644 index 000000000..0938aac2a --- /dev/null +++ b/module_auto_update/i18n/de.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# Niki Waibel , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: Niki Waibel , 2017\n" +"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Modul" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "Modul aktualisieren" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/es.po b/module_auto_update/i18n/es.po new file mode 100644 index 000000000..a318b0947 --- /dev/null +++ b/module_auto_update/i18n/es.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# Pedro M. Baeza , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: Pedro M. Baeza , 2017\n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Módulo" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "Actualización de módulo" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/es_MX.po b/module_auto_update/i18n/es_MX.po new file mode 100644 index 000000000..6a52834e7 --- /dev/null +++ b/module_auto_update/i18n/es_MX.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (Mexico) (https://www.transifex.com/oca/teams/23907/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Módulo" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/hr.po b/module_auto_update/i18n/hr.po new file mode 100644 index 000000000..7cae9d5f4 --- /dev/null +++ b/module_auto_update/i18n/hr.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# Bole , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: Bole , 2017\n" +"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Modul" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/it.po b/module_auto_update/i18n/it.po new file mode 100644 index 000000000..91f03c624 --- /dev/null +++ b/module_auto_update/i18n/it.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Modulo" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/nl_NL.po b/module_auto_update/i18n/nl_NL.po new file mode 100644 index 000000000..340b85847 --- /dev/null +++ b/module_auto_update/i18n/nl_NL.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# Peter Hageman , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: Peter Hageman , 2017\n" +"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/teams/23907/nl_NL/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: nl_NL\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Module" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/pt_BR.po b/module_auto_update/i18n/pt_BR.po new file mode 100644 index 000000000..aef834e1b --- /dev/null +++ b/module_auto_update/i18n/pt_BR.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/teams/23907/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Módulo" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/sl.po b/module_auto_update/i18n/sl.po new file mode 100644 index 000000000..b14fb1443 --- /dev/null +++ b/module_auto_update/i18n/sl.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Modul" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" diff --git a/module_auto_update/i18n/tr.po b/module_auto_update/i18n/tr.po new file mode 100644 index 000000000..2b6b538a1 --- /dev/null +++ b/module_auto_update/i18n/tr.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-21 02:43+0000\n" +"PO-Revision-Date: 2017-07-21 02:43+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir +msgid "Checksum dir" +msgstr "" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum installed" +msgstr "" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_ir_module_module +msgid "Module" +msgstr "Modül" + +#. module: module_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_action_open_updates +msgid "Open Updates and Update Apps List Server Action" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "" From f4305bc884d88e35c0dbeea0a5d43d08c0cafb1f Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 1 Aug 2017 12:22:54 +0200 Subject: [PATCH 3/6] [MIG][module_auto_update] Backport from v10 --- module_auto_update/README.rst | 3 +- .../{__manifest__.py => __openerp__.py} | 2 +- module_auto_update/hooks.py | 2 +- module_auto_update/models/module.py | 36 +++++++++++-------- module_auto_update/tests/test_module.py | 10 +++--- .../tests/test_module_upgrade.py | 8 ++--- module_auto_update/wizards/module_upgrade.py | 4 +-- requirements.txt | 1 + 8 files changed, 38 insertions(+), 28 deletions(-) rename module_auto_update/{__manifest__.py => __openerp__.py} (96%) diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index 3535f4fb2..4a6a4c4cd 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -34,7 +34,7 @@ To perform upgrades manually, click the "Apply Scheduled Upgrades" menu item in .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/149/10.0 + :target: https://runbot.odoo-community.org/runbot/149/9.0 Bug Tracker =========== @@ -57,6 +57,7 @@ Contributors * Brent Hughes * Juan José Scarafía +* Jairo Llopis Do not contact contributors directly about support or help with technical issues. diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__openerp__.py similarity index 96% rename from module_auto_update/__manifest__.py rename to module_auto_update/__openerp__.py index db65d269a..1cbd4d0be 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__openerp__.py @@ -5,7 +5,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '10.0.1.0.0', + 'version': '9.0.1.0.0', 'category': 'Extra Tools', 'website': 'https://odoo-community.org/', 'author': 'LasLabs, ' diff --git a/module_auto_update/hooks.py b/module_auto_update/hooks.py index f062966c3..5a05d0d23 100644 --- a/module_auto_update/hooks.py +++ b/module_auto_update/hooks.py @@ -2,7 +2,7 @@ # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import SUPERUSER_ID, api +from openerp import SUPERUSER_ID, api def post_init_hook(cr, registry): diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 4d9ccec59..22c608ab9 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -4,8 +4,8 @@ import logging -from odoo import api, fields, models -from odoo.modules.module import get_module_path +from openerp import api, fields, models +from openerp.modules.module import get_module_path _logger = logging.getLogger(__name__) try: @@ -30,11 +30,15 @@ class Module(models.Model): ).split(",") for r in self: - r.checksum_dir = dirhash( - get_module_path(r.name), - 'sha1', - excluded_extensions=exclude, - ) + try: + r.checksum_dir = dirhash( + get_module_path(r.name), + 'sha1', + excluded_extensions=exclude, + ) + except TypeError: + # Module path not found + pass def _store_checksum_installed(self, vals): if self.env.context.get('retain_checksum_installed'): @@ -48,17 +52,19 @@ class Module(models.Model): @api.multi def button_uninstall_cancel(self): - return super( - Module, - self.with_context(retain_checksum_installed=True), - ).button_uninstall_cancel() + # TODO Use super() like in v10 after pull is merged + # HACK https://github.com/odoo/odoo/pull/18597 + return self.with_context(retain_checksum_installed=True).write({ + 'state': 'installed', + }) @api.multi def button_upgrade_cancel(self): - return super( - Module, - self.with_context(retain_checksum_installed=True), - ).button_upgrade_cancel() + # TODO Use super() like in v10 after pull is merged + # HACK https://github.com/odoo/odoo/pull/18597 + return self.with_context(retain_checksum_installed=True).write({ + 'state': 'installed', + }) @api.model def create(self, vals): diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index 5d499fc27..36b22090c 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -7,8 +7,8 @@ import tempfile import mock -from odoo.modules import get_module_path -from odoo.tests.common import TransactionCase +from openerp.modules import get_module_path +from openerp.tests.common import TransactionCase from .. import post_init_hook @@ -18,7 +18,7 @@ try: except ImportError: _logger.debug('Cannot `import checksumdir`.') -model = 'odoo.addons.module_auto_update.models.module' +model = 'openerp.addons.module_auto_update.models.module' class TestModule(TransactionCase): @@ -170,9 +170,11 @@ class TestModule(TransactionCase): 'List update does not mark upgradeable modules "to upgrade"', ) - def test_update_list_only_changes_installed(self): + @mock.patch('%s.get_module_path' % model) + def test_update_list_only_changes_installed(self, get_module_path_mock): """It should not change the state of a module with a former state other than 'installed' to 'to upgrade'""" + get_module_path_mock.return_value = self.own_dir_path vals = { 'name': 'module_auto_update_test_module', 'state': 'uninstalled', diff --git a/module_auto_update/tests/test_module_upgrade.py b/module_auto_update/tests/test_module_upgrade.py index edc24fd8e..52134dd17 100644 --- a/module_auto_update/tests/test_module_upgrade.py +++ b/module_auto_update/tests/test_module_upgrade.py @@ -4,9 +4,9 @@ import mock -from odoo.modules import get_module_path -from odoo.modules.registry import Registry -from odoo.tests.common import TransactionCase +from openerp.modules import get_module_path +from openerp.modules.registry import RegistryManager +from openerp.tests.common import TransactionCase class TestModuleUpgrade(TransactionCase): @@ -29,7 +29,7 @@ class TestModuleUpgrade(TransactionCase): 'Upgrade cancellation does not preserve checksum_installed', ) - @mock.patch.object(Registry, 'new') + @mock.patch.object(RegistryManager, 'new') def test_upgrade_module(self, new_mock): """It should call update_list method on ir.module.module""" update_list_mock = mock.MagicMock() diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py index e9b69e07c..0abf8dfca 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -2,7 +2,7 @@ # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, models +from openerp import api, models class ModuleUpgrade(models.TransientModel): @@ -18,4 +18,4 @@ class ModuleUpgrade(models.TransientModel): @api.multi def upgrade_module(self): self.env['ir.module.module'].update_list() - super(ModuleUpgrade, self).upgrade_module() + return super(ModuleUpgrade, self).upgrade_module() diff --git a/requirements.txt b/requirements.txt index 6cad5a6f1..9343b1181 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +checksumdir python-ldap unidecode acme_tiny From 5a2c146705fffa22d152eceba7cf920036616d17 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 2 Aug 2017 10:35:52 +0200 Subject: [PATCH 4/6] [REF][module_auto_update] Recompute dir hashes only when needed By removing the recomputation from `update_list` we get faster CLI module upgrades and it only performs the autoupdate when using the autoupdate wizard or cron. --- module_auto_update/models/module.py | 15 +++----------- module_auto_update/tests/test_module.py | 12 +++++------ .../tests/test_module_upgrade.py | 20 ++++++++++--------- module_auto_update/wizards/module_upgrade.py | 14 ++++++++++++- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 22c608ab9..68d92ef74 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -37,8 +37,9 @@ class Module(models.Model): excluded_extensions=exclude, ) except TypeError: - # Module path not found - pass + _logger.debug( + "Cannot compute dir hash for %s, module not found", + r.display_name) def _store_checksum_installed(self, vals): if self.env.context.get('retain_checksum_installed'): @@ -72,16 +73,6 @@ class Module(models.Model): res._store_checksum_installed(vals) return res - @api.model - def update_list(self): - res = super(Module, self).update_list() - installed_modules = self.search([('state', '=', 'installed')]) - upgradeable_modules = installed_modules.filtered( - lambda r: r.checksum_dir != r.checksum_installed, - ) - upgradeable_modules.write({'state': "to upgrade"}) - return res - @api.multi def write(self, vals): res = super(Module, self).write(vals) diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index 36b22090c..bedc506a6 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -154,33 +154,33 @@ class TestModule(TransactionCase): ) @mock.patch('%s.get_module_path' % model) - def test_update_list(self, get_module_path_mock): + 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'""" - get_module_path_mock.return_value = self.own_dir_path + 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['ir.module.module'].update_list() + 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_update_list_only_changes_installed(self, get_module_path_mock): + 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'""" - get_module_path_mock.return_value = self.own_dir_path + 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['ir.module.module'].update_list() + self.env['base.module.upgrade'].get_module_list() self.assertNotEqual( test_module.state, 'to upgrade', 'List update changed state of an uninstalled module', diff --git a/module_auto_update/tests/test_module_upgrade.py b/module_auto_update/tests/test_module_upgrade.py index 52134dd17..2798e84fd 100644 --- a/module_auto_update/tests/test_module_upgrade.py +++ b/module_auto_update/tests/test_module_upgrade.py @@ -31,12 +31,14 @@ class TestModuleUpgrade(TransactionCase): @mock.patch.object(RegistryManager, 'new') def test_upgrade_module(self, new_mock): - """It should call update_list method on ir.module.module""" - update_list_mock = mock.MagicMock() - self.env['ir.module.module']._patch_method( - 'update_list', - update_list_mock, - ) - self.env['base.module.upgrade'].upgrade_module() - update_list_mock.assert_called_once_with() - self.env['ir.module.module']._revert_method('update_list') + """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') diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py index 0abf8dfca..d0c93e548 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -8,6 +8,16 @@ from openerp import api, models class ModuleUpgrade(models.TransientModel): _inherit = 'base.module.upgrade' + @api.model + def get_module_list(self): + 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.write({'state': "to upgrade"}) + return super(ModuleUpgrade, self).get_module_list() + @api.multi def upgrade_module_cancel(self): return super( @@ -17,5 +27,7 @@ class ModuleUpgrade(models.TransientModel): @api.multi def upgrade_module(self): - self.env['ir.module.module'].update_list() + # Compute updates by checksum when called in @api.model fashion + if not self: + self.get_module_list() return super(ModuleUpgrade, self).upgrade_module() From 83a6a504bd02c90309a7ae0840419d65fbb3f3e0 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 2 Aug 2017 10:52:06 +0200 Subject: [PATCH 5/6] [FIX][module_auto_update] Pass tests if addon is in readonly directory --- module_auto_update/tests/test_module.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index bedc506a6..432256ed5 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -3,6 +3,7 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). import logging +import os import tempfile import mock @@ -35,6 +36,7 @@ class TestModule(TransactionCase): 'sha1', excluded_extensions=['pyc', 'pyo'], ) + 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): @@ -52,6 +54,8 @@ class TestModule(TransactionCase): def test_compute_checksum_dir_ignore_excluded(self): """It should exclude .pyc/.pyo extensions from checksum calculations""" + if not self.own_writeable: + self.skipTest("Own directory not writeable") with tempfile.NamedTemporaryFile( suffix='.pyc', dir=self.own_dir_path): self.assertEqual( @@ -62,6 +66,8 @@ class TestModule(TransactionCase): def test_compute_checksum_dir_recomputes_when_file_added(self): """It should return a different value when a non-.pyc/.pyo file is added to the module directory""" + if not self.own_writeable: + self.skipTest("Own directory not writeable") with tempfile.NamedTemporaryFile( suffix='.py', dir=self.own_dir_path): self.assertNotEqual( From f0ed842da992cd8afdb9eeeb910ee2740f0ba877 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 2 Aug 2017 12:02:37 +0200 Subject: [PATCH 6/6] [FIX][module_auto_update] Set dependencies to upgrade --- module_auto_update/wizards/module_upgrade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py index d0c93e548..fed343957 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -15,7 +15,7 @@ class ModuleUpgrade(models.TransientModel): upgradeable_modules = installed_modules.filtered( lambda r: r.checksum_dir != r.checksum_installed, ) - upgradeable_modules.write({'state': "to upgrade"}) + upgradeable_modules.button_upgrade() return super(ModuleUpgrade, self).get_module_list() @api.multi