From ed4058ed442b9fbdd259c03e42a4021235becab0 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 15 Jul 2020 14:13:14 +0200 Subject: [PATCH] Add mixin for tech name --- server_environment/models/__init__.py | 1 + server_environment/models/server_env_mixin.py | 10 ++- .../models/server_env_tech_name_mixin.py | 72 +++++++++++++++++++ server_environment/readme/CONFIGURE.rst | 12 +++- server_environment/readme/CONTRIBUTORS.rst | 1 + server_environment/readme/ROADMAP.rst | 2 + server_environment/readme/USAGE.rst | 9 +++ 7 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 server_environment/models/server_env_tech_name_mixin.py diff --git a/server_environment/models/__init__.py b/server_environment/models/__init__.py index 6bd869a..d139a0a 100644 --- a/server_environment/models/__init__.py +++ b/server_environment/models/__init__.py @@ -1 +1,2 @@ from . import server_env_mixin +from . import server_env_tech_name_mixin diff --git a/server_environment/models/server_env_mixin.py b/server_environment/models/server_env_mixin.py index 06a71d3..a57f662 100644 --- a/server_environment/models/server_env_mixin.py +++ b/server_environment/models/server_env_mixin.py @@ -165,14 +165,22 @@ class ServerEnvMixin(models.AbstractModel): """ return self._name.replace(".", "_") + _server_env_section_name_field = "name" + def _server_env_section_name(self): """Name of the section in the configuration files Can be customized in your model """ self.ensure_one() + val = self[self._server_env_section_name_field] + if not val: + # special case: we have onchanges relying on tech_name + # and we are testing them using `tests.common.Form`. + # when the for is initialized there's no value yet. + return base = self._server_env_global_section_name() - return ".".join((base, self.name)) + return ".".join((base, val)) def _server_env_read_from_config(self, field_name, config_getter): self.ensure_one() diff --git a/server_environment/models/server_env_tech_name_mixin.py b/server_environment/models/server_env_tech_name_mixin.py new file mode 100644 index 0000000..fcf676c --- /dev/null +++ b/server_environment/models/server_env_tech_name_mixin.py @@ -0,0 +1,72 @@ +# Copyright 2020 Camptocamp (http://www.camptocamp.com) +# @author Simone Orsi +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + +from odoo.addons.http_routing.models.ir_http import slugify + + +class ServerEnvTechNameMixin(models.AbstractModel): + """Provides a tech_name field to be used in server env vars as unique key. + + The `name` field can be error prone because users can easily change it + to something more meaningful for them or set weird chars into it + that make difficult to reference the record in env var config. + This mixin helps solve the problem by providing a tech name field + and a cleanup machinery as well as a unique constrain. + + To use this mixin add it to the _inherit attr of your module like: + + _inherit = [ + "my.model", + "server.env.techname.mixin", + "server.env.mixin", + ] + + """ + + _name = "server.env.techname.mixin" + _description = "Server environment technical name" + _sql_constraints = [ + ("tech_name_uniq", "unique(tech_name)", "`tech_name` must be unique!",) + ] + # TODO: could leverage the new option for computable / writable fields + # and get rid of some onchange / read / write code. + tech_name = fields.Char( + required=True, + help="Unique name for technical purposes. " "Eg: server env keys.", + ) + + _server_env_section_name_field = "tech_name" + + @api.onchange("name") + def _onchange_name_for_tech(self): + # Keep this specific name for the method to avoid possible overrides + # of existing `_onchange_name` methods + if self.name and not self.tech_name: + self.tech_name = self.name + + @api.onchange("tech_name") + def _onchange_tech_name(self): + if self.tech_name: + # make sure is normalized + self.tech_name = self._normalize_tech_name(self.tech_name) + + @api.model + def create(self, vals): + self._handle_tech_name(vals) + return super().create(vals) + + def write(self, vals): + self._handle_tech_name(vals) + return super().write(vals) + + def _handle_tech_name(self, vals): + # make sure technical names are always there + if not vals.get("tech_name") and vals.get("name"): + vals["tech_name"] = self._normalize_tech_name(vals["name"]) + + @staticmethod + def _normalize_tech_name(name): + return slugify(name).replace("-", "_") diff --git a/server_environment/readme/CONFIGURE.rst b/server_environment/readme/CONFIGURE.rst index 6610f44..84b9ff9 100644 --- a/server_environment/readme/CONFIGURE.rst +++ b/server_environment/readme/CONFIGURE.rst @@ -53,7 +53,7 @@ A public file, containing that will contain public variables:: # server environment options export SERVER_ENV_CONFIG=" - [storage_backend.my-sftp] + [storage_backend.my_sftp] sftp_server=10.10.10.10 sftp_login=foo sftp_port=22200 @@ -67,10 +67,18 @@ A second file which is encrypted and contains secrets:: export DB_PASSWORD='xxxxxxxxx' # server environment options export SERVER_ENV_CONFIG_SECRET=" - [storage_backend.my-sftp] + [storage_backend.my_sftp] sftp_password=xxxxxxxxx " +**WARNING** + + `my_sftp` must match the name of the record. + If you want something more reliable use `server.env.techname.mixin` + and use `tech_name` field to reference records. + See "USAGE". + + Default values ~~~~~~~~~~~~~~ diff --git a/server_environment/readme/CONTRIBUTORS.rst b/server_environment/readme/CONTRIBUTORS.rst index 4d64e67..cb37929 100644 --- a/server_environment/readme/CONTRIBUTORS.rst +++ b/server_environment/readme/CONTRIBUTORS.rst @@ -9,3 +9,4 @@ * Guewen Baconnier * Thomas Binfeld * Stéphane Bidoul +* Simone Orsi diff --git a/server_environment/readme/ROADMAP.rst b/server_environment/readme/ROADMAP.rst index 4c8096a..58107c9 100644 --- a/server_environment/readme/ROADMAP.rst +++ b/server_environment/readme/ROADMAP.rst @@ -1,3 +1,5 @@ * it is not possible to set the environment from the command line. A configuration file must be used. * the module does not allow to set low level attributes such as database server, etc. +* `server.env.techname.mixin`'s `tech_name` field could leverage the new option + for computable / writable fields and get rid of some onchange / read / write code. diff --git a/server_environment/readme/USAGE.rst b/server_environment/readme/USAGE.rst index 6c8f221..d12b21d 100644 --- a/server_environment/readme/USAGE.rst +++ b/server_environment/readme/USAGE.rst @@ -13,3 +13,12 @@ by an override of ``_server_env_fields``. Read the documentation of the class and methods in `models/server_env_mixin.py `__. + + +If you want to have a technical name to reference:: + + class StorageBackend(models.Model): + _name = "storage.backend" + _inherit = ["storage.backend", "server.env.techname.mixin", "server.env.mixin"] + + [...]