[FIX] module.py: --upgrades-paths dynamic hooks
Migration have long been only accessible thanks to a symlink from
`odoo.base.maintenance` to our private migration repository. Thank to
the change of bbb1a8f it is now possible to give a load the
migrations scripts from a path given in options.
The `initialize_sys_path` function has been updated to hooks the new
paths or the legacy symlink and to provide aliases to the previous
import logic to ensure backward compatibility.
`odoo.upgrades` (`community/odoo/upgrades`) is a new namespace that hook
all `--upgrades-paths` directories or the
`community/odoo/base/maintenance/migrations` symlink if none is previded.
`odoo.addons.base.maintenance.migrations` has been made an alias to
`odoo.upgrades`.
The `odoo.upgrades` is the desired method for accessing migrations
scripts and should be used by all new scripts.
closes odoo/odoo#44117
Task: 2178274
X-original-commit: d963cc05acd882729c4eb5ab940dae2a2197e55a
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -106,6 +106,7 @@ def registry(database_name=None):
|
||||
#----------------------------------------------------------
|
||||
# Imports
|
||||
#----------------------------------------------------------
|
||||
from . import upgrades # this namespace must be imported first
|
||||
from . import addons
|
||||
from . import conf
|
||||
from . import loglevels
|
||||
|
||||
@@ -12,7 +12,7 @@ from os.path import join as opj
|
||||
|
||||
from odoo.modules.module import get_resource_path
|
||||
import odoo.release as release
|
||||
import odoo.tools as tools
|
||||
import odoo.upgrades
|
||||
from odoo.tools.parse_version import parse_version
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -63,7 +63,7 @@ class MigrationManager(object):
|
||||
|
||||
def _get_files(self):
|
||||
def _get_upgrades_paths(pkg):
|
||||
for path in tools.config['upgrades_paths'].split(','):
|
||||
for path in odoo.upgrades.__path__:
|
||||
upgrade_path = opj(path, pkg)
|
||||
if os.path.exists(upgrade_path):
|
||||
return upgrade_path
|
||||
@@ -86,8 +86,6 @@ class MigrationManager(object):
|
||||
self.migrations[pkg.name] = {
|
||||
'module': get_scripts(get_resource_path(pkg.name, 'migrations')),
|
||||
'module_upgrades': get_scripts(get_resource_path(pkg.name, 'upgrades')),
|
||||
'maintenance': get_scripts(get_resource_path('base', 'maintenance', 'migrations', pkg.name)),
|
||||
'maintenance_upgrades': get_scripts(get_resource_path('base', 'maintenance', 'upgrades', pkg.name)),
|
||||
'upgrades': get_scripts(_get_upgrades_paths(pkg.name)),
|
||||
}
|
||||
|
||||
@@ -133,11 +131,9 @@ class MigrationManager(object):
|
||||
mapping = {
|
||||
'module': opj(pkg.name, 'migrations'),
|
||||
'module_upgrades': opj(pkg.name, 'upgrades'),
|
||||
'maintenance': opj('base', 'maintenance', 'migrations', pkg.name),
|
||||
'maintenance_upgrades': opj('base', 'maintenance', 'upgrades', pkg.name),
|
||||
}
|
||||
|
||||
for path in tools.config['upgrades_paths'].split(','):
|
||||
for path in odoo.upgrades.__path__:
|
||||
if os.path.exists(opj(path, pkg.name)):
|
||||
mapping['upgrades'] = opj(path, pkg.name)
|
||||
break
|
||||
|
||||
+22
-1
@@ -39,20 +39,41 @@ def initialize_sys_path():
|
||||
and explicit directories.
|
||||
"""
|
||||
|
||||
# hook odoo.addons on data dir
|
||||
dd = os.path.normcase(tools.config.addons_data_dir)
|
||||
if os.access(dd, os.R_OK) and dd not in odoo.addons.__path__:
|
||||
odoo.addons.__path__.append(dd)
|
||||
|
||||
# hook odoo.addons on addons paths
|
||||
for ad in tools.config['addons_path'].split(','):
|
||||
ad = os.path.normcase(os.path.abspath(tools.ustr(ad.strip())))
|
||||
if ad not in odoo.addons.__path__:
|
||||
odoo.addons.__path__.append(ad)
|
||||
|
||||
# add base module path
|
||||
# hook odoo.addons on base module path
|
||||
base_path = os.path.normcase(os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons')))
|
||||
if base_path not in odoo.addons.__path__ and os.path.isdir(base_path):
|
||||
odoo.addons.__path__.append(base_path)
|
||||
|
||||
# hook odoo.upgrades on upgrades paths
|
||||
from odoo import upgrades
|
||||
for up in tools.config['upgrades_paths'].split(','):
|
||||
up = os.path.normcase(os.path.abspath(tools.ustr(up.strip())))
|
||||
if up not in upgrades.__path__:
|
||||
upgrades.__path__.append(up)
|
||||
|
||||
# hook odoo.upgrades on legacy odoo/addons/base/maintenance/migrations symlink
|
||||
if not tools.config['upgrades_paths']:
|
||||
upgrades.__path__.append(os.path.join(
|
||||
base_path, 'base', 'maintenance', 'migrations'))
|
||||
|
||||
# create decrecated module alias from odoo.addons.base.maintenance.migrations to odoo.upgrades
|
||||
spec = importlib.machinery.ModuleSpec("odoo.addons.base.maintenance", None, is_package=True)
|
||||
maintenance_pkg = importlib.util.module_from_spec(spec)
|
||||
maintenance_pkg.migrations = upgrades
|
||||
sys.modules["odoo.addons.base.maintenance"] = maintenance_pkg
|
||||
sys.modules["odoo.addons.base.maintenance.migrations"] = upgrades
|
||||
|
||||
def get_module_path(module, downloaded=False, display_warning=True):
|
||||
"""Return the path of the given module.
|
||||
|
||||
|
||||
+16
-7
@@ -9,10 +9,12 @@ except ImportError:
|
||||
import errno
|
||||
import logging
|
||||
import optparse
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import odoo
|
||||
from os.path import expandvars, expanduser, abspath, realpath
|
||||
from .. import release, conf, loglevels
|
||||
from . import appdirs
|
||||
|
||||
@@ -488,7 +490,7 @@ class configmanager(object):
|
||||
self._normalize(x)
|
||||
for x in self.options['addons_path'].split(','))
|
||||
|
||||
self.options['upgrades_paths'] = (
|
||||
self.options["upgrades_paths"] = (
|
||||
",".join(self._normalize(x)
|
||||
for x in self.options['upgrades_paths'].split(','))
|
||||
if self.options['upgrades_paths']
|
||||
@@ -546,7 +548,7 @@ class configmanager(object):
|
||||
if not os.path.isdir(res):
|
||||
raise optparse.OptionValueError("option %s: no such directory: %r" % (opt, path))
|
||||
if not self._is_addons_path(res):
|
||||
raise optparse.OptionValueError("option %s: The addons-path %r does not seem to a be a valid Addons Directory!" % (opt, path))
|
||||
raise optparse.OptionValueError("option %s: the path %r is not a valid addons directory" % (opt, path))
|
||||
ad_paths.append(res)
|
||||
|
||||
setattr(parser.values, option.dest, ",".join(ad_paths))
|
||||
@@ -558,9 +560,18 @@ class configmanager(object):
|
||||
res = self._normalize(path)
|
||||
if not os.path.isdir(res):
|
||||
raise optparse.OptionValueError("option %s: no such directory: %r" % (opt, path))
|
||||
upgrades_paths.append(res)
|
||||
if not self._is_upgrades_path(res):
|
||||
raise optparse.OptionValueError("option %s: the path %r is not a valid upgrade directory" % (opt, path))
|
||||
if res not in upgrades_paths:
|
||||
upgrades_paths.append(res)
|
||||
setattr(parser.values, option.dest, ",".join(upgrades_paths))
|
||||
|
||||
def _is_upgrades_path(self, res):
|
||||
return any(
|
||||
glob.glob(os.path.join(res, f"*/*/{prefix}-*.py"))
|
||||
for prefix in ["pre", "post", "end"]
|
||||
)
|
||||
|
||||
def _test_enable_callback(self, option, opt, value, parser):
|
||||
if not parser.values.test_tags:
|
||||
parser.values.test_tags = "+standard"
|
||||
@@ -700,9 +711,7 @@ class configmanager(object):
|
||||
def _normalize(self, path):
|
||||
if not path:
|
||||
return path
|
||||
return os.path.abspath(
|
||||
os.path.expanduser(
|
||||
os.path.expandvars(
|
||||
path.strip())))
|
||||
return realpath(abspath(expanduser(expandvars(path.strip()))))
|
||||
|
||||
|
||||
config = configmanager()
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
|
||||
from odoo.tools import config
|
||||
from odoo.modules.module import get_resource_path
|
||||
|
||||
for path in config.get("upgrades_paths", "").split(","):
|
||||
if os.path.exists(os.path.join(path, "__init__.py")):
|
||||
break
|
||||
else:
|
||||
# failback to legacy "maintenance/migrations" package
|
||||
path = get_resource_path("base", "maintenance", "migrations")
|
||||
|
||||
if not path:
|
||||
raise ImportError("No package found in `upgrades_paths`")
|
||||
|
||||
spec = importlib.util.spec_from_file_location("odoo.upgrades", os.path.join(path, "__init__.py"))
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
# shadow module and register under legacy name
|
||||
sys.modules["odoo.upgrades"] = sys.modules["odoo.addons.base.maintenance.migrations"] = module
|
||||
@@ -0,0 +1,6 @@
|
||||
import pkgutil
|
||||
import os.path
|
||||
__path__ = [
|
||||
os.path.abspath(path)
|
||||
for path in pkgutil.extend_path(__path__, __name__)
|
||||
]
|
||||
Reference in New Issue
Block a user