From b2733bdaf4b582b7d176cac049fbc4ca641fde6a Mon Sep 17 00:00:00 2001 From: Brenton Hughes Date: Thu, 20 Jul 2017 00:28:37 -0700 Subject: [PATCH 01/31] [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 4cf8301edfded458ccb768d084c081e332fe7739 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 22 Jul 2017 10:29:49 +0200 Subject: [PATCH 02/31] 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 988dd83e720ea67d430cc591ef238927470e13bb Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 2 Aug 2017 10:35:52 +0200 Subject: [PATCH 03/31] [REF][module_auto_update] Forward port v9 improvements * 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. * Pass tests if addon is in readonly directory * Set dependencies to upgrade [FIX][module_auto_update] Pass tests if addon is in readonly directory [FIX][module_auto_update] Set dependencies to upgrade --- module_auto_update/models/module.py | 25 ++++++++----------- module_auto_update/tests/test_module.py | 18 +++++++++---- .../tests/test_module_upgrade.py | 20 ++++++++------- module_auto_update/wizards/module_upgrade.py | 16 ++++++++++-- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 4d9ccec59..f191dcb75 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -30,11 +30,16 @@ 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: + _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'): @@ -66,16 +71,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 5d499fc27..2cdbba44b 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( @@ -154,31 +160,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"', ) - def test_update_list_only_changes_installed(self): + @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['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 edc24fd8e..0f908d5e0 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(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') + """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 e9b69e07c..0ccfeba9a 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -8,6 +8,16 @@ from odoo 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.button_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() - super(ModuleUpgrade, self).upgrade_module() + # Compute updates by checksum when called in @api.model fashion + if not self: + self.get_module_list() + return super(ModuleUpgrade, self).upgrade_module() From dd871c76cc9ead1f8a3f6bb09176b051d1599647 Mon Sep 17 00:00:00 2001 From: Dave Lasley Date: Fri, 11 Aug 2017 09:10:12 -0700 Subject: [PATCH 04/31] [FIX] module_auto_update: Don't compute upgrade on uninstall * `button_uninstall` calls `get_module_list`, which subsequently forces module upgrades. Add a context validation to prevent that * Add test for button_immediate_uninstall * Mock commit for immediate uninstall * Fix immediate uninstall test * Switch nesting * Bump module version --- module_auto_update/__manifest__.py | 2 +- module_auto_update/models/module.py | 7 ++++ module_auto_update/tests/test_module.py | 39 ++++++++++++++++++++ module_auto_update/wizards/module_upgrade.py | 13 ++++--- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index db65d269a..57a5846db 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '10.0.1.0.0', + 'version': '10.0.1.0.1', 'category': 'Extra Tools', 'website': 'https://odoo-community.org/', 'author': 'LasLabs, ' diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index f191dcb75..273d72588 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -51,6 +51,13 @@ class Module(models.Model): elif vals.get('state') == 'uninstalled': self.write({'checksum_installed': False}) + @api.multi + def button_uninstall(self): + return super( + Module, + self.with_context(module_uninstall=True), + ).button_uninstall() + @api.multi def button_uninstall_cancel(self): return super( diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index 2cdbba44b..bd25ed07a 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -22,6 +22,10 @@ except ImportError: model = 'odoo.addons.module_auto_update.models.module' +class EndTestException(Exception): + pass + + class TestModule(TransactionCase): def setUp(self): @@ -122,6 +126,41 @@ class TestModule(TransactionCase): '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'}) diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py index 0ccfeba9a..188030dd8 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -10,12 +10,13 @@ class ModuleUpgrade(models.TransientModel): @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.button_upgrade() + if not self.env.context.get('module_uninstall'): + 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 From 036bf2bfe887d36d0ed97474e4a8ccf3feed1c68 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 28 Aug 2017 12:33:43 +0200 Subject: [PATCH 05/31] [FIX][module_auto_update] Record base addon checksum (#948) --- module_auto_update/models/module.py | 39 ++++++-------------- module_auto_update/tests/test_module.py | 17 ++++----- module_auto_update/wizards/module_upgrade.py | 14 ++++++- 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 273d72588..398809e61 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -41,36 +41,21 @@ class Module(models.Model): "Cannot compute dir hash for %s, module not found", r.display_name) + @api.multi def _store_checksum_installed(self, vals): - if self.env.context.get('retain_checksum_installed'): - return + """Store the right installed checksum, if addon is installed.""" 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': + try: + version = vals["latest_version"] + except KeyError: + return # Not [un]installing/updating any addon + if version is False: + # Uninstalling self.write({'checksum_installed': False}) - - @api.multi - def button_uninstall(self): - return super( - Module, - self.with_context(module_uninstall=True), - ).button_uninstall() - - @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() + else: + # Installing or updating + for one in self: + one.checksum_installed = one.checksum_dir @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 bd25ed07a..f8fcf7278 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -10,6 +10,7 @@ import mock from odoo.modules import get_module_path from odoo.tests.common import TransactionCase +from odoo.tools import mute_logger from .. import post_init_hook @@ -81,24 +82,19 @@ class TestModule(TransactionCase): 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'""" + checksum_dir when vals contain a ``latest_version`` str.""" self.own_module.checksum_installed = 'test' - self.own_module._store_checksum_installed({'state': 'installed'}) + self.own_module._store_checksum_installed({'latest_version': '1.0'}) 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'""" + contain ``"latest_version": False``""" 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', - ) + 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 @@ -198,6 +194,7 @@ class TestModule(TransactionCase): '_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 diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py index 188030dd8..eaf278651 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -31,4 +31,16 @@ class ModuleUpgrade(models.TransientModel): # Compute updates by checksum when called in @api.model fashion if not self: self.get_module_list() - return super(ModuleUpgrade, self).upgrade_module() + # Get base adddon status before updating + base = self.env["ir.module.module"].search([("name", "=", "base")]) + pre_state = base.state + result = super(ModuleUpgrade, self).upgrade_module() + # Update base addon checksum if its state changed + base.invalidate_cache() + if base.state != pre_state: + # This triggers the write hook that should have been triggered + # when the module was [un]installed/updated in the base-only + # module graph inside above call to super(), and updates its + # dir checksum as needed + base.latest_version = base.latest_version + return result From 0173f65890427094ef2593956d6c98b367b3af81 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 29 Aug 2017 10:55:36 +0200 Subject: [PATCH 06/31] [FIX][module_auto_update] Always store changes in lower graphs The same problem that was fixed for the `base` addon in #948 happened with random addons that do not depend on `module_auto_update` (a.k.a. any addon) that Odoo decided to load before that one in the graph. Now we always check for all addons if their state has changed, and make sure to trigger the udpate mechanism that stores the right value in `installed_checksum_dir` field. If you installed and uninstalled the addon right away, you'd get a ProgrammingError saying that some columns exist no more. Checks are done now using `search_read`, which lets us limit the fields being fetched, and the environment is cleared to make sure nothing fails. Also we now guess if this own addon has been uninstalled and skip further logic if so, given it would hit broken triggers otherwise as it did before. --- module_auto_update/wizards/module_upgrade.py | 53 +++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade.py index eaf278651..3ab297d18 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -10,37 +10,40 @@ class ModuleUpgrade(models.TransientModel): @api.model def get_module_list(self): - if not self.env.context.get('module_uninstall'): - 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() + """Set modules to upgrade searching by their dir checksum.""" + 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_cancel(self): - return super( - ModuleUpgrade, - self.with_context(retain_checksum_installed=True), - ).upgrade_module_cancel() - @api.multi def upgrade_module(self): + """Make a fully automated addon upgrade.""" # Compute updates by checksum when called in @api.model fashion if not self: self.get_module_list() - # Get base adddon status before updating - base = self.env["ir.module.module"].search([("name", "=", "base")]) - pre_state = base.state + 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() - # Update base addon checksum if its state changed - base.invalidate_cache() - if base.state != pre_state: - # This triggers the write hook that should have been triggered - # when the module was [un]installed/updated in the base-only - # module graph inside above call to super(), and updates its - # dir checksum as needed - base.latest_version = base.latest_version + # 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 From 6cb53987c4f0b9ff49245ff232c945fba9065860 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 5 Jan 2018 13:55:52 +0000 Subject: [PATCH 07/31] [MIG] module_auto_update: Migrate to v11 --- module_auto_update/README.rst | 7 ++++--- module_auto_update/__init__.py | 2 -- module_auto_update/__manifest__.py | 4 ++-- module_auto_update/data/cron_data.xml | 11 ++++++++--- module_auto_update/hooks.py | 1 - module_auto_update/models/__init__.py | 2 -- module_auto_update/models/module.py | 1 - module_auto_update/tests/__init__.py | 2 -- module_auto_update/tests/test_module.py | 1 - module_auto_update/tests/test_module_upgrade.py | 1 - module_auto_update/wizards/__init__.py | 2 -- module_auto_update/wizards/module_upgrade.py | 2 +- 12 files changed, 15 insertions(+), 21 deletions(-) diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index 3535f4fb2..6349fdd7b 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -15,7 +15,7 @@ Installation Prior to installing this module, you need to: -#. Install checksumdir with `pip install checksumdir` +#. 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 @@ -23,7 +23,7 @@ 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. +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 ===== @@ -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/11.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/__init__.py b/module_auto_update/__init__.py index 36f555442..c80c51237 100644 --- a/module_auto_update/__init__.py +++ b/module_auto_update/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from . import models diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 57a5846db..50a6578ae 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -1,15 +1,15 @@ -# -*- 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.1', + 'version': '11.0.1.0.0', 'category': 'Extra Tools', 'website': 'https://odoo-community.org/', 'author': 'LasLabs, ' 'Juan José Scarafía, ' + 'Tecnativa, ' 'Odoo Community Association (OCA)', 'license': 'LGPL-3', 'application': False, diff --git a/module_auto_update/data/cron_data.xml b/module_auto_update/data/cron_data.xml index 1745fe0c9..9b5b1cc6b 100644 --- a/module_auto_update/data/cron_data.xml +++ b/module_auto_update/data/cron_data.xml @@ -1,4 +1,8 @@ + + Perform Module Upgrades @@ -8,8 +12,9 @@ days -1 - base.module.upgrade - upgrade_module - + + code + model.upgrade_module() + diff --git a/module_auto_update/hooks.py b/module_auto_update/hooks.py index f062966c3..56d60c6ef 100644 --- a/module_auto_update/hooks.py +++ b/module_auto_update/hooks.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/models/__init__.py b/module_auto_update/models/__init__.py index b27944126..e5ee3ea66 100644 --- a/module_auto_update/models/__init__.py +++ b/module_auto_update/models/__init__.py @@ -1,5 +1,3 @@ -# -*- 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 index 398809e61..271bc5700 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/tests/__init__.py b/module_auto_update/tests/__init__.py index 237970451..06952e34e 100644 --- a/module_auto_update/tests/__init__.py +++ b/module_auto_update/tests/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from . import test_module diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index f8fcf7278..08fda9841 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/tests/test_module_upgrade.py b/module_auto_update/tests/test_module_upgrade.py index 0f908d5e0..880c80d00 100644 --- a/module_auto_update/tests/test_module_upgrade.py +++ b/module_auto_update/tests/test_module_upgrade.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/wizards/__init__.py b/module_auto_update/wizards/__init__.py index 58cb00103..0448de3cf 100644 --- a/module_auto_update/wizards/__init__.py +++ b/module_auto_update/wizards/__init__.py @@ -1,5 +1,3 @@ -# -*- 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 index 3ab297d18..8634c38e5 100644 --- a/module_auto_update/wizards/module_upgrade.py +++ b/module_auto_update/wizards/module_upgrade.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). @@ -9,6 +8,7 @@ class ModuleUpgrade(models.TransientModel): _inherit = 'base.module.upgrade' @api.model + @api.returns('ir.module.module') def get_module_list(self): """Set modules to upgrade searching by their dir checksum.""" Module = self.env["ir.module.module"] From 2fe4edb3deb8351ed9e8d0190f7b60b05f068506 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 3 Mar 2018 13:37:30 +0100 Subject: [PATCH 08/31] OCA Transbot updated translations from Transifex --- module_auto_update/i18n/cs_CZ.po | 66 ++++++++++++++++++++++++++++++++ module_auto_update/i18n/es.po | 28 +++++++++----- module_auto_update/i18n/fr.po | 66 ++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 module_auto_update/i18n/cs_CZ.po create mode 100644 module_auto_update/i18n/fr.po diff --git a/module_auto_update/i18n/cs_CZ.po b/module_auto_update/i18n/cs_CZ.po new file mode 100644 index 000000000..754cd18bf --- /dev/null +++ b/module_auto_update/i18n/cs_CZ.po @@ -0,0 +1,66 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# Lukáš Spurný , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-03 10:08+0000\n" +"PO-Revision-Date: 2018-03-03 10:08+0000\n" +"Last-Translator: Lukáš Spurný , 2018\n" +"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/teams/23907/cs_CZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: cs_CZ\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 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 "Kontrolní součet Dir" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum Installed" +msgstr "Kontrolní součet je nainstalován" + +#. 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 "Aktualizace modulů" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "Moduly" + +#. 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 "Otevřít aktualizaci a aktualizovat seznam serverových akcí" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" +msgstr "Provést aktualizaci modulů" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "Plánované aktualizace" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "Aktualizace" diff --git a/module_auto_update/i18n/es.po b/module_auto_update/i18n/es.po index a318b0947..682b6172c 100644 --- a/module_auto_update/i18n/es.po +++ b/module_auto_update/i18n/es.po @@ -3,14 +3,15 @@ # * module_auto_update # # Translators: -# Pedro M. Baeza , 2017 +# OCA Transbot , 2018 +# enjolras , 2018 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 10.0\n" +"Project-Id-Version: Odoo Server 11.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" +"POT-Creation-Date: 2018-03-03 10:08+0000\n" +"PO-Revision-Date: 2018-03-03 10:08+0000\n" +"Last-Translator: enjolras , 2018\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" @@ -20,12 +21,12 @@ msgstr "" #. module: module_auto_update #: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_dir -msgid "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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -41,19 +42,26 @@ msgstr "Actualización de módulo" #. module: module_auto_update #: model:ir.ui.menu,name:module_auto_update.menu_default_modules msgid "Modules" -msgstr "" +msgstr "Módulos" #. 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.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" +msgstr "" + #. module: module_auto_update #: model:ir.ui.view,arch_db:module_auto_update.module_view_search msgid "Scheduled Upgrades" -msgstr "" +msgstr "Actualizaciones programadas" #. module: module_auto_update #: model:ir.ui.menu,name:module_auto_update.module_menu_updates msgid "Updates" -msgstr "" +msgstr "Actualizaciones" diff --git a/module_auto_update/i18n/fr.po b/module_auto_update/i18n/fr.po new file mode 100644 index 000000000..25920a9db --- /dev/null +++ b/module_auto_update/i18n/fr.po @@ -0,0 +1,66 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +# Translators: +# Nicolas JEUDY , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-03 10:08+0000\n" +"PO-Revision-Date: 2018-03-03 10:08+0000\n" +"Last-Translator: Nicolas JEUDY , 2018\n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fr\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 "Somme de contrôle du dossier" + +#. module: module_auto_update +#: model:ir.model.fields,field_description:module_auto_update.field_ir_module_module_checksum_installed +msgid "Checksum Installed" +msgstr "Somme de contrôle installée" + +#. 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 "Mise à niveau du module" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.menu_default_modules +msgid "Modules" +msgstr "Modules" + +#. 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 "Afficher les mises à jour" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" +msgstr "Appliquer les mise à jour de modules" + +#. module: module_auto_update +#: model:ir.ui.view,arch_db:module_auto_update.module_view_search +msgid "Scheduled Upgrades" +msgstr "Planifier les mises à jour" + +#. module: module_auto_update +#: model:ir.ui.menu,name:module_auto_update.module_menu_updates +msgid "Updates" +msgstr "Mises à jour" From fc690c41b393fbfe25bfa7ab0095da6bc288f523 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 16 Mar 2018 11:47:39 +0000 Subject: [PATCH 09/31] [REF] module_auto_update: Step 1, move all deprecated stuff to deprecated files - Files are clearly suffixed with `_deprecated` so we know those features have no support nor migrations. - Views are removed, since updating from UI was too buggy to support it anymore. --- module_auto_update/__manifest__.py | 3 +- ...cron_data.xml => cron_data_deprecated.xml} | 0 module_auto_update/models/__init__.py | 2 +- .../{module.py => module_deprecated.py} | 0 module_auto_update/tests/__init__.py | 4 +- ...st_module.py => test_module_deprecated.py} | 30 ++++++------ ...e.py => test_module_upgrade_deprecated.py} | 0 module_auto_update/views/module_views.xml | 49 ------------------- module_auto_update/wizards/__init__.py | 2 +- ...pgrade.py => module_upgrade_deprecated.py} | 0 10 files changed, 21 insertions(+), 69 deletions(-) rename module_auto_update/data/{cron_data.xml => cron_data_deprecated.xml} (100%) rename module_auto_update/models/{module.py => module_deprecated.py} (100%) rename module_auto_update/tests/{test_module.py => test_module_deprecated.py} (93%) rename module_auto_update/tests/{test_module_upgrade.py => test_module_upgrade_deprecated.py} (100%) delete mode 100644 module_auto_update/views/module_views.xml rename module_auto_update/wizards/{module_upgrade.py => module_upgrade_deprecated.py} (100%) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 50a6578ae..93cdcaecf 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -24,7 +24,6 @@ 'base', ], 'data': [ - 'views/module_views.xml', - 'data/cron_data.xml', + 'data/cron_data_deprecated.xml', ], } diff --git a/module_auto_update/data/cron_data.xml b/module_auto_update/data/cron_data_deprecated.xml similarity index 100% rename from module_auto_update/data/cron_data.xml rename to module_auto_update/data/cron_data_deprecated.xml diff --git a/module_auto_update/models/__init__.py b/module_auto_update/models/__init__.py index e5ee3ea66..19086b02d 100644 --- a/module_auto_update/models/__init__.py +++ b/module_auto_update/models/__init__.py @@ -1,3 +1,3 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from . import module +from . import module_deprecated diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module_deprecated.py similarity index 100% rename from module_auto_update/models/module.py rename to module_auto_update/models/module_deprecated.py diff --git a/module_auto_update/tests/__init__.py b/module_auto_update/tests/__init__.py index 06952e34e..6c2171bab 100644 --- a/module_auto_update/tests/__init__.py +++ b/module_auto_update/tests/__init__.py @@ -1,4 +1,4 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from . import test_module -from . import test_module_upgrade +from . import test_module_deprecated +from . import test_module_upgrade_deprecated diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module_deprecated.py similarity index 93% rename from module_auto_update/tests/test_module.py rename to module_auto_update/tests/test_module_deprecated.py index 08fda9841..51f347677 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module_deprecated.py @@ -19,7 +19,7 @@ try: except ImportError: _logger.debug('Cannot `import checksumdir`.') -model = 'odoo.addons.module_auto_update.models.module' +model = 'odoo.addons.module_auto_update.models.module_deprecated' class EndTestException(Exception): @@ -179,19 +179,21 @@ class TestModule(TransactionCase): 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', - ) + 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) diff --git a/module_auto_update/tests/test_module_upgrade.py b/module_auto_update/tests/test_module_upgrade_deprecated.py similarity index 100% rename from module_auto_update/tests/test_module_upgrade.py rename to module_auto_update/tests/test_module_upgrade_deprecated.py diff --git a/module_auto_update/views/module_views.xml b/module_auto_update/views/module_views.xml deleted file mode 100644 index 78a0be51e..000000000 --- a/module_auto_update/views/module_views.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - 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 index 0448de3cf..bcaca7966 100644 --- a/module_auto_update/wizards/__init__.py +++ b/module_auto_update/wizards/__init__.py @@ -1,3 +1,3 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from . import module_upgrade +from . import module_upgrade_deprecated diff --git a/module_auto_update/wizards/module_upgrade.py b/module_auto_update/wizards/module_upgrade_deprecated.py similarity index 100% rename from module_auto_update/wizards/module_upgrade.py rename to module_auto_update/wizards/module_upgrade_deprecated.py From 0daf2d6ebc8775b262173053de34e0e6a5e334fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Tue, 27 Feb 2018 23:45:55 +0100 Subject: [PATCH 10/31] [REF] module_auto_update: Step 2, add new API This code comes from the module_checksum_upgrade proposal at https://github.com/OCA/server-tools/pull/1176. * [ADD] module_checksum_upgrade It provides the core mechanism of module_auto_update without the cron nor any change to the standard upgrade mechanism. Instead it provides an API on which module_auto_update can build, as well as a method which can be called from a script to run the upgrade of modules for which the checksum has changed. * [IMP] refactor module_auto_update Make it depend on module_checksum_upgrade which provides the core mechanisms of managing the checksums. module_auto_update makes it automatic. * [IMP] module_checksum_upgrade: better exclusion mechanism Ignore files based on exclude patterns. Ignore uninstalled languages. Better default for patterns to ignore (*.pyc,*.pyo,*.pot,static/*) For better control on the hashing mechanism implement our own: it's quite easy, and the checksumdir module used previously had no test. * [MIG] module_auto_update: adapt to new checksum mechanism * [IMP] module_checksum_upgrade: raise in case of incomplete upgrade * [IMP] module_checksum_upgrade: improve default exclusion pattern * [IMP] module_checksum_upgrade: control translations overwrite * [IMP] module_checksum_upgrade: one more test * [IMP] module_checksum_upgrade: credits [ci skip] --- module_auto_update/README.rst | 43 ++-- module_auto_update/__manifest__.py | 6 +- module_auto_update/addon_hash.py | 45 ++++ module_auto_update/hooks.py | 6 +- module_auto_update/models/__init__.py | 1 + module_auto_update/models/module.py | 148 +++++++++++++ .../models/module_deprecated.py | 44 ++-- module_auto_update/tests/__init__.py | 2 + .../tests/sample_module/README.rst | 1 + .../tests/sample_module/data/f1.xml | 1 + .../tests/sample_module/data/f2.xml | 1 + .../tests/sample_module/i18n/en.po | 1 + .../tests/sample_module/i18n/en_US.po | 1 + .../tests/sample_module/i18n/fr.po | 1 + .../tests/sample_module/i18n/fr_BE.po | 1 + .../tests/sample_module/i18n/test.pot | 1 + .../tests/sample_module/i18n_extra/en.po | 1 + .../tests/sample_module/i18n_extra/fr.po | 1 + .../tests/sample_module/i18n_extra/nl_NL.po | 1 + .../tests/sample_module/models/stuff.py | 1 + .../tests/sample_module/models/stuff.pyc | Bin 0 -> 109 bytes .../tests/sample_module/static/src/some.js | 1 + module_auto_update/tests/test_addon_hash.py | 67 ++++++ module_auto_update/tests/test_module.py | 203 ++++++++++++++++++ .../tests/test_module_deprecated.py | 15 +- 25 files changed, 533 insertions(+), 60 deletions(-) create mode 100644 module_auto_update/addon_hash.py create mode 100644 module_auto_update/models/module.py create mode 100644 module_auto_update/tests/sample_module/README.rst create mode 100644 module_auto_update/tests/sample_module/data/f1.xml create mode 100644 module_auto_update/tests/sample_module/data/f2.xml create mode 100644 module_auto_update/tests/sample_module/i18n/en.po create mode 100644 module_auto_update/tests/sample_module/i18n/en_US.po create mode 100644 module_auto_update/tests/sample_module/i18n/fr.po create mode 100644 module_auto_update/tests/sample_module/i18n/fr_BE.po create mode 100644 module_auto_update/tests/sample_module/i18n/test.pot create mode 100644 module_auto_update/tests/sample_module/i18n_extra/en.po create mode 100644 module_auto_update/tests/sample_module/i18n_extra/fr.po create mode 100644 module_auto_update/tests/sample_module/i18n_extra/nl_NL.po create mode 100644 module_auto_update/tests/sample_module/models/stuff.py create mode 100644 module_auto_update/tests/sample_module/models/stuff.pyc create mode 100644 module_auto_update/tests/sample_module/static/src/some.js create mode 100644 module_auto_update/tests/test_addon_hash.py create mode 100644 module_auto_update/tests/test_module.py diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index 6349fdd7b..8989df79a 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -6,31 +6,43 @@ 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. +This addon provides mechanisms to compute sha1 hashes of installed addons, +and save them in the database. It also provides a method that exploits these +mechanisms to update a database by upgrading only the modules for which the +hash has changed since the last successful upgrade. 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 supports the following system parameters: -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. +* ``module_auto_update.exclude_patterns``: comma-separated list of file + name patterns to ignore when computing addon checksums. Defaults to + ``*.pyc,*.pyo,i18n/*.pot,i18n_extra/*.pot,static/*``. + Filename patterns must be compatible with the python ``fnmatch`` function. + +In addition to the above pattern, .po files corresponding to languages that +are not installed in the Odoo database are ignored when computing checksums. Usage ===== -Modules scheduled for upgrade can be viewed by clicking the "Updates" menu item in the Apps sidebar. +The main method provided by this module is ``upgrade_changed_checksum`` +on ``ir.module.module``. It runs a database upgrade for all installed +modules for which the hash has changed since the last successful +run of this method. On success it saves the hashes in the database. + +The first time this method is invoked after installing the module, it +runs an upgrade of all modules, because it has not saved the hashes yet. +This is by design, priviledging safety. Should this be an issue, +the method ``_save_installed_checksums`` can be invoked in a situation +where one is sure all modules on disk are installed and up-to-date in the +database. + +An easy way to invoke this upgrade mechanism is by issuing the following +in an Odoo shell session:: -To perform upgrades manually, click the "Apply Scheduled Upgrades" menu item in the Apps sidebar. + env['ir.module.module'].upgrade_changed_checksum() .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot @@ -58,6 +70,7 @@ Contributors * Brent Hughes * Juan José Scarafía * Jairo Llopis +* Stéphane Bidoul (https://acsone.eu) Do not contact contributors directly about support or help with technical issues. diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 93cdcaecf..4f4375fc7 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -10,16 +10,12 @@ 'author': 'LasLabs, ' 'Juan José Scarafía, ' 'Tecnativa, ' + 'ACSONE SA/NV, ' 'Odoo Community Association (OCA)', 'license': 'LGPL-3', 'application': False, 'installable': True, 'post_init_hook': 'post_init_hook', - 'external_dependencies': { - 'python': [ - 'checksumdir', - ], - }, 'depends': [ 'base', ], diff --git a/module_auto_update/addon_hash.py b/module_auto_update/addon_hash.py new file mode 100644 index 000000000..dea52b4f2 --- /dev/null +++ b/module_auto_update/addon_hash.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from fnmatch import fnmatch +import hashlib +import os + + +def _fnmatch(filename, patterns): + for pattern in patterns: + if fnmatch(filename, pattern): + return True + return False + + +def _walk(top, exclude_patterns, keep_langs): + keep_langs = {l.split('_')[0] for l in keep_langs} + for dirpath, dirnames, filenames in os.walk(top): + dirnames.sort() + reldir = os.path.relpath(dirpath, top) + if reldir == '.': + reldir = '' + for filename in sorted(filenames): + filepath = os.path.join(reldir, filename) + if _fnmatch(filepath, exclude_patterns): + continue + if keep_langs and reldir in {'i18n', 'i18n_extra'}: + basename, ext = os.path.splitext(filename) + if ext == '.po': + if basename.split('_')[0] not in keep_langs: + continue + yield filepath + + +def addon_hash(top, exclude_patterns, keep_langs): + """Compute a sha1 digest of file contents.""" + m = hashlib.sha1() + for filepath in _walk(top, exclude_patterns, keep_langs): + # hash filename so empty files influence the hash + m.update(filepath.encode('utf-8')) + # hash file content + with open(os.path.join(top, filepath), 'rb') as f: + m.update(f.read()) + return m.hexdigest() diff --git a/module_auto_update/hooks.py b/module_auto_update/hooks.py index 56d60c6ef..396f78707 100644 --- a/module_auto_update/hooks.py +++ b/module_auto_update/hooks.py @@ -6,8 +6,4 @@ 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 + env['ir.module.module']._save_installed_checksums() diff --git a/module_auto_update/models/__init__.py b/module_auto_update/models/__init__.py index 19086b02d..53c05a539 100644 --- a/module_auto_update/models/__init__.py +++ b/module_auto_update/models/__init__.py @@ -1,3 +1,4 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from . import module from . import module_deprecated diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py new file mode 100644 index 000000000..334ec9d16 --- /dev/null +++ b/module_auto_update/models/module.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# Copyright 2018 ACSONE SA/NV. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import json +import logging +import os + +from openerp import api, exceptions, models, tools +from openerp.modules.module import get_module_path + +from ..addon_hash import addon_hash + +PARAM_INSTALLED_CHECKSUMS = \ + 'module_auto_update.installed_checksums' +PARAM_EXCLUDE_PATTERNS = \ + 'module_auto_update.exclude_patterns' +DEFAULT_EXCLUDE_PATTERNS = \ + '*.pyc,*.pyo,i18n/*.pot,i18n_extra/*.pot,static/*' + +_logger = logging.getLogger(__name__) + + +class IncompleteUpgradeError(exceptions.UserError): + pass + + +class Module(models.Model): + _inherit = 'ir.module.module' + + @api.multi + def _get_checksum_dir(self): + self.ensure_one() + + exclude_patterns = self.env["ir.config_parameter"].get_param( + PARAM_EXCLUDE_PATTERNS, + DEFAULT_EXCLUDE_PATTERNS, + ) + exclude_patterns = [p.strip() for p in exclude_patterns.split(',')] + keep_langs = self.env['res.lang'].search([]).mapped('code') + + module_path = get_module_path(self.name) + if module_path and os.path.isdir(module_path): + checksum_dir = addon_hash( + module_path, + exclude_patterns, + keep_langs, + ) + else: + checksum_dir = False + + return checksum_dir + + @api.model + def _get_saved_checksums(self): + Icp = self.env['ir.config_parameter'] + return json.loads(Icp.get_param(PARAM_INSTALLED_CHECKSUMS, '{}')) + + @api.model + def _save_checksums(self, checksums): + Icp = self.env['ir.config_parameter'] + Icp.set_param(PARAM_INSTALLED_CHECKSUMS, json.dumps(checksums)) + + @api.model + def _save_installed_checksums(self): + checksums = {} + installed_modules = self.search([('state', '=', 'installed')]) + 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')), + ]) + + @api.model + 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), + ) + + @api.model + def upgrade_changed_checksum(self, overwrite_existing_translations=False): + """Run an upgrade of the database, upgrading only changed modules. + + Installed modules for which the checksum has changed since the + last successful run of this method are marked "to upgrade", + then the normal Odoo scheduled upgrade process + is launched. + + If there is no module with a changed checksum, and no module in state + other than installed, uninstalled, uninstallable, this method does + nothing, otherwise the normal Odoo upgrade process is launched. + + After a successful upgrade, the checksums of installed modules are + saved. + + In case of error during the upgrade, an exception is raised. + If any module remains to upgrade or to uninstall after the upgrade + process, an exception is raised as well. + + Note: this method commits the current transaction at each important + step, it is therefore not intended to be run as part of a + larger transaction. + """ + _logger.info( + "Checksum upgrade starting (i18n-overwrite=%s)...", + overwrite_existing_translations + ) + + tools.config['overwrite_existing_translations'] = \ + overwrite_existing_translations + + _logger.info("Updating modules list...") + self.update_list() + changed_modules = self._get_modules_with_changed_checksum() + if not changed_modules and not self._get_modules_partially_installed(): + _logger.info("No checksum change detected in installed modules " + "and all modules installed, nothing to do.") + return + _logger.info("Marking the following modules to upgrade, " + "for their checksums changed: %s...", + ','.join(changed_modules.mapped('name'))) + changed_modules.button_upgrade() + self.env.cr.commit() # pylint: disable=invalid-commit + + _logger.info("Upgrading...") + self.env['base.module.upgrade'].upgrade_module() + self.env.cr.commit() # pylint: disable=invalid-commit + + _logger.info("Upgrade successful, updating checksums...") + self._save_installed_checksums() + self.env.cr.commit() # pylint: disable=invalid-commit + + partial_modules = self._get_modules_partially_installed() + if partial_modules: + raise IncompleteUpgradeError( + "Checksum upgrade successful " + "but incomplete for the following modules: %s" % + ','.join(partial_modules.mapped('name')) + ) + + _logger.info("Checksum upgrade complete.") diff --git a/module_auto_update/models/module_deprecated.py b/module_auto_update/models/module_deprecated.py index 271bc5700..5f1f5b8e2 100644 --- a/module_auto_update/models/module_deprecated.py +++ b/module_auto_update/models/module_deprecated.py @@ -1,16 +1,7 @@ # 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): @@ -19,26 +10,27 @@ class Module(models.Model): checksum_dir = fields.Char( compute='_compute_checksum_dir', ) - checksum_installed = fields.Char() + checksum_installed = fields.Char( + compute='_compute_checksum_installed', + inverse='_inverse_checksum_installed', + store=False, + ) @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: - try: - r.checksum_dir = dirhash( - get_module_path(r.name), - 'sha1', - excluded_extensions=exclude, - ) - except TypeError: - _logger.debug( - "Cannot compute dir hash for %s, module not found", - r.display_name) + 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): + saved_checksums = self._get_saved_checksums() + for rec in self: + saved_checksums[rec.name] = rec.checksum_installed + self._save_installed_checksums() @api.multi def _store_checksum_installed(self, vals): diff --git a/module_auto_update/tests/__init__.py b/module_auto_update/tests/__init__.py index 6c2171bab..54f7cc144 100644 --- a/module_auto_update/tests/__init__.py +++ b/module_auto_update/tests/__init__.py @@ -1,4 +1,6 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from . import test_addon_hash +from . import test_module from . import test_module_deprecated from . import test_module_upgrade_deprecated diff --git a/module_auto_update/tests/sample_module/README.rst b/module_auto_update/tests/sample_module/README.rst new file mode 100644 index 000000000..048382e52 --- /dev/null +++ b/module_auto_update/tests/sample_module/README.rst @@ -0,0 +1 @@ +Test data for addon_hash module. diff --git a/module_auto_update/tests/sample_module/data/f1.xml b/module_auto_update/tests/sample_module/data/f1.xml new file mode 100644 index 000000000..77a8d9d78 --- /dev/null +++ b/module_auto_update/tests/sample_module/data/f1.xml @@ -0,0 +1 @@ + diff --git a/module_auto_update/tests/sample_module/data/f2.xml b/module_auto_update/tests/sample_module/data/f2.xml new file mode 100644 index 000000000..77a8d9d78 --- /dev/null +++ b/module_auto_update/tests/sample_module/data/f2.xml @@ -0,0 +1 @@ + diff --git a/module_auto_update/tests/sample_module/i18n/en.po b/module_auto_update/tests/sample_module/i18n/en.po new file mode 100644 index 000000000..c8afcebdf --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n/en.po @@ -0,0 +1 @@ +en text diff --git a/module_auto_update/tests/sample_module/i18n/en_US.po b/module_auto_update/tests/sample_module/i18n/en_US.po new file mode 100644 index 000000000..7741b83a3 --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n/en_US.po @@ -0,0 +1 @@ +en_US diff --git a/module_auto_update/tests/sample_module/i18n/fr.po b/module_auto_update/tests/sample_module/i18n/fr.po new file mode 100644 index 000000000..527e861b3 --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n/fr.po @@ -0,0 +1 @@ +fr diff --git a/module_auto_update/tests/sample_module/i18n/fr_BE.po b/module_auto_update/tests/sample_module/i18n/fr_BE.po new file mode 100644 index 000000000..961231717 --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n/fr_BE.po @@ -0,0 +1 @@ +fr_BE diff --git a/module_auto_update/tests/sample_module/i18n/test.pot b/module_auto_update/tests/sample_module/i18n/test.pot new file mode 100644 index 000000000..eb1ae458f --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n/test.pot @@ -0,0 +1 @@ +... diff --git a/module_auto_update/tests/sample_module/i18n_extra/en.po b/module_auto_update/tests/sample_module/i18n_extra/en.po new file mode 100644 index 000000000..c574d073d --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n_extra/en.po @@ -0,0 +1 @@ +en diff --git a/module_auto_update/tests/sample_module/i18n_extra/fr.po b/module_auto_update/tests/sample_module/i18n_extra/fr.po new file mode 100644 index 000000000..527e861b3 --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n_extra/fr.po @@ -0,0 +1 @@ +fr diff --git a/module_auto_update/tests/sample_module/i18n_extra/nl_NL.po b/module_auto_update/tests/sample_module/i18n_extra/nl_NL.po new file mode 100644 index 000000000..85b15b659 --- /dev/null +++ b/module_auto_update/tests/sample_module/i18n_extra/nl_NL.po @@ -0,0 +1 @@ +nl_NL diff --git a/module_auto_update/tests/sample_module/models/stuff.py b/module_auto_update/tests/sample_module/models/stuff.py new file mode 100644 index 000000000..c040fa67d --- /dev/null +++ b/module_auto_update/tests/sample_module/models/stuff.py @@ -0,0 +1 @@ +1+1 diff --git a/module_auto_update/tests/sample_module/models/stuff.pyc b/module_auto_update/tests/sample_module/models/stuff.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2050f52c7c2e2c08bfb655555c80e4342a48a0c2 GIT binary patch literal 109 zcmZSn%**Avesxqb0~9a;X$K%K<^U2YObm=Ej10jV%s@^iBaraR1S!w}Vsrwmp}3?p ZElsbWvIL~tCO1E&G$+*#q^}sH0{{jG4&DF& literal 0 HcmV?d00001 diff --git a/module_auto_update/tests/sample_module/static/src/some.js b/module_auto_update/tests/sample_module/static/src/some.js new file mode 100644 index 000000000..64797d825 --- /dev/null +++ b/module_auto_update/tests/sample_module/static/src/some.js @@ -0,0 +1 @@ +/* javascript */ diff --git a/module_auto_update/tests/test_addon_hash.py b/module_auto_update/tests/test_addon_hash.py new file mode 100644 index 000000000..7523b8ec4 --- /dev/null +++ b/module_auto_update/tests/test_addon_hash.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import os +import unittest + +from .. import addon_hash +from ..models.module import DEFAULT_EXCLUDE_PATTERNS + + +class TestAddonHash(unittest.TestCase): + + def setUp(self): + super(TestAddonHash, self).setUp() + self.sample_dir = os.path.join( + os.path.dirname(__file__), + 'sample_module', + ) + + def test_basic(self): + files = list(addon_hash._walk( + self.sample_dir, + exclude_patterns=[], + keep_langs=[], + )) + self.assertEqual(files, [ + 'README.rst', + 'data/f1.xml', + 'data/f2.xml', + 'i18n/en.po', + 'i18n/en_US.po', + 'i18n/fr.po', + 'i18n/fr_BE.po', + 'i18n/test.pot', + 'i18n_extra/en.po', + 'i18n_extra/fr.po', + 'i18n_extra/nl_NL.po', + 'models/stuff.py', + 'models/stuff.pyc', + 'static/src/some.js', + ]) + + def test_exclude(self): + files = list(addon_hash._walk( + self.sample_dir, + exclude_patterns=DEFAULT_EXCLUDE_PATTERNS.split(','), + keep_langs=['fr_FR', 'nl'], + )) + self.assertEqual(files, [ + 'README.rst', + 'data/f1.xml', + 'data/f2.xml', + 'i18n/fr.po', + 'i18n/fr_BE.po', + 'i18n_extra/fr.po', + 'i18n_extra/nl_NL.po', + 'models/stuff.py', + ]) + + def test2(self): + checksum = addon_hash.addon_hash( + self.sample_dir, + exclude_patterns=['*.pyc', '*.pyo', '*.pot', 'static/*'], + keep_langs=['fr_FR', 'nl'], + ) + self.assertEqual(checksum, 'fecb89486c8a29d1f760cbd01c1950f6e8421b14') diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py new file mode 100644 index 000000000..b4f0746c3 --- /dev/null +++ b/module_auto_update/tests/test_module.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# Copyright 2018 ACSONE SA/NV. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import os +import tempfile + +import mock + +from openerp.modules import get_module_path +from openerp.tests import common +from openerp.tests.common import TransactionCase + +from ..addon_hash import addon_hash +from ..models.module import IncompleteUpgradeError, DEFAULT_EXCLUDE_PATTERNS + +MODULE_NAME = 'module_auto_update' + + +class TestModule(TransactionCase): + + def setUp(self): + super(TestModule, self).setUp() + 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=DEFAULT_EXCLUDE_PATTERNS.split(','), + keep_langs=keep_langs, + ) + self.own_writeable = os.access(self.own_dir_path, os.W_OK) + + def test_compute_checksum_dir(self): + """It should compute the directory's SHA-1 hash""" + self.assertEqual( + self.own_module._get_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""" + if not self.own_writeable: + self.skipTest("Own directory not writeable") + with tempfile.NamedTemporaryFile(suffix='.pyc', dir=self.own_dir_path): + self.assertEqual( + self.own_module._get_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""" + if not self.own_writeable: + self.skipTest("Own directory not writeable") + with tempfile.NamedTemporaryFile(suffix='.py', dir=self.own_dir_path): + self.assertNotEqual( + self.own_module._get_checksum_dir(), self.own_checksum, + 'SHA1 checksum not recomputed', + ) + + def test_saved_checksums(self): + Imm = self.env['ir.module.module'] + base_module = Imm.search([('name', '=', 'base')]) + self.assertEqual(base_module.state, 'installed') + self.assertFalse(Imm._get_saved_checksums()) + Imm._save_installed_checksums() + saved_checksums = Imm._get_saved_checksums() + self.assertTrue(saved_checksums) + self.assertTrue(saved_checksums['base']) + + def test_get_modules_with_changed_checksum(self): + Imm = self.env['ir.module.module'] + self.assertTrue(Imm._get_modules_with_changed_checksum()) + Imm._save_installed_checksums() + self.assertFalse(Imm._get_modules_with_changed_checksum()) + + +@common.at_install(False) +@common.post_install(True) +class TestModuleAfterInstall(TransactionCase): + + def setUp(self): + super(TestModuleAfterInstall, self).setUp() + Imm = self.env['ir.module.module'] + self.own_module = Imm.search([('name', '=', MODULE_NAME)]) + self.base_module = Imm.search([('name', '=', 'base')]) + + def test_get_modules_partially_installed(self): + Imm = self.env['ir.module.module'] + self.assertTrue( + self.own_module not in Imm._get_modules_partially_installed()) + self.own_module.button_upgrade() + self.assertTrue( + self.own_module in Imm._get_modules_partially_installed()) + self.own_module.button_upgrade_cancel() + self.assertTrue( + self.own_module not in Imm._get_modules_partially_installed()) + + def test_upgrade_changed_checksum(self): + Imm = self.env['ir.module.module'] + Bmu = self.env['base.module.upgrade'] + + # check modules are in installed state + installed_modules = Imm.search([('state', '=', 'installed')]) + self.assertTrue(self.own_module in installed_modules) + self.assertTrue(self.base_module in installed_modules) + self.assertTrue(len(installed_modules) > 2) + # change the checksum of 'base' + Imm._save_installed_checksums() + saved_checksums = Imm._get_saved_checksums() + saved_checksums['base'] = False + Imm._save_checksums(saved_checksums) + changed_modules = Imm._get_modules_with_changed_checksum() + self.assertEqual(len(changed_modules), 1) + self.assertTrue(self.base_module in changed_modules) + + def upgrade_module_mock(self_model): + upgrade_module_mock.call_count += 1 + # since we are upgrading base, all installed module + # must have been marked to upgrade at this stage + self.assertEqual(self.base_module.state, 'to upgrade') + self.assertEqual(self.own_module.state, 'to upgrade') + installed_modules.write({'state': 'installed'}) + + upgrade_module_mock.call_count = 0 + + # upgrade_changed_checksum commits, so mock that + with mock.patch.object(self.env.cr, 'commit'): + + # we simulate an install by setting module states + Bmu._patch_method('upgrade_module', upgrade_module_mock) + try: + Imm.upgrade_changed_checksum() + self.assertEqual(upgrade_module_mock.call_count, 1) + self.assertEqual(self.base_module.state, 'installed') + self.assertEqual(self.own_module.state, 'installed') + saved_checksums = Imm._get_saved_checksums() + self.assertTrue(saved_checksums['base']) + self.assertTrue(saved_checksums[MODULE_NAME]) + finally: + Bmu._revert_method('upgrade_module') + + def test_incomplete_upgrade(self): + Imm = self.env['ir.module.module'] + Bmu = self.env['base.module.upgrade'] + + installed_modules = Imm.search([('state', '=', 'installed')]) + # change the checksum of 'base' + Imm._save_installed_checksums() + saved_checksums = Imm._get_saved_checksums() + saved_checksums['base'] = False + Imm._save_checksums(saved_checksums) + + def upgrade_module_mock(self_model): + upgrade_module_mock.call_count += 1 + # since we are upgrading base, all installed module + # must have been marked to upgrade at this stage + self.assertEqual(self.base_module.state, 'to upgrade') + self.assertEqual(self.own_module.state, 'to upgrade') + installed_modules.write({'state': 'installed'}) + # simulate partial upgrade + self.own_module.write({'state': 'to upgrade'}) + + upgrade_module_mock.call_count = 0 + + # upgrade_changed_checksum commits, so mock that + with mock.patch.object(self.env.cr, 'commit'): + + # we simulate an install by setting module states + Bmu._patch_method('upgrade_module', upgrade_module_mock) + try: + with self.assertRaises(IncompleteUpgradeError): + Imm.upgrade_changed_checksum() + self.assertEqual(upgrade_module_mock.call_count, 1) + finally: + Bmu._revert_method('upgrade_module') + + def test_nothing_to_upgrade(self): + Imm = self.env['ir.module.module'] + Bmu = self.env['base.module.upgrade'] + + Imm._save_installed_checksums() + + def upgrade_module_mock(self_model): + upgrade_module_mock.call_count += 1 + + upgrade_module_mock.call_count = 0 + + # upgrade_changed_checksum commits, so mock that + with mock.patch.object(self.env.cr, 'commit'): + + # we simulate an install by setting module states + Bmu._patch_method('upgrade_module', upgrade_module_mock) + try: + Imm.upgrade_changed_checksum() + self.assertEqual(upgrade_module_mock.call_count, 0) + finally: + Bmu._revert_method('upgrade_module') diff --git a/module_auto_update/tests/test_module_deprecated.py b/module_auto_update/tests/test_module_deprecated.py index 51f347677..b82fd6748 100644 --- a/module_auto_update/tests/test_module_deprecated.py +++ b/module_auto_update/tests/test_module_deprecated.py @@ -1,7 +1,6 @@ # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -import logging import os import tempfile @@ -11,13 +10,10 @@ 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 .. 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_deprecated' @@ -35,10 +31,11 @@ class TestModule(TransactionCase): ('name', '=', module_name), ]) self.own_dir_path = get_module_path(module_name) - self.own_checksum = dirhash( + keep_langs = self.env['res.lang'].search([]).mapped('code') + self.own_checksum = addon_hash( self.own_dir_path, - 'sha1', - excluded_extensions=['pyc', 'pyo'], + exclude_patterns=['*.pyc', '*.pyo', '*.pot', 'static/*'], + keep_langs=keep_langs, ) self.own_writeable = os.access(self.own_dir_path, os.W_OK) From 006b822ce3347e85809a85ecb5dc90a7bd15bf7f Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 16 Mar 2018 12:28:20 +0000 Subject: [PATCH 11/31] [REF] module_auto_update: Step 3, backwards compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation of this addon proved being extremely buggy: - It supplied out of the box a enabled cron to update Odoo that didn't restart the server, which possibly meant that upgrades broke things. - It overloaded standard Odoo upgrade methods that made i.e. installing an addon sometimes forced to upgrade all other addons in the database. - The checksum system wasn't smart enough, and some files that didn't need a module upgrade triggered the upgrade. - It was based on a dirhash library that was untested. - Some updates were not detected properly. - Storing a column into `ir.module.module` sometimes forbids uninstalling the addon. Thanks to Stéphane Bidoul (ACSONE), now we have new methods to perform the same work in a safer and more stable way. All I'm doing here is: - Cron is disabled by default. - Installed checksums are no longer saved at first install. - Old installations should keep most functionality intact thanks to the migration script. - Drop some duplicated tests. - Allow module uninstallation by pre-removing the fields from ir.mode.model. - When uninstalling the addon, the deprecated features will get removed for next installs always. Besides that, fixes for the new implementation too: - When uninstalling the addon, we remove the stored checksum data, so further installations work as if the addon was installed from scratch. --- module_auto_update/README.rst | 21 +++++ module_auto_update/__init__.py | 2 +- module_auto_update/__manifest__.py | 4 +- .../data/cron_data_deprecated.xml | 2 +- module_auto_update/hooks.py | 12 ++- .../migrations/10.0.2.0.0/pre-migrate.py | 23 +++++ .../models/module_deprecated.py | 13 ++- .../tests/test_module_deprecated.py | 52 +---------- .../tests/test_module_upgrade_deprecated.py | 3 + .../wizards/module_upgrade_deprecated.py | 93 +++++++++++++------ 10 files changed, 139 insertions(+), 86 deletions(-) create mode 100644 module_auto_update/migrations/10.0.2.0.0/pre-migrate.py diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index 8989df79a..1dd66fbbd 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -48,6 +48,27 @@ in an Odoo shell session:: :alt: Try me on Runbot :target: https://runbot.odoo-community.org/runbot/149/11.0 +Known issues / Roadmap +====================== + +* 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``. + Bug Tracker =========== diff --git a/module_auto_update/__init__.py b/module_auto_update/__init__.py index c80c51237..a0c82fd06 100644 --- a/module_auto_update/__init__.py +++ b/module_auto_update/__init__.py @@ -2,4 +2,4 @@ from . import models from . import wizards -from .hooks import post_init_hook +from .hooks import uninstall_hook diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 4f4375fc7..d39962c1c 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -6,7 +6,7 @@ 'summary': 'Automatically update Odoo modules', 'version': '11.0.1.0.0', 'category': 'Extra Tools', - 'website': 'https://odoo-community.org/', + 'website': 'https://github.com/OCA/server-tools', 'author': 'LasLabs, ' 'Juan José Scarafía, ' 'Tecnativa, ' @@ -15,7 +15,7 @@ 'license': 'LGPL-3', 'application': False, 'installable': True, - 'post_init_hook': 'post_init_hook', + 'uninstall_hook': 'uninstall_hook', 'depends': [ 'base', ], diff --git a/module_auto_update/data/cron_data_deprecated.xml b/module_auto_update/data/cron_data_deprecated.xml index 9b5b1cc6b..d903dbda6 100644 --- a/module_auto_update/data/cron_data_deprecated.xml +++ b/module_auto_update/data/cron_data_deprecated.xml @@ -6,7 +6,7 @@ Perform Module Upgrades - + 1 days diff --git a/module_auto_update/hooks.py b/module_auto_update/hooks.py index 396f78707..cd161a246 100644 --- a/module_auto_update/hooks.py +++ b/module_auto_update/hooks.py @@ -3,7 +3,15 @@ from odoo import SUPERUSER_ID, api +from .models.module import PARAM_INSTALLED_CHECKSUMS +from .models.module_deprecated import PARAM_DEPRECATED -def post_init_hook(cr, registry): + +def uninstall_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) - env['ir.module.module']._save_installed_checksums() + 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() diff --git a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py new file mode 100644 index 000000000..4fe36ede7 --- /dev/null +++ b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Tecnativa - Jairo Llopis +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). +import logging +from psycopg2 import IntegrityError +from openerp.addons.module_auto_update.models.module_deprecated import \ + PARAM_DEPRECATED + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + """Autoenable deprecated behavior.""" + try: + 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") diff --git a/module_auto_update/models/module_deprecated.py b/module_auto_update/models/module_deprecated.py index 5f1f5b8e2..0cb9defaa 100644 --- a/module_auto_update/models/module_deprecated.py +++ b/module_auto_update/models/module_deprecated.py @@ -3,14 +3,18 @@ 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, @@ -27,14 +31,17 @@ class Module(models.Model): rec.checksum_installed = saved_checksums.get(rec.name, False) def _inverse_checksum_installed(self): - saved_checksums = self._get_saved_checksums() + checksums = self._get_saved_checksums() for rec in self: - saved_checksums[rec.name] = rec.checksum_installed - self._save_installed_checksums() + 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"] diff --git a/module_auto_update/tests/test_module_deprecated.py b/module_auto_update/tests/test_module_deprecated.py index b82fd6748..99d0ee4ec 100644 --- a/module_auto_update/tests/test_module_deprecated.py +++ b/module_auto_update/tests/test_module_deprecated.py @@ -2,7 +2,6 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). import os -import tempfile import mock @@ -10,12 +9,12 @@ 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 openerp.addons.module_auto_update.addon_hash import addon_hash -from .. import post_init_hook +from ..models.module_deprecated import PARAM_DEPRECATED -model = 'odoo.addons.module_auto_update.models.module_deprecated' +model = 'odoo.addons.module_auto_update.models.module' class EndTestException(Exception): @@ -27,6 +26,7 @@ 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), ]) @@ -45,37 +45,6 @@ class TestModule(TransactionCase): 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""" - if not self.own_writeable: - self.skipTest("Own directory not writeable") - 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""" - if not self.own_writeable: - self.skipTest("Own directory not writeable") - 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 a ``latest_version`` str.""" @@ -239,16 +208,3 @@ class TestModule(TransactionCase): 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_deprecated.py b/module_auto_update/tests/test_module_upgrade_deprecated.py index 880c80d00..13e729594 100644 --- a/module_auto_update/tests/test_module_upgrade_deprecated.py +++ b/module_auto_update/tests/test_module_upgrade_deprecated.py @@ -7,12 +7,15 @@ 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), ]) diff --git a/module_auto_update/wizards/module_upgrade_deprecated.py b/module_auto_update/wizards/module_upgrade_deprecated.py index 8634c38e5..b44ec684d 100644 --- a/module_auto_update/wizards/module_upgrade_deprecated.py +++ b/module_auto_update/wizards/module_upgrade_deprecated.py @@ -1,49 +1,84 @@ # 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 - @api.returns('ir.module.module') + 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.""" - 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() + 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.""" - # Compute updates by checksum when called in @api.model fashion - 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"])} + 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() - # 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 + 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 From 679660ec4a6a0f2de9320858a90554ff27b23bc3 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 27 Mar 2018 09:53:33 +0100 Subject: [PATCH 12/31] [FIX] module_auto_update: Add .pyo sample file (#1205) Without this patch, if your tests are run under a `PYTHONOPTIMIZE=2` precompiled environment, they'd fail with this error because a new `.pyo` file would be created.: FAIL: test_basic (openerp.addons.module_auto_update.tests.test_addon_hash.TestAddonHash) Traceback (most recent call last): ` File "/opt/odoo/auto/addons/module_auto_update/tests/test_addon_hash.py", line 41, in test_basic ` 'static/src/some.js', ` AssertionError: Lists differ: ['README.rst', 'data/f1.xml', ... != ['README.rst', 'data/f1.xml', ... ` ` First differing element 13: ` models/stuff.pyo ` static/src/some.js ` ` First list contains 1 additional elements. ` First extra element 14: ` static/src/some.js ` ` ['README.rst', ` 'data/f1.xml', ` 'data/f2.xml', ` 'i18n/en.po', ` 'i18n/en_US.po', ` 'i18n/fr.po', ` 'i18n/fr_BE.po', ` 'i18n/test.pot', ` 'i18n_extra/en.po', ` 'i18n_extra/fr.po', ` 'i18n_extra/nl_NL.po', ` 'models/stuff.py', ` 'models/stuff.pyc', ` - 'models/stuff.pyo', ` 'static/src/some.js'] Ran 3 tests in 0.005s FAILED With this patch, the `.pyo` file is included, so tests will pass anywhere. --- .../tests/sample_module/models/stuff.pyo | Bin 0 -> 109 bytes module_auto_update/tests/test_addon_hash.py | 1 + 2 files changed, 1 insertion(+) create mode 100644 module_auto_update/tests/sample_module/models/stuff.pyo diff --git a/module_auto_update/tests/sample_module/models/stuff.pyo b/module_auto_update/tests/sample_module/models/stuff.pyo new file mode 100644 index 0000000000000000000000000000000000000000..b592f19841e2fdfc90a584eb75703c9eed4782f2 GIT binary patch literal 109 zcmZSn%*$2zb3;@z0~9a;X$K%K<^U2YObm=Ej10jV%s@^iBaraR1S!w}Vsrwmp}3?p ZElsbWvIL~tCO1E&G$+*#q^}sH0{}a24`BcR literal 0 HcmV?d00001 diff --git a/module_auto_update/tests/test_addon_hash.py b/module_auto_update/tests/test_addon_hash.py index 7523b8ec4..3827c5aed 100644 --- a/module_auto_update/tests/test_addon_hash.py +++ b/module_auto_update/tests/test_addon_hash.py @@ -38,6 +38,7 @@ class TestAddonHash(unittest.TestCase): 'i18n_extra/nl_NL.po', 'models/stuff.py', 'models/stuff.pyc', + 'models/stuff.pyo', 'static/src/some.js', ]) From 87ae683f24ec897a16a4abd3245e086e0957c3aa Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Tue, 27 Mar 2018 14:45:58 +0200 Subject: [PATCH 13/31] [FIX] Forward port module_auto_update refactoring from 9.0 --- module_auto_update/migrations/10.0.2.0.0/pre-migrate.py | 2 +- module_auto_update/models/module.py | 4 ++-- module_auto_update/tests/test_module.py | 6 +++--- module_auto_update/tests/test_module_deprecated.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py index 4fe36ede7..b5f5aa86d 100644 --- a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py +++ b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py @@ -3,7 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). import logging from psycopg2 import IntegrityError -from openerp.addons.module_auto_update.models.module_deprecated import \ +from odoo.addons.module_auto_update.models.module_deprecated import \ PARAM_DEPRECATED _logger = logging.getLogger(__name__) diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 334ec9d16..6be1562de 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -7,8 +7,8 @@ import json import logging import os -from openerp import api, exceptions, models, tools -from openerp.modules.module import get_module_path +from odoo import api, exceptions, models, tools +from odoo.modules.module import get_module_path from ..addon_hash import addon_hash diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index b4f0746c3..6558f0276 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -8,9 +8,9 @@ import tempfile import mock -from openerp.modules import get_module_path -from openerp.tests import common -from openerp.tests.common import TransactionCase +from odoo.modules import get_module_path +from odoo.tests import common +from odoo.tests.common import TransactionCase from ..addon_hash import addon_hash from ..models.module import IncompleteUpgradeError, DEFAULT_EXCLUDE_PATTERNS diff --git a/module_auto_update/tests/test_module_deprecated.py b/module_auto_update/tests/test_module_deprecated.py index 99d0ee4ec..a83881d11 100644 --- a/module_auto_update/tests/test_module_deprecated.py +++ b/module_auto_update/tests/test_module_deprecated.py @@ -9,7 +9,7 @@ from odoo.modules import get_module_path from odoo.tests.common import TransactionCase from odoo.tools import mute_logger -from openerp.addons.module_auto_update.addon_hash import addon_hash +from odoo.addons.module_auto_update.addon_hash import addon_hash from ..models.module_deprecated import PARAM_DEPRECATED From 43e43e9f342d69bd2b0652d833e204916517efe2 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 27 Mar 2018 09:45:57 +0100 Subject: [PATCH 14/31] [FIX] module_auto_update: Rollback cursor if param exists Without this patch, when upgrading after you have stored the deprecated features parameter, the cursor became broken and no more migrations could happen. You got this error: Traceback (most recent call last): File "/usr/local/bin/odoo", line 6, in exec(compile(open(__file__).read(), __file__, 'exec')) File "/opt/odoo/custom/src/odoo/odoo.py", line 160, in main() File "/opt/odoo/custom/src/odoo/odoo.py", line 157, in main openerp.cli.main() File "/opt/odoo/custom/src/odoo/openerp/cli/command.py", line 64, in main o.run(args) File "/opt/odoo/custom/src/odoo/openerp/cli/shell.py", line 65, in run self.shell(openerp.tools.config['db_name']) File "/opt/odoo/custom/src/odoo/openerp/cli/shell.py", line 52, in shell registry = openerp.modules.registry.RegistryManager.get(dbname) File "/opt/odoo/custom/src/odoo/openerp/modules/registry.py", line 355, in get update_module) File "/opt/odoo/custom/src/odoo/openerp/modules/registry.py", line 386, in new openerp.modules.load_modules(registry._db, force_demo, status, update_module) File "/opt/odoo/custom/src/odoo/openerp/modules/loading.py", line 335, in load_modules force, status, report, loaded_modules, update_module) File "/opt/odoo/custom/src/odoo/openerp/modules/loading.py", line 239, in load_marked_modules loaded, processed = load_module_graph(cr, graph, progressdict, report=report, skip_modules=loaded_modules, perform_checks=perform_checks) File "/opt/odoo/custom/src/odoo/openerp/modules/loading.py", line 136, in load_module_graph registry.setup_models(cr, partial=True) File "/opt/odoo/custom/src/odoo/openerp/modules/registry.py", line 186, in setup_models cr.execute('select model, transient from ir_model where state=%s', ('manual',)) File "/opt/odoo/custom/src/odoo/openerp/sql_db.py", line 154, in wrapper return f(self, *args, **kwargs) File "/opt/odoo/custom/src/odoo/openerp/sql_db.py", line 233, in execute res = self._obj.execute(query, params) psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block Now you can safely migrate, be that parameter pre-created or not. --- .../migrations/10.0.2.0.0/pre-migrate.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py index b5f5aa86d..92135d174 100644 --- a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py +++ b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py @@ -12,10 +12,12 @@ _logger = logging.getLogger(__name__) def migrate(cr, version): """Autoenable deprecated behavior.""" try: - cr.execute( - "INSERT INTO ir_config_parameter (key, value) VALUES (%s, '1')", - (PARAM_DEPRECATED,) - ) + 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.") From 759c8402b12960c90eb19239378461ee8864b61d Mon Sep 17 00:00:00 2001 From: Benjamin Willig Date: Mon, 9 Apr 2018 14:10:12 +0200 Subject: [PATCH 15/31] [CHG] updated version number --- module_auto_update/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index d39962c1c..1fa4b8ae4 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '11.0.1.0.0', + 'version': '11.0.2.0.0', 'category': 'Extra Tools', 'website': 'https://github.com/OCA/server-tools', 'author': 'LasLabs, ' From c7c8a6eb60fb56fb392a8c8fe4550230dc4a50bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Thu, 17 May 2018 18:13:46 +0200 Subject: [PATCH 16/31] module_auto_update: check a post condition --- module_auto_update/models/module.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 6be1562de..29047ed70 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -22,10 +22,30 @@ DEFAULT_EXCLUDE_PATTERNS = \ _logger = logging.getLogger(__name__) +class FailedUpgradeError(exceptions.UserError): + pass + + class IncompleteUpgradeError(exceptions.UserError): pass +def ensure_module_state(env, modules, state): + # read module states, bypassing any Odoo cache + env.cr.execute( + "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()] + if names: + raise FailedUpgradeError( + "The following modules should be in state '%s' " + "at this stage: %s. Bailing out for safety." % + (state, ','.join(names), ), + ) + + class Module(models.Model): _inherit = 'ir.module.module' @@ -128,6 +148,11 @@ class Module(models.Model): ','.join(changed_modules.mapped('name'))) changed_modules.button_upgrade() self.env.cr.commit() # pylint: disable=invalid-commit + # in rare situations, button_upgrade may fail without + # exception, this would lead to corruption because + # no upgrade would be performed and save_installed_checksums + # would update cheksums for modules that have not been upgraded + ensure_module_state(self.env, changed_modules, 'to upgrade') _logger.info("Upgrading...") self.env['base.module.upgrade'].upgrade_module() From 97875e077c627277c748bce13ac61be40c2edc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Thu, 17 May 2018 19:13:01 +0200 Subject: [PATCH 17/31] module_auto_update: bump version --- module_auto_update/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 1fa4b8ae4..d103ca7f6 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '11.0.2.0.0', + 'version': '11.0.2.0.2', 'category': 'Extra Tools', 'website': 'https://github.com/OCA/server-tools', 'author': 'LasLabs, ' From 079267155c105eaaa7c36085628fe1bdf4ce0dfe Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 22 May 2018 12:50:15 +0100 Subject: [PATCH 18/31] [FIX] module_auto_update: Ignore `__pycache__` in hash test Python >= 3.2 implements [PEP 3147](https://www.python.org/dev/peps/pep-3147/), so in a precompiled environment, the patched test could fail with this or similar: FAIL: test_basic (odoo.addons.module_auto_update.tests.test_addon_hash.TestAddonHash) Traceback (most recent call last): ` File "/opt/odoo/auto/addons/module_auto_update/tests/test_addon_hash.py", line 42, in test_basic ` 'static/src/some.js', ` AssertionError: Lists differ: ['REA[237 chars]o', 'models/__pycache__/stuff.cpython-35.opt-1[23 chars].js'] != ['REA[237 chars]o', 'static/src/some.js'] ` ` First differing element 14: ` 'models/__pycache__/stuff.cpython-35.opt-1.pyc' ` 'static/src/some.js' ` ` First list contains 1 additional elements. ` First extra element 15: ` 'static/src/some.js' ` ` ['README.rst', ` 'data/f1.xml', ` 'data/f2.xml', ` 'i18n/en.po', ` 'i18n/en_US.po', ` 'i18n/fr.po', ` 'i18n/fr_BE.po', ` 'i18n/test.pot', ` 'i18n_extra/en.po', ` 'i18n_extra/fr.po', ` 'i18n_extra/nl_NL.po', ` 'models/stuff.py', ` 'models/stuff.pyc', ` 'models/stuff.pyo', ` - 'models/__pycache__/stuff.cpython-35.opt-1.pyc', ` 'static/src/some.js'] With this patch, we fix all those failing tests in integration environments. --- module_auto_update/__manifest__.py | 2 +- module_auto_update/tests/test_addon_hash.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index d103ca7f6..61e54e26c 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '11.0.2.0.2', + 'version': '11.0.2.0.3', 'category': 'Extra Tools', 'website': 'https://github.com/OCA/server-tools', 'author': 'LasLabs, ' diff --git a/module_auto_update/tests/test_addon_hash.py b/module_auto_update/tests/test_addon_hash.py index 3827c5aed..290375762 100644 --- a/module_auto_update/tests/test_addon_hash.py +++ b/module_auto_update/tests/test_addon_hash.py @@ -21,7 +21,7 @@ class TestAddonHash(unittest.TestCase): def test_basic(self): files = list(addon_hash._walk( self.sample_dir, - exclude_patterns=[], + exclude_patterns=["*/__pycache__/*"], keep_langs=[], )) self.assertEqual(files, [ From 602caa2b16c6d16df7afdf86b01fd3bf737c30f2 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Fri, 1 Jun 2018 15:49:13 +0200 Subject: [PATCH 19/31] [10.0][FIX] module_auto_update: Don't set 'to upgrade' on void recordset modules --- module_auto_update/models/module.py | 2 ++ module_auto_update/tests/test_module.py | 36 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index 29047ed70..e561abe5a 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -32,6 +32,8 @@ class IncompleteUpgradeError(exceptions.UserError): def ensure_module_state(env, modules, state): # read module states, bypassing any Odoo cache + if not modules: + return env.cr.execute( "SELECT name FROM ir_module_module " "WHERE id IN %s AND state != %s", diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index 6558f0276..493f75dfe 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -180,6 +180,42 @@ class TestModuleAfterInstall(TransactionCase): finally: Bmu._revert_method('upgrade_module') + def test_incomplete_upgrade_no_checkusm(self): + Imm = self.env['ir.module.module'] + Bmu = self.env['base.module.upgrade'] + + installed_modules = Imm.search( + [('state', '=', 'installed')]) + # change the checksum of 'base' + Imm._save_installed_checksums() + saved_checksums = Imm._get_saved_checksums() + + Imm._save_checksums(saved_checksums) + self.base_module.write({'state': 'to upgrade'}) + + def upgrade_module_mock(self_model): + upgrade_module_mock.call_count += 1 + # since we are upgrading base, all installed module + # must have been marked to upgrade at this stage + self.assertEqual(self.base_module.state, 'to upgrade') + self.assertEqual(self.own_module.state, 'installed') + installed_modules.write({'state': 'installed'}) + + upgrade_module_mock.call_count = 0 + + # upgrade_changed_checksum commits, so mock that + with mock.patch.object(self.env.cr, 'commit'): + + # we simulate an install by setting module states + Bmu._patch_method('upgrade_module', + upgrade_module_mock) + # got just other modules to_upgrade and no checksum ones + try: + Imm.upgrade_changed_checksum() + self.assertEqual(upgrade_module_mock.call_count, 1) + finally: + Bmu._revert_method('upgrade_module') + def test_nothing_to_upgrade(self): Imm = self.env['ir.module.module'] Bmu = self.env['base.module.upgrade'] From 238a6df7a3c511f93401ebe455fd0854f55952b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Sat, 2 Jun 2018 09:43:58 +0200 Subject: [PATCH 20/31] module_auto_update: sbidoul as maintainer Plus Stable development status --- module_auto_update/__manifest__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 61e54e26c..8baa3f1da 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -22,4 +22,6 @@ 'data': [ 'data/cron_data_deprecated.xml', ], + 'development_status': 'Production/Stable', + 'maintainers': ['sbidoul'], } From 4710f2a56b3a17be058c5f27ceeb173a03cbb931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Sat, 2 Jun 2018 09:45:48 +0200 Subject: [PATCH 21/31] module_auto_update: readme fragments --- module_auto_update/readme/CONFIGURE.rst | 9 +++++++++ module_auto_update/readme/CONTRIBUTORS.rst | 4 ++++ module_auto_update/readme/DESCRIPTION.rst | 4 ++++ module_auto_update/readme/ROADMAP.rst | 17 +++++++++++++++++ module_auto_update/readme/USAGE.rst | 16 ++++++++++++++++ 5 files changed, 50 insertions(+) create mode 100644 module_auto_update/readme/CONFIGURE.rst create mode 100644 module_auto_update/readme/CONTRIBUTORS.rst create mode 100644 module_auto_update/readme/DESCRIPTION.rst create mode 100644 module_auto_update/readme/ROADMAP.rst create mode 100644 module_auto_update/readme/USAGE.rst diff --git a/module_auto_update/readme/CONFIGURE.rst b/module_auto_update/readme/CONFIGURE.rst new file mode 100644 index 000000000..b46e74563 --- /dev/null +++ b/module_auto_update/readme/CONFIGURE.rst @@ -0,0 +1,9 @@ +This module supports the following system parameters: + +* ``module_auto_update.exclude_patterns``: comma-separated list of file + name patterns to ignore when computing addon checksums. Defaults to + ``*.pyc,*.pyo,i18n/*.pot,i18n_extra/*.pot,static/*``. + Filename patterns must be compatible with the python ``fnmatch`` function. + +In addition to the above pattern, .po files corresponding to languages that +are not installed in the Odoo database are ignored when computing checksums. diff --git a/module_auto_update/readme/CONTRIBUTORS.rst b/module_auto_update/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..966ffea55 --- /dev/null +++ b/module_auto_update/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* Brent Hughes +* Juan José Scarafía +* Jairo Llopis +* Stéphane Bidoul (https://acsone.eu) diff --git a/module_auto_update/readme/DESCRIPTION.rst b/module_auto_update/readme/DESCRIPTION.rst new file mode 100644 index 000000000..1c1cd09b1 --- /dev/null +++ b/module_auto_update/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This addon provides mechanisms to compute sha1 hashes of installed addons, +and save them in the database. It also provides a method that exploits these +mechanisms to update a database by upgrading only the modules for which the +hash has changed since the last successful upgrade. diff --git a/module_auto_update/readme/ROADMAP.rst b/module_auto_update/readme/ROADMAP.rst new file mode 100644 index 000000000..19dad6fdc --- /dev/null +++ b/module_auto_update/readme/ROADMAP.rst @@ -0,0 +1,17 @@ +* 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``. diff --git a/module_auto_update/readme/USAGE.rst b/module_auto_update/readme/USAGE.rst new file mode 100644 index 000000000..56b4ea468 --- /dev/null +++ b/module_auto_update/readme/USAGE.rst @@ -0,0 +1,16 @@ +The main method provided by this module is ``upgrade_changed_checksum`` +on ``ir.module.module``. It runs a database upgrade for all installed +modules for which the hash has changed since the last successful +run of this method. On success it saves the hashes in the database. + +The first time this method is invoked after installing the module, it +runs an upgrade of all modules, because it has not saved the hashes yet. +This is by design, priviledging safety. Should this be an issue, +the method ``_save_installed_checksums`` can be invoked in a situation +where one is sure all modules on disk are installed and up-to-date in the +database. + +An easy way to invoke this upgrade mechanism is by issuing the following +in an Odoo shell session:: + + env['ir.module.module'].upgrade_changed_checksum() From d8021eb963995f3f68d2d6d3d795e1d12163b96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Mon, 4 Jun 2018 15:39:45 +0200 Subject: [PATCH 22/31] [UPD] README.rst --- module_auto_update/README.rst | 73 ++- .../static/description/index.html | 482 ++++++++++++++++++ 2 files changed, 533 insertions(+), 22 deletions(-) create mode 100644 module_auto_update/static/description/index.html diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index 1dd66fbbd..175c6ff1a 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -1,16 +1,37 @@ -.. 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 file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/11.0/module_auto_update + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| + This addon provides mechanisms to compute sha1 hashes of installed addons, and save them in the database. It also provides a method that exploits these mechanisms to update a database by upgrading only the modules for which the hash has changed since the last successful upgrade. +**Table of contents** + +.. contents:: + :local: + Configuration ============= @@ -44,10 +65,6 @@ in an Odoo shell session:: env['ir.module.module'].upgrade_changed_checksum() -.. 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/11.0 - Known issues / Roadmap ====================== @@ -72,40 +89,52 @@ Known issues / Roadmap 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. +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 smashing it by providing a detailed and welcomed feedback. + +Do not contact contributors directly about support or help with technical issues. Credits ======= -Images ------- +Authors +~~~~~~~ -* Odoo Community Association: `Icon `_. +* LasLabs +* Juan José Scarafía +* Tecnativa +* ACSONE SA/NV Contributors ------------- +~~~~~~~~~~~~ * Brent Hughes * Juan José Scarafía * Jairo Llopis * Stéphane Bidoul (https://acsone.eu) -Do not contact contributors directly about support or help with technical issues. +Maintainers +~~~~~~~~~~~ -Maintainer ----------- +This module is maintained by the OCA. .. 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. +.. |maintainer-sbidoul| image:: https://github.com/sbidoul.png?size=40px + :target: https://github.com/sbidoul + :alt: sbidoul + +Current `maintainer `_: + +|maintainer-sbidoul| + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/module_auto_update/static/description/index.html b/module_auto_update/static/description/index.html new file mode 100644 index 000000000..e11114305 --- /dev/null +++ b/module_auto_update/static/description/index.html @@ -0,0 +1,482 @@ + + + + + + +Module Auto Update + + + +
+

Module Auto Update

+ + +

Production/Stable License: LGPL-3 OCA/server-tools Try me on Runbot

+

This addon provides mechanisms to compute sha1 hashes of installed addons, +and save them in the database. It also provides a method that exploits these +mechanisms to update a database by upgrading only the modules for which the +hash has changed since the last successful upgrade.

+

Table of contents

+ +
+

Configuration

+

This module supports the following system parameters:

+
    +
  • module_auto_update.exclude_patterns: comma-separated list of file +name patterns to ignore when computing addon checksums. Defaults to +*.pyc,*.pyo,i18n/*.pot,i18n_extra/*.pot,static/*. +Filename patterns must be compatible with the python fnmatch function.
  • +
+

In addition to the above pattern, .po files corresponding to languages that +are not installed in the Odoo database are ignored when computing checksums.

+
+
+

Usage

+

The main method provided by this module is upgrade_changed_checksum +on ir.module.module. It runs a database upgrade for all installed +modules for which the hash has changed since the last successful +run of this method. On success it saves the hashes in the database.

+

The first time this method is invoked after installing the module, it +runs an upgrade of all modules, because it has not saved the hashes yet. +This is by design, priviledging safety. Should this be an issue, +the method _save_installed_checksums can be invoked in a situation +where one is sure all modules on disk are installed and up-to-date in the +database.

+

An easy way to invoke this upgrade mechanism is by issuing the following +in an Odoo shell session:

+
+env['ir.module.module'].upgrade_changed_checksum()
+
+
+
+

Known issues / Roadmap

+
    +
  • 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.

    +
  • +
+
+
+

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 smashing it by providing a detailed and welcomed feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • LasLabs
  • +
  • Juan José Scarafía
  • +
  • Tecnativa
  • +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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.

+

Current maintainer:

+

sbidoul

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + From 2d8f1331b7dcf110ef5445db95e8eb094578bdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Mon, 4 Jun 2018 15:39:12 +0200 Subject: [PATCH 23/31] module_auto_update: 11.0.2.0.4 --- module_auto_update/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 8baa3f1da..0b2ff5e2c 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '11.0.2.0.3', + 'version': '11.0.2.0.4', 'category': 'Extra Tools', 'website': 'https://github.com/OCA/server-tools', 'author': 'LasLabs, ' From a9882b32da082ee9a4e560ff9a603219ef910250 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Sun, 17 Jun 2018 20:50:53 +0000 Subject: [PATCH 24/31] [UPD] Update module_auto_update.pot --- module_auto_update/i18n/ca.po | 29 ++++--------- module_auto_update/i18n/cs_CZ.po | 35 +++++++--------- module_auto_update/i18n/de.po | 32 +++++--------- module_auto_update/i18n/es.po | 29 ++++--------- module_auto_update/i18n/es_MX.po | 32 +++++--------- module_auto_update/i18n/fr.po | 32 ++++++-------- module_auto_update/i18n/hr.po | 32 +++++--------- module_auto_update/i18n/it.po | 29 ++++--------- .../i18n/module_auto_update.pot | 42 +++++++++++++++++++ module_auto_update/i18n/nl_NL.po | 32 +++++--------- module_auto_update/i18n/pt_BR.po | 32 +++++--------- module_auto_update/i18n/sl.po | 32 +++++--------- module_auto_update/i18n/tr.po | 29 ++++--------- 13 files changed, 161 insertions(+), 256 deletions(-) create mode 100644 module_auto_update/i18n/module_auto_update.pot diff --git a/module_auto_update/i18n/ca.po b/module_auto_update/i18n/ca.po index 90b967e03..d1939a71f 100644 --- a/module_auto_update/i18n/ca.po +++ b/module_auto_update/i18n/ca.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -12,20 +12,20 @@ msgstr "" "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" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +39,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/cs_CZ.po b/module_auto_update/i18n/cs_CZ.po index 754cd18bf..78054a472 100644 --- a/module_auto_update/i18n/cs_CZ.po +++ b/module_auto_update/i18n/cs_CZ.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # Lukáš Spurný , 2018 msgid "" @@ -11,11 +11,12 @@ msgstr "" "POT-Creation-Date: 2018-03-03 10:08+0000\n" "PO-Revision-Date: 2018-03-03 10:08+0000\n" "Last-Translator: Lukáš Spurný , 2018\n" -"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/teams/23907/cs_CZ/)\n" +"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/" +"teams/23907/cs_CZ/)\n" +"Language: cs_CZ\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: cs_CZ\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #. module: module_auto_update @@ -38,16 +39,6 @@ msgstr "Modul" msgid "Module Upgrade" msgstr "Aktualizace modulů" -#. module: module_auto_update -#: model:ir.ui.menu,name:module_auto_update.menu_default_modules -msgid "Modules" -msgstr "Moduly" - -#. 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 "Otevřít aktualizaci a aktualizovat seznam serverových akcí" - #. module: module_auto_update #: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server #: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron @@ -55,12 +46,14 @@ msgstr "Otevřít aktualizaci a aktualizovat seznam serverových akcí" msgid "Perform Module Upgrades" msgstr "Provést aktualizaci modulů" -#. module: module_auto_update -#: model:ir.ui.view,arch_db:module_auto_update.module_view_search -msgid "Scheduled Upgrades" -msgstr "Plánované aktualizace" +#~ msgid "Modules" +#~ msgstr "Moduly" -#. module: module_auto_update -#: model:ir.ui.menu,name:module_auto_update.module_menu_updates -msgid "Updates" -msgstr "Aktualizace" +#~ msgid "Open Updates and Update Apps List Server Action" +#~ msgstr "Otevřít aktualizaci a aktualizovat seznam serverových akcí" + +#~ msgid "Scheduled Upgrades" +#~ msgstr "Plánované aktualizace" + +#~ msgid "Updates" +#~ msgstr "Aktualizace" diff --git a/module_auto_update/i18n/de.po b/module_auto_update/i18n/de.po index 0938aac2a..62df9c002 100644 --- a/module_auto_update/i18n/de.po +++ b/module_auto_update/i18n/de.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # Niki Waibel , 2017 msgid "" @@ -12,20 +12,20 @@ msgstr "" "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" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +39,9 @@ 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 "" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +#, fuzzy +msgid "Perform Module Upgrades" +msgstr "Modul aktualisieren" diff --git a/module_auto_update/i18n/es.po b/module_auto_update/i18n/es.po index 682b6172c..10347b507 100644 --- a/module_auto_update/i18n/es.po +++ b/module_auto_update/i18n/es.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2018 # enjolras , 2018 @@ -13,10 +13,10 @@ msgstr "" "PO-Revision-Date: 2018-03-03 10:08+0000\n" "Last-Translator: enjolras , 2018\n" "Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"Language: 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 @@ -39,16 +39,6 @@ msgstr "Módulo" 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 "Módulos" - -#. 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.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server #: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron @@ -56,12 +46,11 @@ msgstr "" msgid "Perform Module Upgrades" msgstr "" -#. module: module_auto_update -#: model:ir.ui.view,arch_db:module_auto_update.module_view_search -msgid "Scheduled Upgrades" -msgstr "Actualizaciones programadas" +#~ msgid "Modules" +#~ msgstr "Módulos" -#. module: module_auto_update -#: model:ir.ui.menu,name:module_auto_update.module_menu_updates -msgid "Updates" -msgstr "Actualizaciones" +#~ msgid "Scheduled Upgrades" +#~ msgstr "Actualizaciones programadas" + +#~ msgid "Updates" +#~ msgstr "Actualizaciones" diff --git a/module_auto_update/i18n/es_MX.po b/module_auto_update/i18n/es_MX.po index 6a52834e7..8420bf5be 100644 --- a/module_auto_update/i18n/es_MX.po +++ b/module_auto_update/i18n/es_MX.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -11,21 +11,22 @@ msgstr "" "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" +"Language-Team: Spanish (Mexico) (https://www.transifex.com/oca/teams/23907/" +"es_MX/)\n" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +40,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/fr.po b/module_auto_update/i18n/fr.po index 25920a9db..3da594ac8 100644 --- a/module_auto_update/i18n/fr.po +++ b/module_auto_update/i18n/fr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # Nicolas JEUDY , 2018 msgid "" @@ -12,10 +12,10 @@ msgstr "" "PO-Revision-Date: 2018-03-03 10:08+0000\n" "Last-Translator: Nicolas JEUDY , 2018\n" "Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. module: module_auto_update @@ -38,16 +38,6 @@ msgstr "Module" msgid "Module Upgrade" msgstr "Mise à niveau du module" -#. module: module_auto_update -#: model:ir.ui.menu,name:module_auto_update.menu_default_modules -msgid "Modules" -msgstr "Modules" - -#. 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 "Afficher les mises à jour" - #. module: module_auto_update #: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server #: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron @@ -55,12 +45,14 @@ msgstr "Afficher les mises à jour" msgid "Perform Module Upgrades" msgstr "Appliquer les mise à jour de modules" -#. module: module_auto_update -#: model:ir.ui.view,arch_db:module_auto_update.module_view_search -msgid "Scheduled Upgrades" -msgstr "Planifier les mises à jour" +#~ msgid "Modules" +#~ msgstr "Modules" -#. module: module_auto_update -#: model:ir.ui.menu,name:module_auto_update.module_menu_updates -msgid "Updates" -msgstr "Mises à jour" +#~ msgid "Open Updates and Update Apps List Server Action" +#~ msgstr "Afficher les mises à jour" + +#~ msgid "Scheduled Upgrades" +#~ msgstr "Planifier les mises à jour" + +#~ msgid "Updates" +#~ msgstr "Mises à jour" diff --git a/module_auto_update/i18n/hr.po b/module_auto_update/i18n/hr.po index 7cae9d5f4..a4c44663f 100644 --- a/module_auto_update/i18n/hr.po +++ b/module_auto_update/i18n/hr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # Bole , 2017 msgid "" @@ -12,20 +12,21 @@ msgstr "" "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" +"Language: 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" +"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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +40,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/it.po b/module_auto_update/i18n/it.po index 91f03c624..49899eabe 100644 --- a/module_auto_update/i18n/it.po +++ b/module_auto_update/i18n/it.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -12,20 +12,20 @@ msgstr "" "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" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +39,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/module_auto_update.pot b/module_auto_update/i18n/module_auto_update.pot new file mode 100644 index 000000000..c65254600 --- /dev/null +++ b/module_auto_update/i18n/module_auto_update.pot @@ -0,0 +1,42 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * module_auto_update +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \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_auto_update +#: model:ir.model,name:module_auto_update.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: module_auto_update +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" +msgstr "" + diff --git a/module_auto_update/i18n/nl_NL.po b/module_auto_update/i18n/nl_NL.po index 340b85847..a95995fea 100644 --- a/module_auto_update/i18n/nl_NL.po +++ b/module_auto_update/i18n/nl_NL.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # Peter Hageman , 2017 msgid "" @@ -11,21 +11,22 @@ msgstr "" "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" +"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/" +"teams/23907/nl_NL/)\n" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +40,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/pt_BR.po b/module_auto_update/i18n/pt_BR.po index aef834e1b..237b12392 100644 --- a/module_auto_update/i18n/pt_BR.po +++ b/module_auto_update/i18n/pt_BR.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -11,21 +11,22 @@ msgstr "" "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" +"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/" +"teams/23907/pt_BR/)\n" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +40,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/sl.po b/module_auto_update/i18n/sl.po index b14fb1443..dc1b9b7cb 100644 --- a/module_auto_update/i18n/sl.po +++ b/module_auto_update/i18n/sl.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -12,20 +12,21 @@ msgstr "" "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" +"Language: 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" +"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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +40,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" diff --git a/module_auto_update/i18n/tr.po b/module_auto_update/i18n/tr.po index 2b6b538a1..2e1adb0e6 100644 --- a/module_auto_update/i18n/tr.po +++ b/module_auto_update/i18n/tr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * module_auto_update -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -12,20 +12,20 @@ msgstr "" "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" +"Language: 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" +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" +msgid "Checksum Installed" msgstr "" #. module: module_auto_update @@ -39,21 +39,8 @@ 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" +#: model:ir.actions.server,name:module_auto_update.module_check_upgrades_cron_ir_actions_server +#: model:ir.cron,cron_name:module_auto_update.module_check_upgrades_cron +#: model:ir.cron,name:module_auto_update.module_check_upgrades_cron +msgid "Perform Module Upgrades" msgstr "" From fbefe9c587d86e3a5fd89554142568a7cf317f90 Mon Sep 17 00:00:00 2001 From: OCA Git Bot Date: Thu, 21 Jun 2018 05:31:09 +0200 Subject: [PATCH 25/31] [UPD] README.rst --- module_auto_update/README.rst | 10 +++++++--- module_auto_update/static/description/index.html | 5 +++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index 175c6ff1a..ec2c139e0 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -16,11 +16,14 @@ Module Auto Update .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github :target: https://github.com/OCA/server-tools/tree/11.0/module_auto_update :alt: OCA/server-tools -.. |badge4| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-11-0/server-tools-11-0-module_auto_update + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png :target: https://runbot.odoo-community.org/runbot/149/11.0 :alt: Try me on Runbot -|badge1| |badge2| |badge3| |badge4| +|badge1| |badge2| |badge3| |badge4| |badge5| This addon provides mechanisms to compute sha1 hashes of installed addons, and save them in the database. It also provides a method that exploits these @@ -91,7 +94,8 @@ 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 smashing it by providing a detailed and welcomed feedback. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. Do not contact contributors directly about support or help with technical issues. diff --git a/module_auto_update/static/description/index.html b/module_auto_update/static/description/index.html index e11114305..0efdc5578 100644 --- a/module_auto_update/static/description/index.html +++ b/module_auto_update/static/description/index.html @@ -367,7 +367,7 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Production/Stable License: LGPL-3 OCA/server-tools Try me on Runbot

+

Production/Stable License: LGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

This addon provides mechanisms to compute sha1 hashes of installed addons, and save them in the database. It also provides a method that exploits these mechanisms to update a database by upgrading only the modules for which the @@ -441,7 +441,8 @@ suffixed with _deprecated.

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 smashing it by providing a detailed and welcomed feedback.

+If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

Do not contact contributors directly about support or help with technical issues.

From 3e2824383ee92f85881d926af3890924db251398 Mon Sep 17 00:00:00 2001 From: OCA Git Bot Date: Sun, 5 Aug 2018 17:31:56 +0200 Subject: [PATCH 26/31] [UPD] README.rst --- module_auto_update/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_auto_update/README.rst b/module_auto_update/README.rst index ec2c139e0..e13559c73 100644 --- a/module_auto_update/README.rst +++ b/module_auto_update/README.rst @@ -135,7 +135,7 @@ promote its widespread use. :target: https://github.com/sbidoul :alt: sbidoul -Current `maintainer `_: +Current `maintainer `__: |maintainer-sbidoul| From 003a9443a93a6609bfa0d93755626a3f810a3584 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 3 Sep 2018 10:00:27 +0200 Subject: [PATCH 27/31] Global pylint cleanup --- module_auto_update/addon_hash.py | 1 - module_auto_update/migrations/10.0.2.0.0/pre-migrate.py | 1 - module_auto_update/models/module.py | 1 - module_auto_update/models/module_deprecated.py | 1 + module_auto_update/tests/sample_module/static/src/some.js | 2 +- module_auto_update/tests/test_addon_hash.py | 1 - module_auto_update/tests/test_module.py | 1 - module_auto_update/tests/test_module_deprecated.py | 3 +-- 8 files changed, 3 insertions(+), 8 deletions(-) diff --git a/module_auto_update/addon_hash.py b/module_auto_update/addon_hash.py index dea52b4f2..6bcbebf5a 100644 --- a/module_auto_update/addon_hash.py +++ b/module_auto_update/addon_hash.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 ACSONE SA/NV. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py index 92135d174..da98ab3ca 100644 --- a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py +++ b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 Tecnativa - Jairo Llopis # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). import logging diff --git a/module_auto_update/models/module.py b/module_auto_update/models/module.py index e561abe5a..aee072ac6 100644 --- a/module_auto_update/models/module.py +++ b/module_auto_update/models/module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # Copyright 2018 ACSONE SA/NV. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/models/module_deprecated.py b/module_auto_update/models/module_deprecated.py index 0cb9defaa..7383a8ac5 100644 --- a/module_auto_update/models/module_deprecated.py +++ b/module_auto_update/models/module_deprecated.py @@ -1,5 +1,6 @@ # 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 diff --git a/module_auto_update/tests/sample_module/static/src/some.js b/module_auto_update/tests/sample_module/static/src/some.js index 64797d825..896fe66fe 100644 --- a/module_auto_update/tests/sample_module/static/src/some.js +++ b/module_auto_update/tests/sample_module/static/src/some.js @@ -1 +1 @@ -/* javascript */ +/* Javascript */ diff --git a/module_auto_update/tests/test_addon_hash.py b/module_auto_update/tests/test_addon_hash.py index 290375762..884645168 100644 --- a/module_auto_update/tests/test_addon_hash.py +++ b/module_auto_update/tests/test_addon_hash.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 ACSONE SA/NV. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index 493f75dfe..e424f7701 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # Copyright 2018 ACSONE SA/NV. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/module_auto_update/tests/test_module_deprecated.py b/module_auto_update/tests/test_module_deprecated.py index a83881d11..ca0434fc8 100644 --- a/module_auto_update/tests/test_module_deprecated.py +++ b/module_auto_update/tests/test_module_deprecated.py @@ -9,8 +9,7 @@ from odoo.modules import get_module_path from odoo.tests.common import TransactionCase from odoo.tools import mute_logger -from odoo.addons.module_auto_update.addon_hash import addon_hash - +from .. addon_hash import addon_hash from ..models.module_deprecated import PARAM_DEPRECATED From 3a9ece40bdad91712a614dc3d613bcd94fca685f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Fri, 5 Oct 2018 18:09:47 +0200 Subject: [PATCH 28/31] Align .travis.yml with template --- .travis.yml | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2e9e39727..6c10faa4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,36 +7,21 @@ python: addons: postgresql: "9.6" - postgresql: "9.3" # minimal postgresql version for the base_import_security_group module - # more info: https://github.com/OCA/maintainer-quality-tools/issues/432 apt: packages: - expect-dev # provides unbuffer utility - - python-lxml # because pip installation is slow env: global: - - VERSION="12.0" TESTS="0" LINT_CHECK="0" TRANSIFEX="0" - - TRANSIFEX_USER='transbot@odoo-community.org' - - secure: Z06mZCN+Hm3myqHSOZpOOk1pd4oq1epAWZv6m9OX2bTNHbhyOVOGK6JWWsnDm/3DUCN1ZeLtSGOl9bvQfMa8ahQHA80MkLL16YlTvQV59Lh+L2gAYmxX+ogJCJgeQSVAXlGLscgkADCu/HzDlmatrDeROMtULn5i23j2qcyUNyM= + - VERSION="12.0" TESTS="0" LINT_CHECK="0" MAKEPOT="0" matrix: - LINT_CHECK="1" - - TRANSIFEX="1" - - TESTS="1" ODOO_REPO="OCA/OCB" EXCLUDE="database_cleanup" - - TESTS="1" ODOO_REPO="OCA/OCB" INCLUDE="database_cleanup" - - TESTS="1" ODOO_REPO="odoo/odoo" EXCLUDE="database_cleanup" - - TESTS="1" ODOO_REPO="odoo/odoo" INCLUDE="database_cleanup" - -before_install: - - "export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH" - - "if [ $(phantomjs --version) != '2.1.1' ]; then rm -rf $PWD/travis_phantomjs; mkdir -p $PWD/travis_phantomjs; fi" - - "if [ $(phantomjs --version) != '2.1.1' ]; then wget https://assets.membergetmember.co/software/phantomjs-2.1.1-linux-x86_64.tar.bz2 -O $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2; fi" - - "if [ $(phantomjs --version) != '2.1.1' ]; then tar -xvf $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs; fi" - - "phantomjs --version" + - TESTS="1" ODOO_REPO="OCA/OCB" + - TESTS="1" ODOO_REPO="OCA/OCB" MAKEPOT="1" install: - - git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools + - git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} - travis_install_nightly @@ -44,4 +29,4 @@ script: - travis_run_tests after_success: -- travis_after_tests_success + - travis_after_tests_success From dee3f2c0faff85521972d4238b148829c658f4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Fri, 5 Oct 2018 18:13:04 +0200 Subject: [PATCH 29/31] Add weblate translation status in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dbcbe7d01..c4d0c5495 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,4 @@ Do you want to contribute? Please read our [contributing guidelines](https://git Translation Status ------------------ -[![Transifex Status](https://www.transifex.com/projects/p/OCA-server-tools-12-0/chart/image_png)](https://www.transifex.com/projects/p/OCA-server-tools-12-0) +[![Translation status](https://translation.odoo-community.org/widgets/server-tools-12-0/-/multi-auto.svg)](https://translation.odoo-community.org/engage/server-tools-12-0/?utm_source=widget) From 2c25f45ac98cbe5ce195431b27bdf259031cbf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Fri, 5 Oct 2018 18:12:50 +0200 Subject: [PATCH 30/31] [MIG] module_auto_update from 11 to 12 Use tagged to mark post install tests as previous mechanism seems to be broken. --- module_auto_update/__init__.py | 1 - module_auto_update/__manifest__.py | 5 +- .../data/cron_data_deprecated.xml | 20 -- module_auto_update/hooks.py | 6 - .../migrations/10.0.2.0.0/pre-migrate.py | 24 -- module_auto_update/models/__init__.py | 1 - .../models/module_deprecated.py | 69 ------ module_auto_update/readme/ROADMAP.rst | 17 -- module_auto_update/tests/__init__.py | 2 - module_auto_update/tests/test_module.py | 7 +- .../tests/test_module_deprecated.py | 209 ------------------ .../tests/test_module_upgrade_deprecated.py | 46 ---- module_auto_update/wizards/__init__.py | 3 - .../wizards/module_upgrade_deprecated.py | 84 ------- setup/.setuptools-odoo-make-default-ignore | 2 + setup/README | 2 + .../odoo/addons/module_auto_update | 1 + setup/module_auto_update/setup.py | 6 + 18 files changed, 15 insertions(+), 490 deletions(-) delete mode 100644 module_auto_update/data/cron_data_deprecated.xml delete mode 100644 module_auto_update/migrations/10.0.2.0.0/pre-migrate.py delete mode 100644 module_auto_update/models/module_deprecated.py delete mode 100644 module_auto_update/readme/ROADMAP.rst delete mode 100644 module_auto_update/tests/test_module_deprecated.py delete mode 100644 module_auto_update/tests/test_module_upgrade_deprecated.py delete mode 100644 module_auto_update/wizards/__init__.py delete mode 100644 module_auto_update/wizards/module_upgrade_deprecated.py create mode 100644 setup/.setuptools-odoo-make-default-ignore create mode 100644 setup/README create mode 120000 setup/module_auto_update/odoo/addons/module_auto_update create mode 100644 setup/module_auto_update/setup.py diff --git a/module_auto_update/__init__.py b/module_auto_update/__init__.py index a0c82fd06..d2ad125af 100644 --- a/module_auto_update/__init__.py +++ b/module_auto_update/__init__.py @@ -1,5 +1,4 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from . import models -from . import wizards from .hooks import uninstall_hook diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index 0b2ff5e2c..b0b0c5033 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'Module Auto Update', 'summary': 'Automatically update Odoo modules', - 'version': '11.0.2.0.4', + 'version': '12.0.2.0.4', 'category': 'Extra Tools', 'website': 'https://github.com/OCA/server-tools', 'author': 'LasLabs, ' @@ -19,9 +19,6 @@ 'depends': [ 'base', ], - 'data': [ - 'data/cron_data_deprecated.xml', - ], 'development_status': 'Production/Stable', 'maintainers': ['sbidoul'], } diff --git a/module_auto_update/data/cron_data_deprecated.xml b/module_auto_update/data/cron_data_deprecated.xml deleted file mode 100644 index d903dbda6..000000000 --- a/module_auto_update/data/cron_data_deprecated.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - Perform Module Upgrades - - - 1 - days - -1 - - - code - model.upgrade_module() - - - diff --git a/module_auto_update/hooks.py b/module_auto_update/hooks.py index cd161a246..50b2eabf6 100644 --- a/module_auto_update/hooks.py +++ b/module_auto_update/hooks.py @@ -4,14 +4,8 @@ from odoo import SUPERUSER_ID, api from .models.module import PARAM_INSTALLED_CHECKSUMS -from .models.module_deprecated import PARAM_DEPRECATED def uninstall_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) 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() diff --git a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py b/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py deleted file mode 100644 index da98ab3ca..000000000 --- a/module_auto_update/migrations/10.0.2.0.0/pre-migrate.py +++ /dev/null @@ -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") diff --git a/module_auto_update/models/__init__.py b/module_auto_update/models/__init__.py index 53c05a539..e5ee3ea66 100644 --- a/module_auto_update/models/__init__.py +++ b/module_auto_update/models/__init__.py @@ -1,4 +1,3 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from . import module -from . import module_deprecated diff --git a/module_auto_update/models/module_deprecated.py b/module_auto_update/models/module_deprecated.py deleted file mode 100644 index 7383a8ac5..000000000 --- a/module_auto_update/models/module_deprecated.py +++ /dev/null @@ -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 diff --git a/module_auto_update/readme/ROADMAP.rst b/module_auto_update/readme/ROADMAP.rst deleted file mode 100644 index 19dad6fdc..000000000 --- a/module_auto_update/readme/ROADMAP.rst +++ /dev/null @@ -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``. diff --git a/module_auto_update/tests/__init__.py b/module_auto_update/tests/__init__.py index 54f7cc144..82778565d 100644 --- a/module_auto_update/tests/__init__.py +++ b/module_auto_update/tests/__init__.py @@ -2,5 +2,3 @@ from . import test_addon_hash from . import test_module -from . import test_module_deprecated -from . import test_module_upgrade_deprecated diff --git a/module_auto_update/tests/test_module.py b/module_auto_update/tests/test_module.py index e424f7701..f2d9486bf 100644 --- a/module_auto_update/tests/test_module.py +++ b/module_auto_update/tests/test_module.py @@ -7,9 +7,9 @@ import tempfile import mock +import odoo from odoo.modules import get_module_path -from odoo.tests import common -from odoo.tests.common import TransactionCase +from odoo.tests import TransactionCase from ..addon_hash import addon_hash from ..models.module import IncompleteUpgradeError, DEFAULT_EXCLUDE_PATTERNS @@ -79,8 +79,7 @@ class TestModule(TransactionCase): self.assertFalse(Imm._get_modules_with_changed_checksum()) -@common.at_install(False) -@common.post_install(True) +@odoo.tests.tagged('post_install', '-at_install') class TestModuleAfterInstall(TransactionCase): def setUp(self): diff --git a/module_auto_update/tests/test_module_deprecated.py b/module_auto_update/tests/test_module_deprecated.py deleted file mode 100644 index ca0434fc8..000000000 --- a/module_auto_update/tests/test_module_deprecated.py +++ /dev/null @@ -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', - ) diff --git a/module_auto_update/tests/test_module_upgrade_deprecated.py b/module_auto_update/tests/test_module_upgrade_deprecated.py deleted file mode 100644 index 13e729594..000000000 --- a/module_auto_update/tests/test_module_upgrade_deprecated.py +++ /dev/null @@ -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') diff --git a/module_auto_update/wizards/__init__.py b/module_auto_update/wizards/__init__.py deleted file mode 100644 index bcaca7966..000000000 --- a/module_auto_update/wizards/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import module_upgrade_deprecated diff --git a/module_auto_update/wizards/module_upgrade_deprecated.py b/module_auto_update/wizards/module_upgrade_deprecated.py deleted file mode 100644 index b44ec684d..000000000 --- a/module_auto_update/wizards/module_upgrade_deprecated.py +++ /dev/null @@ -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 diff --git a/setup/.setuptools-odoo-make-default-ignore b/setup/.setuptools-odoo-make-default-ignore new file mode 100644 index 000000000..207e61533 --- /dev/null +++ b/setup/.setuptools-odoo-make-default-ignore @@ -0,0 +1,2 @@ +# addons listed in this file are ignored by +# setuptools-odoo-make-default (one addon per line) diff --git a/setup/README b/setup/README new file mode 100644 index 000000000..a63d633e8 --- /dev/null +++ b/setup/README @@ -0,0 +1,2 @@ +To learn more about this directory, please visit +https://pypi.python.org/pypi/setuptools-odoo diff --git a/setup/module_auto_update/odoo/addons/module_auto_update b/setup/module_auto_update/odoo/addons/module_auto_update new file mode 120000 index 000000000..752ff6fc9 --- /dev/null +++ b/setup/module_auto_update/odoo/addons/module_auto_update @@ -0,0 +1 @@ +../../../../module_auto_update \ No newline at end of file diff --git a/setup/module_auto_update/setup.py b/setup/module_auto_update/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/module_auto_update/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From e278a0a05ff6d177049ab072cef1214de04b1f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Sat, 6 Oct 2018 14:58:47 +0200 Subject: [PATCH 31/31] module_auto_update: cosmetics --- module_auto_update/__manifest__.py | 1 - module_auto_update/readme/USAGE.rst | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module_auto_update/__manifest__.py b/module_auto_update/__manifest__.py index b0b0c5033..fe337dbff 100644 --- a/module_auto_update/__manifest__.py +++ b/module_auto_update/__manifest__.py @@ -13,7 +13,6 @@ 'ACSONE SA/NV, ' 'Odoo Community Association (OCA)', 'license': 'LGPL-3', - 'application': False, 'installable': True, 'uninstall_hook': 'uninstall_hook', 'depends': [ diff --git a/module_auto_update/readme/USAGE.rst b/module_auto_update/readme/USAGE.rst index 56b4ea468..39414ad0f 100644 --- a/module_auto_update/readme/USAGE.rst +++ b/module_auto_update/readme/USAGE.rst @@ -11,6 +11,8 @@ where one is sure all modules on disk are installed and up-to-date in the database. An easy way to invoke this upgrade mechanism is by issuing the following -in an Odoo shell session:: +in an Odoo shell session: + +.. code-block:: python env['ir.module.module'].upgrade_changed_checksum()