19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:30:27 +01:00
parent d1963a3c3a
commit 2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions

View file

@ -17,6 +17,7 @@ import odoo.sql_db
import odoo.tools.sql
import odoo.tools.translate
from odoo import api, tools
from odoo.tools import OrderedSet
from odoo.tools.convert import convert_file, IdRef, ConvertMode as LoadMode
from . import db as modules_db
@ -69,7 +70,7 @@ def load_demo(env: Environment, package: ModuleNode, idref: IdRef, mode: LoadMod
if package.manifest.get('demo') or package.manifest.get('demo_xml'):
_logger.info("Module %s: loading demo", package.name)
with env.cr.savepoint(flush=False):
load_data(env(su=True), idref, mode, kind='demo', package=package)
load_data(env(su=True, context=dict(env.context, install_demo=True)), idref, mode, kind='demo', package=package)
return True
except Exception: # noqa: BLE001
# If we could not install demo data for this module
@ -89,6 +90,7 @@ def force_demo(env: Environment) -> None:
"""
Forces the `demo` flag on all modules, and installs demo data for all installed modules.
"""
assert env.registry.ready
env.cr.execute('UPDATE ir_module_module SET demo=True')
env.cr.execute(
"SELECT name FROM ir_module_module WHERE state IN ('installed', 'to upgrade', 'to remove')"
@ -102,13 +104,20 @@ def force_demo(env: Environment) -> None:
env['ir.module.module'].invalidate_model(['demo'])
# If demo data triggered module state changes (to install/upgrade/remove),
# commit and rebuild registry to process button_install/upgrade calls.
if env['ir.module.module'].search_count([('state', 'in', ('to install', 'to upgrade', 'to remove'))], limit=1):
env.cr.commit()
Registry.new(env.cr.dbname, update_module=True)
env.transaction.reset()
def load_module_graph(
env: Environment,
graph: ModuleGraph,
update_module: bool = False,
report: OdooTestResult | None = None,
models_to_check: set[str] | None = None,
models_to_check: OrderedSet[str] | None = None,
install_demo: bool = True,
) -> None:
""" Load, upgrade and install not loaded module nodes in the ``graph`` for ``env.registry``
@ -121,7 +130,7 @@ def load_module_graph(
:param install_demo: whether to attempt installing demo data for newly installed modules
"""
if models_to_check is None:
models_to_check = set()
models_to_check = OrderedSet()
registry = env.registry
assert isinstance(env.cr, odoo.sql_db.Cursor), "Need for a real Cursor to load modules"
@ -179,8 +188,8 @@ def load_module_graph(
if update_operation:
model_names = registry.descendants(model_names, '_inherit', '_inherits')
models_updated |= set(model_names)
models_to_check -= set(model_names)
models_updated |= model_names
models_to_check -= model_names
registry._setup_models__(env.cr, []) # incremental setup
registry.init_models(env.cr, model_names, {'module': package.name}, update_operation == 'install')
elif update_module and package.state != 'to remove':
@ -190,7 +199,11 @@ def load_module_graph(
# e.g. adding required=True to an existing field, but the schema has not been
# updated by this module because it's not marked as 'to upgrade/to install'.
model_names = registry.descendants(model_names, '_inherit', '_inherits')
models_to_check |= set(model_names) & models_updated
models_to_check |= model_names & models_updated
elif update_module and package.state == 'to remove':
# For all model extented (with _inherit) in the package to uninstall, we need to
# update ir.model / ir.model.fields along side not-null SQL constrains.
models_to_check |= model_names
if update_operation:
# Can't put this line out of the loop: ir.module.module will be
@ -332,6 +345,7 @@ def load_modules(
install_modules: Collection[str] = (),
reinit_modules: Collection[str] = (),
new_db_demo: bool = False,
models_to_check: OrderedSet[str] | None = None,
) -> None:
""" Load the modules for a registry object that has just been created. This
function is part of Registry.new() and should not be used anywhere else.
@ -343,9 +357,10 @@ def load_modules(
:param reinit_modules: A collection of module names to reinitialize.
:param new_db_demo: Whether to install demo data for new database. Defaults to ``False``
"""
initialize_sys_path()
if models_to_check is None:
models_to_check = OrderedSet()
models_to_check: set[str] = set()
initialize_sys_path()
with registry.cursor() as cr:
# prevent endless wait for locks on schema changes (during online
@ -536,11 +551,8 @@ def load_modules(
cr.commit()
_logger.info('Reloading registry once more after uninstalling modules')
registry = Registry.new(
cr.dbname, update_module=update_module
cr.dbname, update_module=update_module, models_to_check=models_to_check,
)
cr.reset()
registry.check_tables_exist(cr)
cr.commit()
return
# STEP 5.5: Verify extended fields on every model
@ -555,7 +567,9 @@ def load_modules(
cr.execute("""SELECT DISTINCT model FROM ir_model_fields WHERE state = 'manual'""")
models_to_check.update(model_name for model_name, in cr.fetchall() if model_name in registry)
if models_to_check:
registry.init_models(cr, list(models_to_check), {'models_to_check': True, 'update_custom_fields': True})
# Doesn't check models that didn't exist anymore, it might happen during uninstallation
models_to_check = [model for model in models_to_check if model in registry]
registry.init_models(cr, models_to_check, {'models_to_check': True, 'update_custom_fields': True})
# STEP 6: verify custom views on every model
if update_module:
@ -583,6 +597,16 @@ def load_modules(
# STEP 10: check that we can trust nullable columns
registry.check_null_constraints(cr)
if update_module:
cr.execute(
"""
INSERT INTO ir_config_parameter(key, value)
SELECT 'base.partially_updated_database', '1'
WHERE EXISTS(SELECT FROM ir_module_module WHERE state IN ('to upgrade', 'to install', 'to remove'))
ON CONFLICT DO NOTHING
"""
)
def reset_modules_state(db_name: str) -> None:
"""
@ -596,8 +620,7 @@ def reset_modules_state(db_name: str) -> None:
# of time
db = odoo.sql_db.db_connect(db_name)
with db.cursor() as cr:
cr.execute("SELECT 1 FROM information_schema.tables WHERE table_name='ir_module_module'")
if not cr.fetchall():
if not odoo.tools.sql.table_exists(cr, 'ir_module_module'):
_logger.info('skipping reset_modules_state, ir_module_module table does not exists')
return
cr.execute(