19.0 vanilla

This commit is contained in:
Ernad Husremovic 2025-10-03 18:07:25 +02:00
parent 0a7ae8db93
commit 991d2234ca
416 changed files with 646602 additions and 300844 deletions

View file

@ -1,21 +1,29 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
""" Modules migration handling. """
from __future__ import annotations
import glob
import importlib.util
import inspect
import itertools
import logging
import os
import re
import typing
from collections import defaultdict
from os.path import join as opj
import odoo.release as release
import odoo.upgrade
from odoo.tools.parse_version import parse_version
from odoo.modules.module import load_script
from odoo.orm.registry import Registry
from odoo.tools.misc import file_path
from odoo.tools.parse_version import parse_version
if typing.TYPE_CHECKING:
from collections.abc import Iterator
from odoo.sql_db import Cursor
from . import module_graph
_logger = logging.getLogger(__name__)
@ -47,15 +55,7 @@ VERSION_RE = re.compile(
)
def load_script(path, module_name):
full_path = file_path(path) if not os.path.isabs(path) else path
spec = importlib.util.spec_from_file_location(module_name, full_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
class MigrationManager(object):
class MigrationManager:
""" Manages the migration of modules.
Migrations files must be python files containing a ``migrate(cr, installed_version)``
@ -86,21 +86,22 @@ class MigrationManager(object):
| `-- end-invariants.py # processed on all version update
`-- foo.py # not processed
"""
migrations: defaultdict[str, dict]
def __init__(self, cr, graph):
def __init__(self, cr: Cursor, graph: module_graph.ModuleGraph):
self.cr = cr
self.graph = graph
self.migrations = defaultdict(dict)
self._get_files()
def _get_files(self):
def _get_upgrade_path(pkg):
def _get_files(self) -> None:
def _get_upgrade_path(pkg: str) -> Iterator[str]:
for path in odoo.upgrade.__path__:
upgrade_path = opj(path, pkg)
if os.path.exists(upgrade_path):
yield upgrade_path
def _verify_upgrade_version(path, version):
def _verify_upgrade_version(path: str, version: str) -> bool:
full_path = opj(path, version)
if not os.path.isdir(full_path):
return False
@ -114,7 +115,7 @@ class MigrationManager(object):
return True
def get_scripts(path):
def get_scripts(path: str) -> dict[str, list[str]]:
if not path:
return {}
return {
@ -123,15 +124,14 @@ class MigrationManager(object):
if _verify_upgrade_version(path, version)
}
def check_path(path):
def check_path(path: str) -> str:
try:
return file_path(path)
except FileNotFoundError:
return False
return ''
for pkg in self.graph:
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade' or
getattr(pkg, 'load_state', None) == 'to upgrade'):
if pkg.load_state != 'to upgrade' and pkg.name not in Registry(self.cr.dbname)._force_upgrade_scripts:
continue
@ -146,26 +146,24 @@ class MigrationManager(object):
scripts[v].extend(s)
self.migrations[pkg.name]["upgrade"] = scripts
def migrate_module(self, pkg, stage):
def migrate_module(self, pkg: module_graph.ModuleNode, stage: typing.Literal['pre', 'post', 'end']) -> None:
assert stage in ('pre', 'post', 'end')
stageformat = {
'pre': '[>%s]',
'post': '[%s>]',
'end': '[$%s]',
}
state = pkg.state if stage in ('pre', 'post') else getattr(pkg, 'load_state', None)
if not (hasattr(pkg, 'update') or state == 'to upgrade') or state == 'to install':
if pkg.load_state != 'to upgrade' and pkg.name not in Registry(self.cr.dbname)._force_upgrade_scripts:
return
def convert_version(version):
def convert_version(version: str) -> str:
if version == "0.0.0":
return version
if version.count(".") > 2:
return version # the version number already contains the server version, see VERSION_RE for details
return "%s.%s" % (release.major_version, version)
def _get_migration_versions(pkg, stage):
def _get_migration_versions(pkg, stage: str) -> list[str]:
versions = sorted({
ver
for lv in self.migrations[pkg.name].values()
@ -196,11 +194,11 @@ class MigrationManager(object):
key=os.path.basename,
)
installed_version = getattr(pkg, 'load_version', pkg.installed_version) or ''
installed_version = pkg.load_version or ''
parsed_installed_version = parse_version(installed_version)
current_version = parse_version(convert_version(pkg.data['version']))
current_version = parse_version(convert_version(pkg.manifest['version']))
def compare(version):
def compare(version: str) -> bool:
if version == "0.0.0" and parsed_installed_version < current_version:
return True