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 Nov 29, 2024
1 parent 0ed46cf commit e0840ca
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 35 deletions.
5 changes: 2 additions & 3 deletions spec_driven_model/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

{
"name": "Spec Driven Model",
"summary": """
Tools for specifications driven mixins (from xsd for instance)""",
"summary": """XML binding for Odoo: XML to Odoo models and models to XML.""",
"version": "15.0.1.3.1",
"maintainers": ["rvalyi"],
"license": "LGPL-3",
"author": "Akretion,Odoo Community Association (OCA)",
"author": "Akretion, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/l10n-brazil",
"depends": [],
"data": [],
Expand Down
58 changes: 39 additions & 19 deletions spec_driven_model/models/spec_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,50 @@ def _get_concrete_model(self, model_name):
else:
return self.env.get(model_name)

def _spec_prefix(self):
"""
_spec_prefix should be available for all generated specs mixins
and it should be defined in SpecModel to avoid circular imports.
"""
return SpecModel._ensure_spec_prefix(self._context)

def _get_spec_property(self, spec_property="", fallback=None):
"""
Used to access schema wise and version wise automatic mappings properties
"""
return getattr(self, f"_{self._spec_prefix()}_{spec_property}", fallback)

def _get_stacking_points(self):
return self._get_spec_property("stacking_points", {})

def _register_hook(self):
"""
Called once all modules are loaded.
Here we take all spec models that are not injected into existing concrete
Here we take all spec models that were not injected into existing concrete
Odoo models and we make them concrete automatically with
their _auto_init method that will create their SQL DDL structure.
"""
res = super()._register_hook()
if not hasattr(self, "_spec_module"):
if "spec_schema" not in self._context:
return res

load_key = "_%s_loaded" % (self._spec_module,)
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
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']}_"
self.env.cr.execute(
"""SELECT DISTINCT relation FROM ir_model_fields
WHERE relation LIKE %s;""",
(f"{self._schema_name}.{self._schema_version.replace('.', '')[:2]}.%",),
(relation_prefix,),
)
# now we will filter only the spec models not injected into some existing class:
remaining_models = {
Expand All @@ -73,17 +96,14 @@ def _register_hook(self):
and not SPEC_MIXIN_MAPPINGS[self.env.cr.dbname].get(i[0])
}
for name in remaining_models:
spec_class = StackedModel._odoo_name_to_class(name, self._spec_module)
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(
lambda x: (
x.startswith(self.env[spec_class._name]._field_prefix)
and "_choice" not in x
),
lambda x: (x.startswith(field_prefix) and "_choice" not in x),
fields,
)
)
Expand All @@ -93,16 +113,16 @@ def _register_hook(self):
{
"_name": name,
"_inherit": spec_class._inherit,
"_original_module": "fiscal",
"_odoo_module": self._odoo_module,
"_spec_module": self._spec_module,
"_original_module": odoo_module,
"_rec_name": rec_name,
"_module": self._odoo_module,
"_module": odoo_module,
},
)
model_type._schema_name = self._schema_name
model_type._schema_version = self._schema_version
models.MetaModel.module_to_models[self._odoo_module] += [model_type]
# 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"]
models.MetaModel.module_to_models[odoo_module] += [model_type]

# now we init these models properly
# a bit like odoo.modules.loading#load_module_graph would do
Expand All @@ -123,11 +143,11 @@ def _register_hook(self):
"perm_create",
"perm_unlink",
]
model._auto_fill_access_data(self.env, self._odoo_module, access_data)
model._auto_fill_access_data(self.env, odoo_module, access_data)

self.env["ir.model.access"].load(access_fields, access_data)
self.env.registry.init_models(
self.env.cr, remaining_models, {"module": self._odoo_module}
self.env.cr, remaining_models, {"module": odoo_module}
)
return res

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,7 +64,7 @@ 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

def _get_stacking_points(self):
Expand All @@ -73,14 +73,6 @@ def _get_stacking_points(self):
return getattr(self, key)["stacking_points"]
return {}

@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 @@ -193,7 +185,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 @@ -245,15 +236,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}"
stacking_settings = getattr(cls, "_%s_spec_settings" % (spec_prefix,))
# inject all stacked m2o as inherited classes
_logger.info(f"building StackedModel {cls._name} {cls}")
Expand Down

0 comments on commit e0840ca

Please sign in to comment.