diff --git a/server_environment/__manifest__.py b/server_environment/__manifest__.py
index b6872be..ef036da 100644
--- a/server_environment/__manifest__.py
+++ b/server_environment/__manifest__.py
@@ -5,18 +5,12 @@
{
"name": "server configuration environment files",
"version": "13.0.2.0.0",
- "depends": [
- "base",
- "base_sparse_field",
- ],
+ "depends": ["base", "base_sparse_field"],
"author": "Camptocamp,Odoo Community Association (OCA)",
"summary": "move some configurations out of the database",
"website": "http://github.com/OCA/server-env",
"license": "GPL-3 or any later version",
"category": "Tools",
- "data": [
- 'security/res_groups.xml',
- 'serv_config.xml',
- ],
- 'installable': True,
+ "data": ["security/res_groups.xml", "serv_config.xml"],
+ "installable": True,
}
diff --git a/server_environment/models/server_env_mixin.py b/server_environment/models/server_env_mixin.py
index 0227bfa..81868c5 100644
--- a/server_environment/models/server_env_mixin.py
+++ b/server_environment/models/server_env_mixin.py
@@ -2,12 +2,12 @@
# License GPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
-
from functools import partialmethod
from lxml import etree
from odoo import api, fields, models
+
from ..server_env import serv_config
_logger = logging.getLogger(__name__)
@@ -96,19 +96,20 @@ class ServerEnvMixin(models.AbstractModel):
``keychain.backend``.
"""
- _name = 'server.env.mixin'
- _description = 'Mixin to add server environment in existing models'
+
+ _name = "server.env.mixin"
+ _description = "Mixin to add server environment in existing models"
server_env_defaults = fields.Serialized()
_server_env_getter_mapping = {
- 'integer': 'getint',
- 'float': 'getfloat',
- 'monetary': 'getfloat',
- 'boolean': 'getboolean',
- 'char': 'get',
- 'selection': 'get',
- 'text': 'get',
+ "integer": "getint",
+ "float": "getfloat",
+ "monetary": "getfloat",
+ "boolean": "getboolean",
+ "char": "get",
+ "selection": "get",
+ "text": "get",
}
@property
@@ -180,16 +181,13 @@ class ServerEnvMixin(models.AbstractModel):
# _server_env_has_key_defined so we are sure that the value is
# either in the global or the record config
getter = getattr(serv_config, config_getter)
- if (section_name in serv_config
- and field_name in serv_config[section_name]):
+ if section_name in serv_config and field_name in serv_config[section_name]:
value = getter(section_name, field_name)
else:
value = getter(global_section_name, field_name)
except Exception:
_logger.exception(
- "error trying to read field %s in section %s",
- field_name,
- section_name,
+ "error trying to read field %s in section %s", field_name, section_name
)
return False
return value
@@ -203,34 +201,31 @@ class ServerEnvMixin(models.AbstractModel):
and field_name in serv_config[global_section_name]
)
has_config = (
- section_name in serv_config
- and field_name in serv_config[section_name]
+ section_name in serv_config and field_name in serv_config[section_name]
)
return has_global_config or has_config
def _compute_server_env_from_config(self, field_name, options):
- getter_name = options.get('getter') if options else None
+ getter_name = options.get("getter") if options else None
if not getter_name:
field_type = self._fields[field_name].type
getter_name = self._server_env_getter_mapping.get(field_type)
if not getter_name:
# if you get this message and the field is working as expected,
# you may want to add the type in _server_env_getter_mapping
- _logger.warning('server.env.mixin is used on a field of type %s, '
- 'which may not be supported properly')
- getter_name = 'get'
- value = self._server_env_read_from_config(
- field_name, getter_name
- )
+ _logger.warning(
+ "server.env.mixin is used on a field of type %s, "
+ "which may not be supported properly"
+ )
+ getter_name = "get"
+ value = self._server_env_read_from_config(field_name, getter_name)
self[field_name] = value
def _compute_server_env_from_default(self, field_name, options):
- if options and options.get('compute_default'):
- getattr(self, options['compute_default'])()
+ if options and options.get("compute_default"):
+ getattr(self, options["compute_default"])()
else:
- default_field = self._server_env_default_fieldname(
- field_name
- )
+ default_field = self._server_env_default_fieldname(field_name)
if default_field:
self[field_name] = self[default_field]
else:
@@ -248,9 +243,7 @@ class ServerEnvMixin(models.AbstractModel):
record._compute_server_env_from_config(field_name, options)
else:
- record._compute_server_env_from_default(
- field_name, options
- )
+ record._compute_server_env_from_default(field_name, options)
def _inverse_server_env(self, field_name):
options = self._server_env_fields[field_name]
@@ -262,8 +255,8 @@ class ServerEnvMixin(models.AbstractModel):
# we update the default value in database
if record[is_editable_field]:
- if options and options.get('inverse_default'):
- getattr(record, options['inverse_default'])()
+ if options and options.get("inverse_default"):
+ getattr(record, options["inverse_default"])()
elif default_field:
record[default_field] = record[field_name]
@@ -278,12 +271,8 @@ class ServerEnvMixin(models.AbstractModel):
# in ``_inverse_server_env`` it would reset the value of the field
for record in self:
for field_name in self._server_env_fields:
- is_editable_field = self._server_env_is_editable_fieldname(
- field_name
- )
- is_editable = not record._server_env_has_key_defined(
- field_name
- )
+ is_editable_field = self._server_env_is_editable_fieldname(field_name)
+ is_editable = not record._server_env_has_key_defined(field_name)
record[is_editable_field] = is_editable
def _server_env_view_set_readonly(self, view_arch):
@@ -293,37 +282,32 @@ class ServerEnvMixin(models.AbstractModel):
for elem in view_arch.findall(field_xpath % field):
# set env-computed fields to readonly if the configuration
# files have a key set for this field
- elem.set('attrs',
- str({'readonly': [(is_editable_field, '=', False)]}))
+ elem.set("attrs", str({"readonly": [(is_editable_field, "=", False)]}))
if not view_arch.findall(field_xpath % is_editable_field):
# add the _is_editable fields in the view for the 'attrs'
# domain
view_arch.append(
- etree.Element(
- 'field',
- name=is_editable_field,
- invisible="1"
- )
+ etree.Element("field", name=is_editable_field, invisible="1")
)
return view_arch
- def _fields_view_get(self, view_id=None, view_type='form', toolbar=False,
- submenu=False):
+ def _fields_view_get(
+ self, view_id=None, view_type="form", toolbar=False, submenu=False
+ ):
view_data = super()._fields_view_get(
- view_id=view_id, view_type=view_type,
- toolbar=toolbar, submenu=submenu
+ view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
)
- view_arch = etree.fromstring(view_data['arch'].encode('utf-8'))
+ view_arch = etree.fromstring(view_data["arch"].encode("utf-8"))
view_arch = self._server_env_view_set_readonly(view_arch)
- view_data['arch'] = etree.tostring(view_arch, encoding='unicode')
+ view_data["arch"] = etree.tostring(view_arch, encoding="unicode")
return view_data
def _server_env_default_fieldname(self, base_field_name):
"""Return the name of the field with default value"""
options = self._server_env_fields[base_field_name]
- if options and options.get('no_default_field'):
- return ''
- return '%s_env_default' % (base_field_name,)
+ if options and options.get("no_default_field"):
+ return ""
+ return "{}_env_default".format(base_field_name)
def _server_env_is_editable_fieldname(self, base_field_name):
"""Return the name of the field for "is editable"
@@ -331,16 +315,14 @@ class ServerEnvMixin(models.AbstractModel):
This is the field used to tell if the env-computed field can
be edited.
"""
- return '%s_env_is_editable' % (base_field_name,)
+ return "{}_env_is_editable".format(base_field_name)
def _server_env_transform_field_to_read_from_env(self, field):
"""Transform the original field in a computed field"""
- field.compute = '_compute_server_env'
+ field.compute = "_compute_server_env"
- inverse_method_name = '_inverse_server_env_%s' % field.name
- inverse_method = partialmethod(
- type(self)._inverse_server_env, field.name
- )
+ inverse_method_name = "_inverse_server_env_%s" % field.name
+ inverse_method = partialmethod(type(self)._inverse_server_env, field.name)
setattr(type(self), inverse_method_name, inverse_method)
field.inverse = inverse_method_name
field.store = False
@@ -360,7 +342,7 @@ class ServerEnvMixin(models.AbstractModel):
# (inherits), we want to override it with a new one
if fieldname not in self._fields or self._fields[fieldname].inherited:
field = fields.Boolean(
- compute='_compute_server_env_is_editable',
+ compute="_compute_server_env_is_editable",
automatic=True,
# this is required to be able to edit fields
# on new records
@@ -385,14 +367,11 @@ class ServerEnvMixin(models.AbstractModel):
if fieldname not in self._fields or self._fields[fieldname].inherited:
base_field_cls = base_field.__class__
field_args = base_field.args.copy()
- field_args.pop('_sequence', None)
- field_args.update({
- 'sparse': 'server_env_defaults',
- 'automatic': True,
- })
+ field_args.pop("_sequence", None)
+ field_args.update({"sparse": "server_env_defaults", "automatic": True})
- if hasattr(base_field, 'selection'):
- field_args['selection'] = base_field.selection
+ if hasattr(base_field, "selection"):
+ field_args["selection"] = base_field.selection
field = base_field_cls(**field_args)
self._add_field(fieldname, field)
diff --git a/server_environment/server_env.py b/server_environment/server_env.py
index a18bd22..06106c3 100644
--- a/server_environment/server_env.py
+++ b/server_environment/server_env.py
@@ -18,13 +18,14 @@
#
##############################################################################
+import configparser
import logging
import os
-import configparser
-from lxml import etree
from itertools import chain
-from odoo import api, models, fields
+from lxml import etree
+
+from odoo import api, fields, models
from odoo.tools.config import config as system_base_config
from .system_info import get_server_environment
@@ -33,19 +34,29 @@ _logger = logging.getLogger(__name__)
try:
from odoo.addons import server_environment_files
+
_dir = os.path.dirname(server_environment_files.__file__)
except ImportError:
- _logger.info('not using server_environment_files for configuration,'
- ' no directory found')
+ _logger.info(
+ "not using server_environment_files for configuration," " no directory found"
+ )
_dir = None
-ENV_VAR_NAMES = ('SERVER_ENV_CONFIG', 'SERVER_ENV_CONFIG_SECRET')
+ENV_VAR_NAMES = ("SERVER_ENV_CONFIG", "SERVER_ENV_CONFIG_SECRET")
# Same dict as RawConfigParser._boolean_states
-_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
- '0': False, 'no': False, 'false': False, 'off': False}
+_boolean_states = {
+ "1": True,
+ "yes": True,
+ "true": True,
+ "on": True,
+ "0": False,
+ "no": False,
+ "false": False,
+ "off": False,
+}
-if not system_base_config.get('running_env', False):
+if not system_base_config.get("running_env", False):
raise Exception(
"The parameter 'running_env' has not be set neither in base config "
"file option -c or in openerprc.\n"
@@ -56,7 +67,7 @@ if not system_base_config.get('running_env', False):
ck_path = None
if _dir:
- ck_path = os.path.join(_dir, system_base_config['running_env'])
+ ck_path = os.path.join(_dir, system_base_config["running_env"])
if not os.path.exists(ck_path):
raise Exception(
@@ -77,25 +88,29 @@ def setboolean(obj, attr, _bool=None):
# Borrowed from MarkupSafe
def _escape(s):
"""Convert the characters &<>'" in string s to HTML-safe sequences."""
- return (str(s).replace('&', '&')
- .replace('>', '>')
- .replace('<', '<')
- .replace("'", ''')
- .replace('"', '"'))
+ return (
+ str(s)
+ .replace("&", "&")
+ .replace(">", ">")
+ .replace("<", "<")
+ .replace("'", "'")
+ .replace('"', """)
+ )
def _listconf(env_path):
"""List configuration files in a folder."""
- files = [os.path.join(env_path, name)
- for name in sorted(os.listdir(env_path))
- if name.endswith('.conf')]
+ files = [
+ os.path.join(env_path, name)
+ for name in sorted(os.listdir(env_path))
+ if name.endswith(".conf")
+ ]
return files
def _load_config_from_server_env_files(config_p):
- default = os.path.join(_dir, 'default')
- running_env = os.path.join(_dir,
- system_base_config['running_env'])
+ default = os.path.join(_dir, "default")
+ running_env = os.path.join(_dir, system_base_config["running_env"])
if os.path.isdir(default):
conf_files = _listconf(default) + _listconf(running_env)
else:
@@ -104,12 +119,12 @@ def _load_config_from_server_env_files(config_p):
try:
config_p.read(conf_files)
except Exception as e:
- raise Exception('Cannot read config files "%s": %s' % (conf_files, e))
+ raise Exception('Cannot read config files "{}": {}'.format(conf_files, e))
def _load_config_from_rcfile(config_p):
config_p.read(system_base_config.rcfile)
- config_p.remove_section('options')
+ config_p.remove_section("options")
def _load_config_from_env(config_p):
@@ -120,8 +135,7 @@ def _load_config_from_env(config_p):
config_p.read_string(env_config)
except configparser.Error as err:
raise Exception(
- '%s content could not be parsed: %s'
- % (varname, err,)
+ "{} content could not be parsed: {}".format(varname, err)
)
@@ -147,13 +161,15 @@ class _Defaults(dict):
def __setitem__(self, key, value):
def func(*a):
return str(value)
+
return dict.__setitem__(self, key, func)
class ServerConfiguration(models.TransientModel):
"""Display server configuration."""
- _name = 'server.config'
- _description = 'Display server configuration'
+
+ _name = "server.config"
+ _description = "Display server configuration"
_conf_defaults = _Defaults()
@classmethod
@@ -164,20 +180,20 @@ class ServerConfiguration(models.TransientModel):
"""
ModelClass = super(ServerConfiguration, cls)._build_model(pool, cr)
ModelClass._add_columns()
- ModelClass.running_env = system_base_config['running_env']
+ ModelClass.running_env = system_base_config["running_env"]
# Only show passwords in development
- ModelClass.show_passwords = ModelClass.running_env in ('dev',)
+ ModelClass.show_passwords = ModelClass.running_env in ("dev",)
ModelClass._arch = None
ModelClass._build_osv()
return ModelClass
@classmethod
def _format_key(cls, section, key):
- return '%s_I_%s' % (section, key)
+ return "{}_I_{}".format(section, key)
@classmethod
def _format_key_display_name(cls, key_name):
- return key_name.replace('_I_', ' | ')
+ return key_name.replace("_I_", " | ")
@classmethod
def _add_columns(cls):
@@ -185,16 +201,17 @@ class ServerConfiguration(models.TransientModel):
cols = chain(
list(cls._get_base_cols().items()),
list(cls._get_env_cols().items()),
- list(cls._get_system_cols().items())
+ list(cls._get_system_cols().items()),
)
for col, value in cols:
- col_name = col.replace('.', '_')
- setattr(ServerConfiguration,
- col_name,
- fields.Char(
- string=cls._format_key_display_name(col_name),
- readonly=True)
- )
+ col_name = col.replace(".", "_")
+ setattr(
+ ServerConfiguration,
+ col_name,
+ fields.Char(
+ string=cls._format_key_display_name(col_name), readonly=True
+ ),
+ )
cls._conf_defaults[col_name] = value
@classmethod
@@ -202,7 +219,7 @@ class ServerConfiguration(models.TransientModel):
""" Compute base fields"""
res = {}
for col, item in list(system_base_config.options.items()):
- key = cls._format_key('odoo', col)
+ key = cls._format_key("odoo", col)
res[key] = item
return res
@@ -222,7 +239,7 @@ class ServerConfiguration(models.TransientModel):
""" Compute system fields"""
res = {}
for col, item in get_server_environment():
- key = cls._format_key('system', col)
+ key = cls._format_key("system", col)
res[key] = item
return res
@@ -232,17 +249,19 @@ class ServerConfiguration(models.TransientModel):
names = []
for key in sorted(items):
- names.append(key.replace('.', '_'))
- return ('