# HG changeset patch # User Vincent Hatakeyama <vincent.hatakeyama@xcg-consulting.fr> # Date 1668010812 -3600 # Wed Nov 09 17:20:12 2022 +0100 # Branch 15.0 # Node ID ddadf40955885b19425e211825cae7d95dd2ac66 # Parent d940cb24f4eeb8df313e5a3366208995f00ff348 ✨ port to Odoo 15 diff --git a/.badges/code_style-black-000000.svg b/.badges/code_style-black-000000.svg new file mode 100644 --- /dev/null +++ b/.badges/code_style-black-000000.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="114" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h72v20H0z" /> + <path fill="#000000" d="M72 0h42v20H72z" /> + <path fill="url(#b)" d="M0 0h114v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="37.0" y="15" fill="#010101" fill-opacity=".3">code style</text> + <text x="36.0" y="14">code style</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="94.0" y="15" fill="#010101" fill-opacity=".3">black</text> + <text x="93.0" y="14">black</text> + </g> +</svg> diff --git a/.badges/code_style-prettier-ff69b4.svg b/.badges/code_style-prettier-ff69b4.svg new file mode 100644 --- /dev/null +++ b/.badges/code_style-prettier-ff69b4.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="129" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="129" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h72v20H0z" /> + <path fill="#ff69b4" d="M72 0h57v20H72z" /> + <path fill="url(#b)" d="M0 0h129v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="37.0" y="15" fill="#010101" fill-opacity=".3">code style</text> + <text x="36.0" y="14">code style</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="101.5" y="15" fill="#010101" fill-opacity=".3">prettier</text> + <text x="100.5" y="14">prettier</text> + </g> +</svg> diff --git a/.badges/licence-AGPL--3-blue.svg b/.badges/licence-AGPL--3-blue.svg new file mode 100644 --- /dev/null +++ b/.badges/licence-AGPL--3-blue.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="107" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="107" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h53v20H0z" /> + <path fill="#0000FF" d="M53 0h54v20H53z" /> + <path fill="url(#b)" d="M0 0h107v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="27.5" y="15" fill="#010101" fill-opacity=".3">licence</text> + <text x="26.5" y="14">licence</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="81.0" y="15" fill="#010101" fill-opacity=".3">AGPL-3</text> + <text x="80.0" y="14">AGPL-3</text> + </g> +</svg> diff --git a/.badges/maturity.svg b/.badges/maturity.svg new file mode 100644 --- /dev/null +++ b/.badges/maturity.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="177" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="177" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h61v20H0z" /> + <path fill="#4c1" d="M61 0h116v20H61z" /> + <path fill="url(#b)" d="M0 0h177v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="31.5" y="15" fill="#010101" fill-opacity=".3">maturity</text> + <text x="30.5" y="14">maturity</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="120.0" y="15" fill="#010101" fill-opacity=".3">Production/Stable</text> + <text x="119.0" y="14">Production/Stable</text> + </g> +</svg> diff --git a/.editorconfig b/.editorconfig new file mode 100644 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# Configuration for known file extensions +[*.{css,htm,html,js,json,jsx,less,markdown,md,py,rst,sass,scss,toml,xml,yaml,yml}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{json,yml,yaml,rst,markdown,md,toml}] +indent_size = 2 + +# Do not configure editor for libs +[*/static/{lib,src/lib}/**] +charset = unset +end_of_line = unset +indent_size = unset +indent_style = unset +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.flake8 b/.flake8 new file mode 100644 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 88 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,3 @@ include: - project: xcg/ci-templates - file: /odoo/13.0/gitlab-ci.yaml + file: /odoo/15.0/gitlab-ci.yaml diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,8 @@ +# Defaults for all prettier-supported languages. +# Prettier will complete this with settings from .editorconfig file. +bracketSpacing: false +printWidth: 88 +proseWrap: always +semi: true +trailingComma: "es5" +xmlWhitespaceSensitivity: "ignore" diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,4 @@ +rules: + document-start: disable + indentation: + indent-sequences: true diff --git a/NEWS.rst b/NEWS.rst --- a/NEWS.rst +++ b/NEWS.rst @@ -1,24 +1,7 @@ -======= -Changes -======= +Changelog +========= -13.0.1.1.1 ----------- - -Fix reST in readme. - -13.0.1.1.0 +15.0.1.0.0 ---------- -Add code to handle currency formatting. - -Stop using hook to add methods to base when inheriting works. - -Add formatter class to ease creating compute methods. - -Add more caches. - -13.0.1.0.0 ----------- - -Port to Odoo 13.0 +Port to Odoo 15.0. diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -2,6 +2,22 @@ ICU Format ========== +.. Update the badge below depending on status +.. |maturity| image:: .badges/maturity.svg + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |license| image:: .badges/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |black| image:: .badges/code_style-black-000000.svg + :target: https://github.com/psf/black + :alt: Black +.. |prettier| image:: .badges/code_style-prettier-ff69b4.svg + :target: https://github.com/prettier/prettier + :alt: Prettier + +|maturity| |license| |black| |prettier| + Provides methods that encapsulates PyICU, including at the model level. ICU provides handling of plural and many other things that are not present in the gettext implementation of Odoo. diff --git a/__manifest__.py b/__manifest__.py --- a/__manifest__.py +++ b/__manifest__.py @@ -21,7 +21,7 @@ { "name": "ICU Format", "summary": "Format message using ICU", - "version": "13.0.1.1.1", + "version": "15.0.1.0.0", "category": "Technical", "author": "XCG Consulting", "website": "https://odoo.consulting/", diff --git a/hooks.py b/hooks.py --- a/hooks.py +++ b/hooks.py @@ -37,13 +37,13 @@ change Odoo’s function odoo.tools.translate.trans_generate. """ __original_extract = extract.extract - __ICU_FORMAT_TRANSLATE = "icu_format_translate" + __icu_format_translate = "icu_format_translate" # Same signature as babel.message.extract.extract def _extract( method, fileobj, - keywords={ + keywords={ # noqa: B006 "N_": None, "_": None, "dgettext": (2,), @@ -61,8 +61,8 @@ strip_comment_tags=True, ): if method == "python": - if __ICU_FORMAT_TRANSLATE not in keywords: - keywords[__ICU_FORMAT_TRANSLATE] = (1,) + if __icu_format_translate not in keywords: + keywords[__icu_format_translate] = (1,) # changed to include this tag by default if TRANSLATORS_TAG not in comment_tags: comment_tags += (TRANSLATORS_TAG,) diff --git a/i18n/fr.po b/i18n/fr.po new file mode 100644 --- /dev/null +++ b/i18n/fr.po @@ -0,0 +1,35 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * icuformat +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-11-09 16:25+0000\n" +"PO-Revision-Date: 2022-11-09 17:27+0100\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 2.4.2\n" +"Last-Translator: Vincent Hatakeyama <vincent.hatakeyama@xcg-consulting.fr>\n" +"Language: fr\n" + +#. module: icuformat +#. This is a test message, no need for translation +#: code:addons/icuformat/tests/test_icuformat.py:0 +#, python-format +msgid "A message" +msgstr "" + +#. module: icuformat +#: model:ir.model,name:icuformat.model_base +msgid "Base" +msgstr "Base" + +#. module: icuformat +#: model:ir.model,name:icuformat.model_res_currency +msgid "Currency" +msgstr "Devise" diff --git a/icu_format.py b/icu_format.py --- a/icu_format.py +++ b/icu_format.py @@ -21,6 +21,8 @@ import logging from typing import Dict, Mapping, Optional, Union +# Disable the warning as the library name is pyicu +# pylint: disable=missing-manifest-dependency from icu import Formattable, ICUError, ListFormatter, Locale, MessageFormat _logger = logging.getLogger(__name__) @@ -40,8 +42,7 @@ """Return an item, eventually created with the factory""" # create a tuple out of args and kwargs key = tuple( - tuple(arg.items()) if isinstance(arg, dict) else arg - for arg in args + tuple(arg.items()) if isinstance(arg, dict) else arg for arg in args ) + tuple( (key, tuple(value.items()) if isinstance(value, dict) else value) for key, value in kwargs.items() @@ -90,9 +91,7 @@ def format( self, - args: Dict[ - str, Union[int, str, datetime.date, datetime.datetime, bool, float] - ], + args: Dict[str, Union[int, str, datetime.date, datetime.datetime, bool, float]], raise_exception: bool = True, ): """Format a message with ICU. @@ -127,9 +126,7 @@ def icu_format( lang: Optional[str], msg: str, - args: Dict[ - str, Union[int, str, datetime.date, datetime.datetime, bool, float] - ], + args: Dict[str, Union[int, str, datetime.date, datetime.datetime, bool, float]], raise_exception: bool = True, locale_kwargs: Optional[Mapping[str, str]] = None, ) -> str: diff --git a/logger.py b/logger.py --- a/logger.py +++ b/logger.py @@ -19,8 +19,6 @@ ############################################################################## import logging -from odoo.tools import GettextAlias - from .icu_format import icu_format @@ -39,9 +37,6 @@ (C) to format the messages """ - # This will be used to call _get_lang (an instance is needed) - __gettext_alias = GettextAlias() - def log(self, level, msg, *args, **kwargs): """Changed to reformat the message according to the lang information, and from the provided dictionary. @@ -51,7 +46,7 @@ args_dict = args[0] args = args[1:] else: - args_dict = dict() + args_dict = {} msg = icu_format("C", msg, args_dict) msg, kwargs = self.process(msg, kwargs) @@ -79,7 +74,7 @@ def get_logger(name: str = None) -> logging.LoggerAdapter: """Provide a way to get a Logger that will call :func:`icu_format` only - when needed (to avoid spending time formating a message that will not be + when needed (to avoid spending time formatting a message that will not be displayed). This is similar to what is done in logging for formatting. .. code-block:: python @@ -91,4 +86,4 @@ _logger.info("Value: {value, number}", {"value": 1000}) """ logger = logging.getLogger(name) - return ICUFormatAdapter(logger, dict()) + return ICUFormatAdapter(logger, {}) diff --git a/logging_test.py b/logging_test.py new file mode 100644 --- /dev/null +++ b/logging_test.py @@ -0,0 +1,49 @@ +import inspect +import logging + +MAGIC_KEY = "icuvalues" + + +class CustomAdapter(logging.LoggerAdapter): + def log(self, level, msg, *args, **kwargs): + """ + Delegate a log call to the underlying logger, after adding + contextual information from this adapter instance. + """ + if self.isEnabledFor(level): + # reuse _ way of finding the lang + lang = None + frame = inspect.currentframe() + if frame is not None: + frame = frame.f_back + if frame: + lang = "en" + # lang = GettextAlias._get_lang(frame) + # pdb.set_trace() + if args: + args_dict = args[0] + args = args[1:] + else: + args_dict = {} + + msg = "icuformat(" + lang + ", " + msg + ", " + str(args_dict) + ")" + msg, kwargs = self.process(msg, kwargs) + self.logger.log(level, msg, *args, **kwargs) + + +logging.basicConfig( + level=logging.DEBUG, + format="%(relativeCreated)6d %(threadName)s %(message)s", +) +logger = logging.getLogger(__name__) +adapter = CustomAdapter(logger, {}) +adapter.info("ABC", {"a": 123}) +adapter.critical("Fatal") + +brace_formatter = logging.Formatter(fmt="{message}", style="{") +logger_brace = logger.getChild("test_brace") +map( + lambda handler: handler.setFormatter(brace_formatter), + logger_brace.handlers, +) +logger_brace.debug("Test %s", "a") diff --git a/models/base.py b/models/base.py --- a/models/base.py +++ b/models/base.py @@ -1,7 +1,7 @@ ############################################################################## # # ICU Format, a module for Odoo -# Copyright (C) 2021 XCG Consulting <https://odoo.consulting> +# Copyright (C) 2021, 2022 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 @@ -21,23 +21,18 @@ import logging from typing import Dict, Mapping, Union +# Disable the warning as the library name is pyicu +from icu import ICUError # pylint: disable=missing-manifest-dependency + from odoo import _, models -from ..icu_format import ( - ICUFormatter, - _icu_formatter_cache, - icu_format, - icu_list_format, -) - -from icu import ICUError +from ..icu_format import ICUFormatter, _icu_formatter_cache, icu_format, icu_list_format _logger = logging.getLogger(__name__) class BaseModel(models.AbstractModel): - """Add methods to BaseModel to use icu formatting. - """ + """Add methods to BaseModel to use icu formatting.""" _inherit = "base" @@ -49,9 +44,7 @@ def icu_format( self, msg: str, - args: Dict[ - str, Union[int, str, datetime.date, datetime.datetime, bool, float] - ], + args: Dict[str, Union[int, str, datetime.date, datetime.datetime, bool, float]], raise_exception: bool = False, ) -> str: """Provide a faster way to format the message, using the context lang, @@ -68,9 +61,7 @@ def icu_format_translate( self, untranslated_message: str, - args: Dict[ - str, Union[int, str, datetime.date, datetime.datetime, bool, float] - ], + args: Dict[str, Union[int, str, datetime.date, datetime.datetime, bool, float]], raise_exception: bool = False, ) -> str: """Try to format and translate a message. diff --git a/models/currency.py b/models/currency.py --- a/models/currency.py +++ b/models/currency.py @@ -1,7 +1,7 @@ ############################################################################## # # ICU Format, a module for Odoo -# Copyright (C) 2021 XCG Consulting <https://odoo.consulting> +# Copyright (C) 2021, 2022 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 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[tool.isort] +py_version = 310 +profile = "black" +known_odoo = ['odoo'] +known_odoo_addons = ['odoo.addons'] +sections = [ + 'FUTURE', + 'STDLIB', + 'THIRDPARTY', + 'ODOO', + 'ODOO_ADDONS', + 'FIRSTPARTY', + 'LOCALFOLDER' +] + +[tool.black] +target = 3.10 diff --git a/tests/test_icuformat.py b/tests/test_icuformat.py --- a/tests/test_icuformat.py +++ b/tests/test_icuformat.py @@ -1,7 +1,7 @@ ############################################################################### # # ICU Format, a module for Odoo -# Copyright (C) 2019, 2021 XCG Consulting (https://odoo.consulting/) +# Copyright (C) 2019, 2021, 2022 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 @@ -21,20 +21,20 @@ from odoo import tests -from odoo.addons.icuformat import ICUFormatter, icu_format, icu_list_format +from ..icu_format import ICUFormatter, icu_format, icu_list_format class Test(tests.TransactionCase): def test_simple(self): msg = "{test}" - d = {"test": "foobar"} + data = {"test": "foobar"} expected = "foobar" - self.assertEqual(expected, icu_format("en", msg, d)) + self.assertEqual(expected, icu_format("en", msg, data)) def test_nothing_to_format(self): msg = "test" - d = dict() - self.assertEqual(msg, icu_format("en", msg, d)) + data = {} + self.assertEqual(msg, icu_format("en", msg, data)) def test_nested_plural_select(self): msg = ( @@ -59,16 +59,14 @@ "other {{host} invites {guest} and # other people to their party.}" "}}}" ) - d = dict( + data = dict( gender_of_host="female", num_guests=1005, host="Ms. Marple", guest="Robert", ) - expected = ( - "Ms. Marple invites Robert and 1,004 other people to her party." - ) - self.assertEqual(expected, icu_format("en", msg, d)) + expected = "Ms. Marple invites Robert and 1,004 other people to her party." + self.assertEqual(expected, icu_format("en", msg, data)) def test_format_bool(self): # message with select should always have other, not just True/False @@ -87,39 +85,34 @@ def test_format_float(self): msg = "{i,number}" - d = {"i": 1000.12} - self.assertEqual("1,000.12", icu_format("en", msg, d)) - self.assertEqual("1 000,12", icu_format("fr", msg, d)) - self.assertEqual("1000.12", icu_format(None, msg, d)) + data = {"i": 1000.12} + self.assertEqual("1,000.12", icu_format("en", msg, data)) + self.assertEqual("1 000,12", icu_format("fr", msg, data)) + self.assertEqual("1000.12", icu_format(None, msg, data)) def test_format_year(self): msg = "{y,date,::yMMMM}" - d = {"y": date(2021, 3, 8)} - self.assertEqual("March 2021", icu_format(None, msg, d)) - self.assertEqual("March 2021", icu_format("en", msg, d)) - self.assertEqual("mars 2021", icu_format("fr", msg, d)) - self.assertEqual("2021年3月", icu_format("ja", msg, d)) - self.assertEqual("令和3年3月", icu_format("ja@calendar=japanese", msg, d)) + data = {"y": date(2021, 3, 8)} + self.assertEqual("March 2021", icu_format(None, msg, data)) + self.assertEqual("March 2021", icu_format("en", msg, data)) + self.assertEqual("mars 2021", icu_format("fr", msg, data)) + self.assertEqual("2021年3月", icu_format("ja", msg, data)) + self.assertEqual("令和3年3月", icu_format("ja@calendar=japanese", msg, data)) def test_record_icu_format(self): user = self.env["res.users"].search([], limit=1) - self.assertEqual("A message", user.icu_format("A message", dict())) - self.assertEqual("A message", user.icu_format("A message", dict())) + self.assertEqual("A message", user.icu_format("A message", {})) + self.assertEqual("A message", user.icu_format("A message", {})) def test_record_icu_format_and_translate(self): user = self.env["res.users"].search([], limit=1) # TRANSLATORS: This is a test message, no need for translation - self.assertEqual( - "A message", user.icu_format_translate("A message", dict()) - ) + self.assertEqual("A message", user.icu_format_translate("A message", {})) def test_list_format(self): - """Test the list formatter provided on BaseModel. - """ + """Test the list formatter provided on BaseModel.""" self.assertEqual(icu_list_format("fr", ["a", "b", "c"]), "a, b et c") - self.assertEqual( - icu_list_format("en_GB", ["1", "2", "5"]), "1, 2 and 5" - ) + self.assertEqual(icu_list_format("en_GB", ["1", "2", "5"]), "1, 2 and 5") user = self.env["res.users"].search([], limit=1) self.assertEqual(user.icu_list_format(["1", "2", "5"]), "1, 2, and 5") @@ -173,15 +166,11 @@ self.assertEqual(formatter.format(dict(total=2.3)), "Test 2.3") self.assertEqual(formatter.format(dict(total=11)), "Test 11") formatter = ICUFormatter("Test {total, number, currency}", "fr_FR") - self.assertEqual( - formatter.format(dict(total=147802.3)), "Test 147 802,30 €" - ) + self.assertEqual(formatter.format(dict(total=147802.3)), "Test 147 802,30 €") formatter = ICUFormatter( "Test {total, number, currency}", "fr_FR", {"currency": "GBP"} ) - self.assertEqual( - formatter.format(dict(total=147802.3)), "Test 147 802,30 £GB" - ) + self.assertEqual(formatter.format(dict(total=147802.3)), "Test 147 802,30 £GB") def test_record_icu_formatter(self): user = self.env["res.users"].search([], limit=1) diff --git a/tests/test_logger.py b/tests/test_logger.py --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -1,7 +1,7 @@ ############################################################################### # # ICU Format, a module for Odoo -# Copyright (C) 2019, 2021 XCG Consulting (https://odoo.consulting/) +# Copyright (C) 2019, 2021, 2022 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 @@ -26,8 +26,7 @@ class Test(tests.TransactionCase): def test_logging(self): - """Test adapter provided by this module. - """ + """Test adapter provided by this module.""" logger = get_logger(__name__) logger.info("Info level test message without formatting") logger.info(