123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- #!/usr/bin/env python3
- import argparse
- import logging.config
- import os
- import sys
- import time
- sys.path.append(os.path.abspath(os.path.join(__file__,'../../../')))
- import odoo
- from odoo.tools import config, topological_sort, unique
- from odoo.netsvc import init_logger
- from odoo.tests import standalone_tests
- import odoo.tests.loader
- _logger = logging.getLogger('odoo.tests.test_module_operations')
- BLACKLIST = {
- 'auth_ldap', 'document_ftp', 'website_instantclick', 'pad',
- 'pad_project', 'note_pad', 'pos_cache', 'pos_blackbox_be',
- }
- IGNORE = ('hw_', 'theme_', 'l10n_', 'test_')
- INSTALL_BLACKLIST = {
- 'payment_alipay', 'payment_ogone', 'payment_payulatam', 'payment_payumoney',
- } # deprecated modules (cannot be installed manually through button_install anymore)
- def install(db_name, module_id, module_name):
- with odoo.registry(db_name).cursor() as cr:
- env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
- module = env['ir.module.module'].browse(module_id)
- module.button_immediate_install()
- _logger.info('%s installed', module_name)
- def uninstall(db_name, module_id, module_name):
- with odoo.registry(db_name).cursor() as cr:
- env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
- module = env['ir.module.module'].browse(module_id)
- module.button_immediate_uninstall()
- _logger.info('%s uninstalled', module_name)
- def cycle(db_name, module_id, module_name):
- install(db_name, module_id, module_name)
- uninstall(db_name, module_id, module_name)
- install(db_name, module_id, module_name)
- class CheckAddons(argparse.Action):
- def __call__(self, parser, namespace, values, option_string=None):
- self.values = namespace
- config._check_addons_path(self, option_string, values, self)
- def parse_args():
- parser = argparse.ArgumentParser(
- description="Script for testing the install / uninstall / reinstall"
- " cycle of Odoo modules. Prefer the 'cycle' subcommand to"
- " running this without anything specified (this is the"
- " default behaviour).")
- parser.set_defaults(
- func=test_cycle,
- reinstall=True,
- )
- fake_commands = parser.add_mutually_exclusive_group()
- parser.add_argument("--database", "-d", type=str, required=True,
- help="The database to test (/ run the command on)")
- parser.add_argument("--data-dir", "-D", dest="data_dir", type=str,
- help="Directory where to store Odoo data"
- )
- parser.add_argument("--skip", "-s", type=str,
- help="Comma-separated list of modules to skip (they will only be installed)")
- parser.add_argument("--resume-at", "-r", type=str,
- help="Skip modules (only install) up to the specified one in topological order")
- parser.add_argument("--addons-path", "-p", type=str, action=CheckAddons,
- help="Comma-separated list of paths to directories containing extra Odoo modules")
- cmds = parser.add_subparsers(title="subcommands", metavar='')
- cycle = cmds.add_parser(
- 'cycle', help="Full install/uninstall/reinstall cycle.",
- description="Installs, uninstalls, and reinstalls all modules which are"
- " not skipped or blacklisted, the database should have"
- " 'base' installed (only).")
- cycle.set_defaults(func=test_cycle)
- fake_commands.add_argument(
- "--uninstall", "-U", action=UninstallAction,
- help="Comma-separated list of modules to uninstall/reinstall. Prefer the 'uninstall' subcommand."
- )
- uninstall = cmds.add_parser(
- 'uninstall', help="Uninstallation",
- description="Uninstalls then (by default) reinstalls every specified "
- "module. Modules which are not installed before running "
- "are ignored.")
- uninstall.set_defaults(func=test_uninstall)
- uninstall.add_argument('uninstall', help="comma-separated list of modules to uninstall/reinstall")
- uninstall.add_argument(
- '-n', '--no-reinstall', dest='reinstall', action='store_false',
- help="Skips reinstalling the module(s) after uninstalling."
- )
- fake_commands.add_argument("--standalone", action=StandaloneAction,
- help="Launch standalone scripts tagged with @standalone. Accepts a list of "
- "module names or tags separated by commas. 'all' will run all available scripts. Prefer the 'standalone' subcommand."
- )
- standalone = cmds.add_parser('standalone', help="Run scripts tagged with @standalone")
- standalone.set_defaults(func=test_standalone)
- standalone.add_argument('standalone', help="List of module names or tags separated by commas, 'all' will run all available scripts.")
- return parser.parse_args()
- class UninstallAction(argparse.Action):
- def __call__(self, parser, namespace, values, option_string=None):
- namespace.func = test_uninstall
- setattr(namespace, self.dest, values)
- class StandaloneAction(argparse.Action):
- def __call__(self, parser, namespace, values, option_string=None):
- namespace.func = test_standalone
- setattr(namespace, self.dest, values)
- def test_cycle(args):
- """ Test full install/uninstall/reinstall cycle for all modules """
- with odoo.registry(args.database).cursor() as cr:
- env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
- def valid(module):
- return not (
- module.name in BLACKLIST
- or module.name in INSTALL_BLACKLIST
- or module.name.startswith(IGNORE)
- or module.state in ('installed', 'uninstallable')
- )
- modules = env['ir.module.module'].search([]).filtered(valid)
- # order modules in topological order
- modules = modules.browse(topological_sort({
- module.id: module.dependencies_id.depend_id.ids
- for module in modules
- }))
- modules_todo = [(module.id, module.name) for module in modules]
- resume = args.resume_at
- skip = set(args.skip.split(',')) if args.skip else set()
- for module_id, module_name in modules_todo:
- if module_name == resume:
- resume = None
- if resume or module_name in skip:
- install(args.database, module_id, module_name)
- else:
- cycle(args.database, module_id, module_name)
- def test_uninstall(args):
- """ Tries to uninstall/reinstall one ore more modules"""
- for module_name in args.uninstall.split(','):
- with odoo.registry(args.database).cursor() as cr:
- env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
- module = env['ir.module.module'].search([('name', '=', module_name)])
- module_id, module_state = module.id, module.state
- if module_state == 'installed':
- uninstall(args.database, module_id, module_name)
- if args.reinstall and module_name not in INSTALL_BLACKLIST:
- install(args.database, module_id, module_name)
- elif module_state:
- _logger.warning("Module %r is not installed", module_name)
- else:
- _logger.warning("Module %r does not exist", module_name)
- def test_standalone(args):
- """ Tries to launch standalone scripts tagged with @post_testing """
- # load the registry once for script discovery
- registry = odoo.registry(args.database)
- for module_name in registry._init_modules:
- # import tests for loaded modules
- odoo.tests.loader.get_test_modules(module_name)
- # fetch and filter scripts to test
- funcs = list(unique(
- func
- for tag in args.standalone.split(',')
- for func in standalone_tests[tag]
- ))
- start_time = time.time()
- for index, func in enumerate(funcs, start=1):
- with odoo.registry(args.database).cursor() as cr:
- env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
- _logger.info("Executing standalone script: %s (%d / %d)",
- func.__name__, index, len(funcs))
- try:
- func(env)
- except Exception:
- _logger.error("Standalone script %s failed", func.__name__, exc_info=True)
- _logger.info("%d standalone scripts executed in %.2fs" % (len(funcs), time.time() - start_time))
- if __name__ == '__main__':
- args = parse_args()
- # handle paths option
- if args.addons_path:
- odoo.tools.config['addons_path'] = ','.join([args.addons_path, odoo.tools.config['addons_path']])
- if args.data_dir:
- odoo.tools.config['data_dir'] = args.data_dir
- odoo.modules.module.initialize_sys_path()
- init_logger()
- logging.config.dictConfig({
- 'version': 1,
- 'incremental': True,
- 'disable_existing_loggers': False,
- 'loggers': {
- 'odoo.modules.loading': {'level': 'CRITICAL'},
- 'odoo.sql_db': {'level': 'CRITICAL'},
- 'odoo.models.unlink': {'level': 'WARNING'},
- 'odoo.addons.base.models.ir_model': {'level': "WARNING"},
- }
- })
- try:
- args.func(args)
- except Exception:
- _logger.error("%s tests failed", args.func.__name__[5:])
- raise
|