Skip to content
Snippets Groups Projects
Commit 15a6567eb80f authored by Vincent Hatakeyama's avatar Vincent Hatakeyama
Browse files

:sparkles: Added Writeonly converter.

:shirt: Add some typing information, or make it consistent.
:books: Add more docstrings.
:ambulance: Fix using Skip in switch converter.
parent 16ef4c946a87
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !58. Comments created here will be created in the context of that merge request.
Changelog
=========
18.0.3.1.0
----------
Added Writeonly converter.
Add some typing information, or make it consistent.
Add more docstrings.
Fix using Skip in switch converter.
18.0.3.0.0
----------
......
......@@ -34,6 +34,8 @@
NewinstanceType,
Readonly,
Skip,
SkipType,
Writeonly,
message_to_odoo,
build_context,
)
......
......@@ -21,7 +21,7 @@
"name": "Converter",
"license": "AGPL-3",
"summary": "Convert odoo records to/from plain data structures.",
"version": "18.0.3.0.0",
"version": "18.0.3.1.0",
"category": "Hidden",
"author": "XCG Consulting",
"website": "https://orbeet.io/",
......
##############################################################################
#
# Converter Odoo module
# Copyright © 2020 XCG Consulting <https://xcg-consulting.fr>
# Copyright © 2020, 2025 XCG Consulting <https://xcg-consulting.fr>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
......@@ -189,7 +189,7 @@
class Readonly(Converter):
def __init__(self, conv):
def __init__(self, conv: Converter):
super().__init__()
self.conv = conv
......@@ -197,6 +197,35 @@
return self.conv.odoo_to_message(instance, ctx)
class Writeonly(Converter):
"""A converter that only convert to odoo but does nothing from odoo."""
def __init__(self, conv: Converter):
super().__init__()
self._conv = conv
def message_to_odoo(
self,
odoo_env: api.Environment,
phase: str,
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
) -> dict | SkipType:
return self._conv.message_to_odoo(
odoo_env, phase, message_value, instance, value_present
)
@property
def is_instance_getter(self) -> bool:
return self._conv.is_instance_getter
def get_instance(
self, odoo_env: api.Environment, message_data
) -> models.BaseModel | NewinstanceType | None:
return self._conv.get_instance(odoo_env, message_data)
class Computed(Converter):
def __init__(self, from_odoo: Callable[[models.BaseModel, Context], Any]):
self.from_odoo = from_odoo
......@@ -216,7 +245,9 @@
class Constant(Converter):
def __init__(self, value):
self.value = value
"""When building messages, this converter return a constant value."""
def __init__(self, value: Any):
self._value = value
def odoo_to_message(self, instance: models.BaseModel, ctx: Context = None) -> Any:
......@@ -221,6 +252,6 @@
def odoo_to_message(self, instance: models.BaseModel, ctx: Context = None) -> Any:
return self.value
return self._value
def message_to_odoo(
......
......@@ -25,7 +25,7 @@
import pytz
from odoo import api, models # type: ignore[import-untyped]
from .base import PHASE_POSTCREATE, Context, Converter, Newinstance, Skip
from .base import PHASE_POSTCREATE, Context, Converter, Newinstance, Skip, SkipType
class Field(Converter):
......@@ -122,7 +122,7 @@
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
) -> dict:
) -> dict | SkipType:
if phase == PHASE_POSTCREATE:
return {}
if not value_present:
......@@ -187,7 +187,7 @@
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
) -> dict:
) -> dict | SkipType:
message = super().message_to_odoo(
odoo_env, phase, message_value, instance, value_present
)
......@@ -191,7 +191,7 @@
message = super().message_to_odoo(
odoo_env, phase, message_value, instance, value_present
)
if self.field_name in message:
if not isinstance(message, SkipType) and self.field_name in message:
self._lazy_dicts(instance)
message[self.field_name] = self._lazy_dict_message_to_odoo.get(
message[self.field_name]
......
......@@ -20,5 +20,5 @@
from typing import Any
from odoo import models # type: ignore[import-untyped]
from odoo import api, models # type: ignore[import-untyped]
......@@ -24,5 +24,5 @@
from .base import Context, ContextBuilder, Converter, Skip, build_context
from .base import Context, ContextBuilder, Converter, Skip, SkipType, build_context
class List(Converter):
......@@ -51,5 +51,5 @@
def message_to_odoo(
self,
odoo_env,
odoo_env: api.Environment,
phase: str,
......@@ -55,4 +55,4 @@
phase: str,
message_value,
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
......@@ -57,4 +57,11 @@
instance: models.BaseModel,
value_present: bool = True,
) -> dict:
return {}
) -> dict | SkipType:
result = {}
for i, converter in enumerate(self._converters):
new_values = converter.message_to_odoo(
odoo_env, phase, message_value[i], instance, value_present
)
if not isinstance(new_values, SkipType):
result.update(new_values)
return result
......@@ -28,7 +28,7 @@
class MailTemplate(Converter):
"""This converter wraps ``mail.template::_render_template``.
Multiple records are allowed but ``mail.template::_render_template`` still
runs once per record; to accomodate, we provide ``ctx["records"]``.
runs once per record; to accommodate, we provide ``ctx["records"]``.
Using this converter requires the mail module to be installed.
"""
......
......@@ -30,6 +30,7 @@
NewinstanceType,
Skip,
build_context,
SkipType
)
from .field import Field
......@@ -69,7 +70,7 @@
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
) -> dict:
) -> dict | SkipType:
if not value_present:
return {}
......@@ -129,7 +130,7 @@
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
) -> dict:
) -> dict | SkipType:
# if not present or value is None, do not update the values.
if not value_present or message_value is None:
return {}
......@@ -196,7 +197,7 @@
message_value: Any,
instance: models.BaseModel,
value_present: bool = True,
) -> dict:
) -> dict | SkipType:
# if not present or value is None, do not update the values.
if not value_present or message_value is None:
return {}
......
......@@ -39,8 +39,8 @@
AURION_REFERENTIAL: Switch(
[
(
lambda e: e.is_xxx,
lambda p: "wave_code" in p,
lambda record: record.is_xxx,
lambda message_value: "wave_code" in message_value,
Model("__wave__", {}),
),
(None, None, Model("__event__", {})),
......@@ -53,8 +53,8 @@
converters: list[
tuple[
Callable[[models.BaseModel], bool] | None,
Callable[[Any], bool],
Converter,
Callable[[Any], bool] | None,
Converter | SkipType,
]
],
validator: Validator | None = None,
......@@ -92,7 +92,9 @@
value_present: bool = True,
) -> dict | SkipType:
for _out_cond, in_cond, converter in self._converters:
if in_cond is None or in_cond(message_value):
if not isinstance(converter, SkipType) and (
in_cond is None or in_cond(message_value)
):
return converter.message_to_odoo(
odoo_env,
phase,
......@@ -106,7 +108,7 @@
@property
def is_instance_getter(self) -> bool:
for _out_cond, _in_cond, converter in self._converters:
if converter.is_instance_getter:
if not isinstance(converter, SkipType) and converter.is_instance_getter:
return True
return False
......@@ -115,8 +117,10 @@
self, odoo_env: api.Environment, message_data
) -> models.BaseModel | NewinstanceType | None:
for _out_cond, in_cond, converter in self._converters:
if converter.is_instance_getter and (
in_cond is None or in_cond(message_data)
if (
not isinstance(converter, SkipType)
and converter.is_instance_getter
and (in_cond is None or in_cond(message_data))
):
return converter.get_instance(odoo_env, message_data)
return super().get_instance(odoo_env, message_data)
......@@ -125,9 +129,10 @@
# also set validator on any converters in our switch, in case they care
super()._set_validator(value)
for _out_cond, _in_cond, converter in self._converters:
converter.validator = value
if not isinstance(converter, SkipType):
converter.validator = value
def _set_validation(self, value: str) -> None:
# also set validation on any converters in our switch
super()._set_validation(value)
for _out_cond, _in_cond, converter in self._converters:
......@@ -129,10 +134,11 @@
def _set_validation(self, value: str) -> None:
# also set validation on any converters in our switch
super()._set_validation(value)
for _out_cond, _in_cond, converter in self._converters:
converter.validation = value
if not isinstance(converter, SkipType):
converter.validation = value
def get__type__(self) -> set[str]:
types = set()
for _out_cond, _in_cond, converter in self._converters:
......@@ -135,6 +141,7 @@
def get__type__(self) -> set[str]:
types = set()
for _out_cond, _in_cond, converter in self._converters:
types.update(converter.get__type__())
if not isinstance(converter, SkipType):
types.update(converter.get__type__())
return types
......@@ -20,7 +20,7 @@
from typing import Any
from odoo import models # type: ignore[import-untyped]
from odoo import api, models # type: ignore[import-untyped]
from .base import Context, NewinstanceType, PostHookConverter
from .models.ir_model_data import _XREF_IMD_MODULE
......@@ -47,8 +47,8 @@
)
def get_instance(
self, odoo_env, message_data
) -> None | models.BaseModel | NewinstanceType:
self, odoo_env: api.Environment, message_data
) -> models.BaseModel | NewinstanceType | None:
if self._is_instance_getter:
return odoo_env.ref(
".".join(["" if self._module is None else self._module, message_data]),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment