Browse Source

Merge pull request #1382 from acsone/12.0-mig-module_auto_update

[MIG][12.0] module auto update from 11 to 12
pull/1376/merge
Stéphane Bidoul (ACSONE) 6 years ago
committed by GitHub
parent
commit
da6a2f8004
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      .travis.yml
  2. 2
      README.md
  3. 144
      module_auto_update/README.rst
  4. 4
      module_auto_update/__init__.py
  5. 23
      module_auto_update/__manifest__.py
  6. 44
      module_auto_update/addon_hash.py
  7. 11
      module_auto_update/hooks.py
  8. 46
      module_auto_update/i18n/ca.po
  9. 59
      module_auto_update/i18n/cs_CZ.po
  10. 47
      module_auto_update/i18n/de.po
  11. 56
      module_auto_update/i18n/es.po
  12. 47
      module_auto_update/i18n/es_MX.po
  13. 58
      module_auto_update/i18n/fr.po
  14. 47
      module_auto_update/i18n/hr.po
  15. 46
      module_auto_update/i18n/it.po
  16. 42
      module_auto_update/i18n/module_auto_update.pot
  17. 47
      module_auto_update/i18n/nl_NL.po
  18. 47
      module_auto_update/i18n/pt_BR.po
  19. 47
      module_auto_update/i18n/sl.po
  20. 46
      module_auto_update/i18n/tr.po
  21. 3
      module_auto_update/models/__init__.py
  22. 174
      module_auto_update/models/module.py
  23. 9
      module_auto_update/readme/CONFIGURE.rst
  24. 4
      module_auto_update/readme/CONTRIBUTORS.rst
  25. 4
      module_auto_update/readme/DESCRIPTION.rst
  26. 18
      module_auto_update/readme/USAGE.rst
  27. 483
      module_auto_update/static/description/index.html
  28. 4
      module_auto_update/tests/__init__.py
  29. 1
      module_auto_update/tests/sample_module/README.rst
  30. 1
      module_auto_update/tests/sample_module/data/f1.xml
  31. 1
      module_auto_update/tests/sample_module/data/f2.xml
  32. 1
      module_auto_update/tests/sample_module/i18n/en.po
  33. 1
      module_auto_update/tests/sample_module/i18n/en_US.po
  34. 1
      module_auto_update/tests/sample_module/i18n/fr.po
  35. 1
      module_auto_update/tests/sample_module/i18n/fr_BE.po
  36. 1
      module_auto_update/tests/sample_module/i18n/test.pot
  37. 1
      module_auto_update/tests/sample_module/i18n_extra/en.po
  38. 1
      module_auto_update/tests/sample_module/i18n_extra/fr.po
  39. 1
      module_auto_update/tests/sample_module/i18n_extra/nl_NL.po
  40. 1
      module_auto_update/tests/sample_module/models/stuff.py
  41. BIN
      module_auto_update/tests/sample_module/models/stuff.pyc
  42. BIN
      module_auto_update/tests/sample_module/models/stuff.pyo
  43. 1
      module_auto_update/tests/sample_module/static/src/some.js
  44. 67
      module_auto_update/tests/test_addon_hash.py
  45. 237
      module_auto_update/tests/test_module.py
  46. 1
      setup/module_auto_update/odoo/addons/module_auto_update
  47. 6
      setup/module_auto_update/setup.py

23
.travis.yml

@ -7,36 +7,21 @@ python:
addons: addons:
postgresql: "9.6" 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: apt:
packages: packages:
- expect-dev # provides unbuffer utility - expect-dev # provides unbuffer utility
- python-lxml # because pip installation is slow
env: env:
global: 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: matrix:
- LINT_CHECK="1" - 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: 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} - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
- travis_install_nightly - travis_install_nightly

2
README.md

@ -18,4 +18,4 @@ Do you want to contribute? Please read our [contributing guidelines](https://git
Translation Status 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)

144
module_auto_update/README.rst

@ -0,0 +1,144 @@
==================
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/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| |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
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
=============
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 <https://github.com/OCA/server-tools/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 <https://github.com/OCA/server-tools/issues/new?body=module:%20module_auto_update%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* LasLabs
* Juan José Scarafía
* Tecnativa
* ACSONE SA/NV
Contributors
~~~~~~~~~~~~
* Brent Hughes <brent.hughes@laslabs.com>
* Juan José Scarafía <jjs@adhoc.com.ar>
* Jairo Llopis <jairo.llopis@tecnativa.com>
* Stéphane Bidoul <stephane.bidoul@acsone.eu> (https://acsone.eu)
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
.. |maintainer-sbidoul| image:: https://github.com/sbidoul.png?size=40px
:target: https://github.com/sbidoul
:alt: sbidoul
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-sbidoul|
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/11.0/module_auto_update>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

4
module_auto_update/__init__.py

@ -0,0 +1,4 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from . import models
from .hooks import uninstall_hook

23
module_auto_update/__manifest__.py

@ -0,0 +1,23 @@
# 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': '12.0.2.0.4',
'category': 'Extra Tools',
'website': 'https://github.com/OCA/server-tools',
'author': 'LasLabs, '
'Juan José Scarafía, '
'Tecnativa, '
'ACSONE SA/NV, '
'Odoo Community Association (OCA)',
'license': 'LGPL-3',
'installable': True,
'uninstall_hook': 'uninstall_hook',
'depends': [
'base',
],
'development_status': 'Production/Stable',
'maintainers': ['sbidoul'],
}

44
module_auto_update/addon_hash.py

@ -0,0 +1,44 @@
# 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()

11
module_auto_update/hooks.py

@ -0,0 +1,11 @@
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from odoo import SUPERUSER_ID, api
from .models.module import PARAM_INSTALLED_CHECKSUMS
def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
env["ir.config_parameter"].set_param(PARAM_INSTALLED_CHECKSUMS, False)

46
module_auto_update/i18n/ca.po

@ -0,0 +1,46 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 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"
"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.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 ""

59
module_auto_update/i18n/cs_CZ.po

@ -0,0 +1,59 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# Lukáš Spurný <lukasspurny8@gmail.com>, 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ý <lukasspurny8@gmail.com>, 2018\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"
"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.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ů"
#~ msgid "Modules"
#~ msgstr "Moduly"
#~ 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"

47
module_auto_update/i18n/de.po

@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# Niki Waibel <niki.waibel@gmail.com>, 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 <niki.waibel@gmail.com>, 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"
"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.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"

56
module_auto_update/i18n/es.po

@ -0,0 +1,56 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 2018
# enjolras <yo@miguelrevilla.com>, 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: enjolras <yo@miguelrevilla.com>, 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"
"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.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 ""
#~ msgid "Modules"
#~ msgstr "Módulos"
#~ msgid "Scheduled Upgrades"
#~ msgstr "Actualizaciones programadas"
#~ msgid "Updates"
#~ msgstr "Actualizaciones"

47
module_auto_update/i18n/es_MX.po

@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 2017\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"
"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.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 ""

58
module_auto_update/i18n/fr.po

@ -0,0 +1,58 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# Nicolas JEUDY <njeudy@panda-chi.io>, 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 <njeudy@panda-chi.io>, 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"
"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.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"
#~ msgid "Modules"
#~ msgstr "Modules"
#~ 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"

47
module_auto_update/i18n/hr.po

@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# Bole <bole@dajmi5.com>, 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 <bole@dajmi5.com>, 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"
"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.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 ""

46
module_auto_update/i18n/it.po

@ -0,0 +1,46 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 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"
"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.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 ""

42
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 ""

47
module_auto_update/i18n/nl_NL.po

@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# Peter Hageman <hageman.p@gmail.com>, 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 <hageman.p@gmail.com>, 2017\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"
"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.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 ""

47
module_auto_update/i18n/pt_BR.po

@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 2017\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"
"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.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 ""

47
module_auto_update/i18n/sl.po

@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 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"
"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.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 ""

46
module_auto_update/i18n/tr.po

@ -0,0 +1,46 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * module_auto_update
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 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"
"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.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 ""

3
module_auto_update/models/__init__.py

@ -0,0 +1,3 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from . import module

174
module_auto_update/models/module.py

@ -0,0 +1,174 @@
# 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 odoo import api, exceptions, models, tools
from odoo.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 FailedUpgradeError(exceptions.UserError):
pass
class IncompleteUpgradeError(exceptions.UserError):
pass
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",
(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'
@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
# 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()
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.")

9
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.

4
module_auto_update/readme/CONTRIBUTORS.rst

@ -0,0 +1,4 @@
* Brent Hughes <brent.hughes@laslabs.com>
* Juan José Scarafía <jjs@adhoc.com.ar>
* Jairo Llopis <jairo.llopis@tecnativa.com>
* Stéphane Bidoul <stephane.bidoul@acsone.eu> (https://acsone.eu)

4
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.

18
module_auto_update/readme/USAGE.rst

@ -0,0 +1,18 @@
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:
.. code-block:: python
env['ir.module.module'].upgrade_changed_checksum()

483
module_auto_update/static/description/index.html

@ -0,0 +1,483 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>Module Auto Update</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="module-auto-update">
<h1 class="title">Module Auto Update</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/server-tools/tree/11.0/module_auto_update"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/server-tools-11-0/server-tools-11-0-module_auto_update"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/149/11.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>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.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="id2">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id3">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id8">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#id1">Configuration</a></h1>
<p>This module supports the following system parameters:</p>
<ul class="simple">
<li><tt class="docutils literal">module_auto_update.exclude_patterns</tt>: comma-separated list of file
name patterns to ignore when computing addon checksums. Defaults to
<tt class="docutils literal"><span class="pre">*.pyc,*.pyo,i18n/*.pot,i18n_extra/*.pot,static/*</span></tt>.
Filename patterns must be compatible with the python <tt class="docutils literal">fnmatch</tt> function.</li>
</ul>
<p>In addition to the above pattern, .po files corresponding to languages that
are not installed in the Odoo database are ignored when computing checksums.</p>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id2">Usage</a></h1>
<p>The main method provided by this module is <tt class="docutils literal">upgrade_changed_checksum</tt>
on <tt class="docutils literal">ir.module.module</tt>. 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.</p>
<p>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 <tt class="docutils literal">_save_installed_checksums</tt> can be invoked in a situation
where one is sure all modules on disk are installed and up-to-date in the
database.</p>
<p>An easy way to invoke this upgrade mechanism is by issuing the following
in an Odoo shell session:</p>
<pre class="literal-block">
env['ir.module.module'].upgrade_changed_checksum()
</pre>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
<ul>
<li><p class="first">Since version <tt class="docutils literal">2.0.0</tt>, some features have been deprecated.
When you upgrade from previous versions, these features will be kept for
backwards compatibility, but beware! They are buggy!</p>
<p>If you install this addon from scratch, these features are disabled by
default.</p>
<p>To force enabling or disabling the deprecated features, set a configuration
parameter called <tt class="docutils literal">module_auto_update.enable_deprecated</tt> to either <tt class="docutils literal">1</tt>
or <tt class="docutils literal">0</tt>. It is recommended that you disable them.</p>
<p>Keep in mind that from this version, all upgrades are assumed to run in a
separate odoo instance, dedicated exclusively to upgrade Odoo.</p>
</li>
<li><p class="first">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 <tt class="docutils literal">_deprecated</tt>.</p>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20module_auto_update%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id5">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id6">Authors</a></h2>
<ul class="simple">
<li>LasLabs</li>
<li>Juan José Scarafía</li>
<li>Tecnativa</li>
<li>ACSONE SA/NV</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id7">Contributors</a></h2>
<ul class="simple">
<li>Brent Hughes &lt;<a class="reference external" href="mailto:brent.hughes&#64;laslabs.com">brent.hughes&#64;laslabs.com</a>&gt;</li>
<li>Juan José Scarafía &lt;<a class="reference external" href="mailto:jjs&#64;adhoc.com.ar">jjs&#64;adhoc.com.ar</a>&gt;</li>
<li>Jairo Llopis &lt;<a class="reference external" href="mailto:jairo.llopis&#64;tecnativa.com">jairo.llopis&#64;tecnativa.com</a>&gt;</li>
<li>Stéphane Bidoul &lt;<a class="reference external" href="mailto:stephane.bidoul&#64;acsone.eu">stephane.bidoul&#64;acsone.eu</a>&gt; (<a class="reference external" href="https://acsone.eu">https://acsone.eu</a>)</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id8">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/sbidoul"><img alt="sbidoul" src="https://github.com/sbidoul.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/11.0/module_auto_update">OCA/server-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

4
module_auto_update/tests/__init__.py

@ -0,0 +1,4 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from . import test_addon_hash
from . import test_module

1
module_auto_update/tests/sample_module/README.rst

@ -0,0 +1 @@
Test data for addon_hash module.

1
module_auto_update/tests/sample_module/data/f1.xml

@ -0,0 +1 @@
<odoo/>

1
module_auto_update/tests/sample_module/data/f2.xml

@ -0,0 +1 @@
<odoo/>

1
module_auto_update/tests/sample_module/i18n/en.po

@ -0,0 +1 @@
en text

1
module_auto_update/tests/sample_module/i18n/en_US.po

@ -0,0 +1 @@
en_US

1
module_auto_update/tests/sample_module/i18n/fr.po

@ -0,0 +1 @@
fr

1
module_auto_update/tests/sample_module/i18n/fr_BE.po

@ -0,0 +1 @@
fr_BE

1
module_auto_update/tests/sample_module/i18n/test.pot

@ -0,0 +1 @@
...

1
module_auto_update/tests/sample_module/i18n_extra/en.po

@ -0,0 +1 @@
en

1
module_auto_update/tests/sample_module/i18n_extra/fr.po

@ -0,0 +1 @@
fr

1
module_auto_update/tests/sample_module/i18n_extra/nl_NL.po

@ -0,0 +1 @@
nl_NL

1
module_auto_update/tests/sample_module/models/stuff.py

@ -0,0 +1 @@
1+1

BIN
module_auto_update/tests/sample_module/models/stuff.pyc

BIN
module_auto_update/tests/sample_module/models/stuff.pyo

1
module_auto_update/tests/sample_module/static/src/some.js

@ -0,0 +1 @@
/* Javascript */

67
module_auto_update/tests/test_addon_hash.py

@ -0,0 +1,67 @@
# 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=["*/__pycache__/*"],
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',
'models/stuff.pyo',
'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')

237
module_auto_update/tests/test_module.py

@ -0,0 +1,237 @@
# 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
import odoo
from odoo.modules import get_module_path
from odoo.tests 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())
@odoo.tests.tagged('post_install', '-at_install')
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_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']
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')

1
setup/module_auto_update/odoo/addons/module_auto_update

@ -0,0 +1 @@
../../../../module_auto_update

6
setup/module_auto_update/setup.py

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
Loading…
Cancel
Save