# HG changeset patch
# User Vincent Hatakeyama <vincent.hatakeyama@xcg-consulting.fr>
# Date 1741872023 -3600
#      Thu Mar 13 14:20:23 2025 +0100
# Branch 17.0
# Node ID 8e41e562a5166a650b9379ce798d07c9ca6bb685
# Parent  e90fb6234da32b937a5225686d36a63300b691be
👕 mypy, pylint

diff --git a/base.py b/base.py
--- a/base.py
+++ b/base.py
@@ -102,7 +102,7 @@
 
 
 class NotAnInstanceGetterException(Exception):
-    def __init__(self):
+    def __init__(self) -> None:
         super().__init__("Not an instance getter")
 
 
@@ -111,8 +111,9 @@
     It does not actually convert anything.
     """
 
-    def __init__(self):
+    def __init__(self) -> None:
         self._validation: Validation = Validation.SKIP
+        self._validator: None | Validator = None
 
     def odoo_to_message(self, instance: models.BaseModel, ctx: Context = None) -> Any:
         """From an instance, this method returns a matching value for the
@@ -217,7 +218,7 @@
 
 
 class Readonly(Converter):
-    def __init__(self, conv: Converter):
+    def __init__(self, conv: Converter) -> None:
         super().__init__()
         self._conv = conv
 
@@ -231,7 +232,7 @@
 class Writeonly(Converter):
     """A converter that only convert to odoo but does nothing from odoo."""
 
-    def __init__(self, conv: Converter):
+    def __init__(self, conv: Converter) -> None:
         super().__init__()
         self._conv = conv
 
@@ -262,7 +263,8 @@
 
 
 class Computed(Converter):
-    def __init__(self, from_odoo: Callable[[models.BaseModel, Context], Any]):
+    def __init__(self, from_odoo: Callable[[models.BaseModel, Context], Any]) -> None:
+        super().__init__()
         self.from_odoo = from_odoo
 
         sig = inspect.signature(from_odoo)
@@ -282,7 +284,8 @@
 class Constant(Converter):
     """When building messages, this converter return a constant value."""
 
-    def __init__(self, value: Any):
+    def __init__(self, value: Any) -> None:
+        super().__init__()
         self._value = value
 
     def odoo_to_message(self, instance: models.BaseModel, ctx: Context = None) -> Any:
diff --git a/keyfield.py b/keyfield.py
--- a/keyfield.py
+++ b/keyfield.py
@@ -35,6 +35,7 @@
     """
 
     def __init__(self, field_name: str, model_name: str, limit_lookup: bool = False):
+        super().__init__()
         self.field_name = field_name
         self.model_name = model_name
         self.lookup_limit = 1 if limit_lookup else None
diff --git a/mail_template.py b/mail_template.py
--- a/mail_template.py
+++ b/mail_template.py
@@ -34,16 +34,17 @@
     """
 
     def __init__(self, template: str, post_eval: bool = False):
+        super().__init__()
         self.template = template
         self.post_eval = post_eval
 
-    def odoo_to_message(self, records: models.BaseModel, ctx: Context = None) -> Any:
+    def odoo_to_message(self, instance: models.BaseModel, ctx: Context = None) -> Any:
         value = (
-            records.env["mail.template"]
-            .with_context(records=records, safe=True)
-            ._render_template(self.template, records._name, records.ids)
+            instance.env["mail.template"]
+            .with_context(records=instance, safe=True)
+            ._render_template(self.template, instance._name, instance.ids)
         )
-        value = value[records[0].id]  # _render_template outputs indexed by record ID
+        value = value[instance[0].id]  # _render_template outputs indexed by record ID
         if self.post_eval:
             value = ast.literal_eval(value)
         return value
diff --git a/relation.py b/relation.py
--- a/relation.py
+++ b/relation.py
@@ -59,8 +59,7 @@
         if not relation_instance:
             if not self._send_empty:
                 return Skip
-            else:
-                relation_instance = instance.env[self.model_name]
+            relation_instance = instance.env[self.model_name]
         return self.converter.odoo_to_message(relation_instance, ctx)
 
     def message_to_odoo(
@@ -224,7 +223,7 @@
         pi = name.find("(")
         if pi != -1:
             if not name.endswith(")"):
-                raise ValueError("Invalid path: %s", name)
+                raise ValueError(f"Invalid path: {name}")
             model_name = name[pi + 1 : -1]  # noqa: E203
             name = name[:pi]
         if name.endswith("[]"):
@@ -277,26 +276,24 @@
                 return None
 
         return rel_record
-    else:
-        field_value = (
-            getattr(instance, self.field_name)
-            if instance and not isinstance(instance, NewinstanceType)
-            else None
-        )
+    field_value = (
+        getattr(instance, self.field_name)
+        if instance and not isinstance(instance, NewinstanceType)
+        else None
+    )
 
-        updates = self.converter.message_to_odoo(
-            odoo_env, phase, message_value, field_value, value_present
-        )
+    updates = self.converter.message_to_odoo(
+        odoo_env, phase, message_value, field_value, value_present
+    )
 
-        if updates:
-            if field_value:
-                field_value.write(updates)
-                if post_hook:
-                    post_hook(field_value, message_value)
-                return None
-            else:
-                rel_record = odoo_env[self.model_name].create(updates)
-                if post_hook:
-                    post_hook(rel_record, message_value)
-                return rel_record
-        return None
+    if updates:
+        if field_value:
+            field_value.write(updates)
+            if post_hook:
+                post_hook(field_value, message_value)
+            return None
+        rel_record = odoo_env[self.model_name].create(updates)
+        if post_hook:
+            post_hook(rel_record, message_value)
+        return rel_record
+    return None
diff --git a/switch.py b/switch.py
--- a/switch.py
+++ b/switch.py
@@ -75,7 +75,7 @@
         :param validator:
         :param context:
         """
-        super()
+        super().__init__()
         self._converters = converters
         self.context = context
         self.validator = validator
@@ -86,8 +86,7 @@
             if out_cond is None or out_cond(instance):
                 if isinstance(converter, SkipType):
                     return converter
-                else:
-                    return converter.odoo_to_message(instance, ctx)
+                return converter.odoo_to_message(instance, ctx)
 
         return Skip
 
diff --git a/tests/schemas/__init__.py b/tests/schemas/__init__.py
--- a/tests/schemas/__init__.py
+++ b/tests/schemas/__init__.py
@@ -1,10 +1,10 @@
 import json
 import pkgutil
 from typing import Any
-from collections.abc import Generator
+from collections.abc import Iterator
 
 
-def get_schemas() -> Generator[Any]:
+def get_schemas() -> Iterator[Any]:
     for file_prefix in ("product",):
         data: bytes | None = pkgutil.get_data(__name__, f"{file_prefix}.schema.json")
         if data:
diff --git a/validate.py b/validate.py
--- a/validate.py
+++ b/validate.py
@@ -1,7 +1,7 @@
 ##############################################################################
 #
 #    Converter Odoo module
-#    Copyright © 2020, 2024 XCG Consulting <https://xcg-consulting.fr>
+#    Copyright © 2020, 2024, 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
@@ -25,6 +25,7 @@
 from importlib import import_module
 from typing import Any
 
+from odoo import _  # type: ignore[import-untyped]
 from odoo.exceptions import UserError  # type: ignore[import-untyped]
 
 _fastjsonschema: None | Exception = None
@@ -88,7 +89,7 @@
         else:
             if module.__file__ is None:
                 # XXX maybe not the best type of error
-                raise UserError("Module %s has no file", self.package_name)
+                raise UserError(_("Module %s has no file", self.package_name))
             # Fallback on searching schema json files
             schema_search_path = os.path.dirname(module.__file__)
             schema_search_path = os.path.abspath(