Skip to content

Commit

Permalink
[FIX] spec_driven_model: register_hook when no ctx
Browse files Browse the repository at this point in the history
  • Loading branch information
rvalyi committed Oct 15, 2024
1 parent 3cd56a9 commit 74e90d5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 28 deletions.
50 changes: 35 additions & 15 deletions spec_driven_model/models/spec_mixin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright 2019-TODAY Akretion - Raphael Valyi <raphael.valyi@akretion.com>
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html).

from importlib import import_module

from odoo import api, models

from .spec_models import SPEC_MIXIN_MAPPINGS, SpecModel, StackedModel
Expand Down Expand Up @@ -43,12 +45,32 @@ def _get_concrete_model(self, model_name):
else:
return self.env.get(model_name)

def _spec_prefix(self):
def _spec_prefix(self, split=False):
"""
_spec_prefix should be available for all generated specs mixins
and it should be defined in SpecModel to avoid circular imports.
_spec_prefix should be available for all generated specs mixins.
It is inferred from the context or from the module of the class.
"""
return SpecModel._ensure_spec_prefix(self._context)
if self._context.get("spec_schema") and self._context.get("spec_version"):
spec_schema = self._context.get("spec_schema")
spec_version = self._context.get("spec_version")
if spec_schema and spec_version:
spec_version = spec_version.replace(".", "")[:2]
if split:
return spec_schema, spec_version
return f"{spec_schema}{spec_version}"

for ancestor in type(self).mro():
if not ancestor.__module__.startswith("odoo.addons."):
continue
mod = import_module(".".join(ancestor.__module__.split(".")[:-1]))
if hasattr(mod, "spec_schema"):
spec_schema = mod.spec_schema
spec_version = mod.spec_version.replace(".", "")[:2]
if split:
return spec_schema, spec_version
return f"{spec_schema}{spec_version}"

return None, None if split else None

def _get_spec_property(self, spec_property="", fallback=None):
"""
Expand All @@ -67,22 +89,21 @@ def _register_hook(self):
their _auto_init method that will create their SQL DDL structure.
"""
res = super()._register_hook()
if "spec_schema" not in self._context:
spec_schema, spec_version = self._spec_prefix(split=True)
if not spec_schema:
return res

spec_module = self._get_spec_property("odoo_module")
if not spec_module:
return res
odoo_module = spec_module.split("_spec.")[0].split(".")[-1]
load_key = f"_{spec_module}_loaded"
if hasattr(self.env.registry, load_key): # already done for registry
if hasattr(self.env.registry, load_key): # hook already done for registry
return res
setattr(self.env.registry, load_key, True)

access_data = []
access_fields = []
relation_prefix = (
f"{self._context['spec_schema']}.{self._context['spec_version']}.%"
)
field_prefix = f"{self._context['spec_schema']}{self._context['spec_version']}_"
field_prefix = f"{spec_schema}{spec_version}"
relation_prefix = f"{spec_schema}.{spec_version}.%"
self.env.cr.execute(
"""SELECT DISTINCT relation FROM ir_model_fields
WHERE relation LIKE %s;""",
Expand All @@ -99,7 +120,6 @@ def _register_hook(self):
spec_class = StackedModel._odoo_name_to_class(name, spec_module)
if spec_class is None:
continue
spec_class._module = "fiscal" # TODO use python_module ?
fields = self.env[spec_class._name].fields_get_keys()
rec_name = next(
filter(
Expand All @@ -120,8 +140,8 @@ def _register_hook(self):
)
# we set _spec_schema and _spec_version because
# _build_model will not have context access:
model_type._spec_schema = self._context["spec_schema"]
model_type._spec_version = self._context["spec_version"]
model_type._spec_schema = spec_schema
model_type._spec_version = spec_version
models.MetaModel.module_to_models[odoo_module] += [model_type]

# now we init these models properly
Expand Down
16 changes: 3 additions & 13 deletions spec_driven_model/models/spec_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,9 @@ def _compute_display_name(self):
res = super()._compute_display_name()
for rec in self:
if rec.display_name == "False" or not rec.display_name:
rec.display_name = _("Abrir...")
rec.display_name = _("Open...")
return res

@classmethod
def _ensure_spec_prefix(cls, context=None, spec_schema=None, spec_version=None):
if context and context.get("spec_schema"):
spec_schema = context.get("spec_schema")
if context and context.get("spec_version"):
spec_version = context.get("spec_version")
return "%s%s" % (spec_schema, spec_version.replace(".", "")[:2])

@classmethod
def _build_model(cls, pool, cr):
"""
Expand Down Expand Up @@ -180,7 +172,6 @@ def _setup_fields(self):

@classmethod
def _map_concrete(cls, dbname, key, target, quiet=False):
# TODO bookkeep according to a key to allow multiple injection contexts
if not quiet:
_logger.debug(f"{key} ---> {target}")
global SPEC_MIXIN_MAPPINGS
Expand Down Expand Up @@ -232,15 +223,14 @@ class StackedModel(SpecModel):

@classmethod
def _build_model(cls, pool, cr):
mod = import_module(".".join(cls.__module__.split(".")[:-1]))
if hasattr(cls, "_spec_schema"):
if hasattr(cls, "_spec_schema"): # when called via _register_hook
schema = cls._spec_schema
version = cls._spec_version.replace(".", "")[:2]
else:
mod = import_module(".".join(cls.__module__.split(".")[:-1]))
schema = mod.spec_schema
version = mod.spec_version.replace(".", "")[:2]
spec_prefix = cls._ensure_spec_prefix(spec_schema=schema, spec_version=version)
spec_prefix = f"{schema}{version}"
setattr(cls, f"_{spec_prefix}_stacking_points", {})
stacking_settings = {
"odoo_module": getattr(cls, f"_{spec_prefix}_odoo_module"), # TODO inherit?
Expand Down

0 comments on commit 74e90d5

Please sign in to comment.