diff options
author | Ashley Whetter <ashley@awhetter.co.uk> | 2020-04-05 18:11:08 -0700 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2020-04-27 10:34:18 +0200 |
commit | fb59ed86d5e463ebfdeb5d0af8539b7a8431aa15 (patch) | |
tree | 460a7553ace1d0b8b6dde264cd97d6b4b0dd3d6f | |
parent | db0d55bcb19db4d8a9b7dd339d6ab554a4a1f017 (diff) | |
download | pylint-git-fb59ed86d5e463ebfdeb5d0af8539b7a8431aa15.tar.gz |
Brought back logging-fstring-interpolation
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | doc/whatsnew/2.5.rst | 8 | ||||
-rw-r--r-- | pylint/checkers/logging.py | 102 | ||||
-rw-r--r-- | tests/functional/l/logging_format_interpolation.txt | 10 | ||||
-rw-r--r-- | tests/functional/l/logging_format_interpolation_py36.py | 4 | ||||
-rw-r--r-- | tests/functional/l/logging_format_interpolation_py36.txt | 2 | ||||
-rw-r--r-- | tests/functional/l/logging_fstring_interpolation_py36.py | 12 | ||||
-rw-r--r-- | tests/functional/l/logging_fstring_interpolation_py36.txt | 10 | ||||
-rw-r--r-- | tests/functional/l/logging_not_lazy.txt | 12 | ||||
-rw-r--r-- | tests/messages/func_bug113231.txt | 4 | ||||
-rw-r--r-- | tests/messages/func_logging_not_lazy_with_logger.txt | 8 | ||||
-rw-r--r-- | tests/unittest_checker_logging.py | 46 |
12 files changed, 113 insertions, 112 deletions
@@ -275,6 +275,13 @@ Release date: TBA Close #1482 Close #1553 +* Multiple types of string formatting are allowed in logging functions. + + The `logging-fstring-interpolation` message has been brought back to allow + multiple types of string formatting to be used. + + Close #3361 + What's New in Pylint 2.4.4? =========================== Release date: 2019-11-13 diff --git a/doc/whatsnew/2.5.rst b/doc/whatsnew/2.5.rst index 178b8c34b..35ffbbdcc 100644 --- a/doc/whatsnew/2.5.rst +++ b/doc/whatsnew/2.5.rst @@ -92,3 +92,11 @@ Other Changes This command lists all extensions present in ``pylint.extensions``. * Various false positives have been fixed which you can read more about in the Changelog files. + +* Multiple types of string formatting are allowed in logging functions. + +The `logging-fstring-interpolation` message has been brought back to allow +multiple types of string formatting to be used. +The type of formatting to use is chosen through enabling and disabling messages +rather than through the logging-format-style option. +The fstr value of the logging-format-style option is not valid. diff --git a/pylint/checkers/logging.py b/pylint/checkers/logging.py index 9a2ab95d3..5de0340d5 100644 --- a/pylint/checkers/logging.py +++ b/pylint/checkers/logging.py @@ -26,25 +26,43 @@ from pylint.checkers.utils import check_messages MSGS = { "W1201": ( - "Specify string format arguments as logging function parameters", + "Use %s formatting in logging functions", "logging-not-lazy", "Used when a logging statement has a call form of " '"logging.<logging method>(format_string % (format_args...))". ' - "Such calls should leave string interpolation to the logging " - "method itself and be written " - '"logging.<logging method>(format_string, format_args...)" ' - "so that the program may avoid incurring the cost of the " - "interpolation in those cases in which no message will be " - "logged. For more, see " - "http://www.python.org/dev/peps/pep-0282/.", + "Use another type of string formatting instead. " + "You can use % formatting but leave interpolation to " + "the logging function by passing the parameters as arguments. " + "If logging-fstring-interpolation is disabled then " + "you can use fstring formatting. " + "If logging-format-interpolation is disabled then " + "you can use str.format.", ), "W1202": ( - "Use %s formatting in logging functions%s", + "Use %s formatting in logging functions", "logging-format-interpolation", "Used when a logging statement has a call form of " - '"logging.<logging method>(<string formatting>)".' - " with invalid string formatting. " - "Use another way for format the string instead.", + '"logging.<logging method>(format_string.format(format_args...))". ' + "Use another type of string formatting instead. " + "You can use % formatting but leave interpolation to " + "the logging function by passing the parameters as arguments. " + "If logging-fstring-interpolation is disabled then " + "you can use fstring formatting. " + "If logging-not-lazy is disabled then " + "you can use % formatting as normal.", + ), + "W1203": ( + "Use %s formatting in logging functions", + "logging-fstring-interpolation", + "Used when a logging statement has a call form of " + '"logging.<logging method>(f"...")".' + "Use another type of string formatting instead. " + "You can use % formatting but leave interpolation to " + "the logging function by passing the parameters as arguments. " + "If logging-format-interpolation is disabled then " + "you can use str.format. " + "If logging-not-lazy is disabled then " + "you can use % formatting as normal.", ), "E1200": ( "Unsupported logging format character %r (%#02x) at index %d", @@ -126,11 +144,10 @@ class LoggingChecker(checkers.BaseChecker): { "default": "old", "type": "choice", - "metavar": "<old (%) or new ({) or fstr (f'')>", - "choices": ["old", "new", "fstr"], - "help": "Format style used to check logging format string. " - "`old` means using % formatting, `new` is for `{}` formatting," - "and `fstr` is for f-strings.", + "metavar": "<old (%) or new ({)>", + "choices": ["old", "new"], + "help": "The type of string formatting that logging methods do. " + "`old` means using % formatting, `new` is for `{}` formatting.", }, ), ) @@ -144,12 +161,6 @@ class LoggingChecker(checkers.BaseChecker): logging_mods = self.config.logging_modules self._format_style = self.config.logging_format_style - format_styles = {"old": "%", "new": "{", "fstr": "f-string"} - format_style_help = "" - if self._format_style == "old": - format_style_help = " and pass the % parameters as arguments" - - self._format_style_args = (format_styles[self._format_style], format_style_help) self._logging_modules = set(logging_mods) self._from_imports = {} @@ -238,20 +249,36 @@ class LoggingChecker(checkers.BaseChecker): ) emit = total_number_of_strings > 0 if emit: - self.add_message("logging-not-lazy", node=node) + self.add_message( + "logging-not-lazy", node=node, args=(self._helper_string(node),), + ) elif isinstance(node.args[format_pos], astroid.Call): self._check_call_func(node.args[format_pos]) elif isinstance(node.args[format_pos], astroid.Const): self._check_format_string(node, format_pos) - elif isinstance( - node.args[format_pos], (astroid.FormattedValue, astroid.JoinedStr) + elif isinstance(node.args[format_pos], astroid.JoinedStr): + self.add_message( + "logging-fstring-interpolation", + node=node, + args=(self._helper_string(node),), + ) + + def _helper_string(self, node): + """Create a string that lists the valid types of formatting for this node.""" + valid_types = ["lazy %"] + + if not self.linter.is_message_enabled( + "logging-fstring-formatting", node.fromlineno ): - if self._format_style != "fstr": - self.add_message( - "logging-format-interpolation", - node=node, - args=self._format_style_args, - ) + valid_types.append("fstring") + if not self.linter.is_message_enabled( + "logging-format-formatting", node.fromlineno + ): + valid_types.append(".format()") + if not self.linter.is_message_enabled("logging-not-lazy", node.fromlineno): + valid_types.append("%") + + return " or ".join(valid_types) @staticmethod def _is_operand_literal_str(operand): @@ -274,7 +301,9 @@ class LoggingChecker(checkers.BaseChecker): func.bound ): self.add_message( - "logging-format-interpolation", node=node, args=self._format_style_args + "logging-format-interpolation", + node=node, + args=(self._helper_string(node),), ) def _check_format_string(self, node, format_arg): @@ -317,13 +346,6 @@ class LoggingChecker(checkers.BaseChecker): required_num_args = ( keyword_args_cnt + implicit_pos_args + explicit_pos_args ) - else: - self.add_message( - "logging-format-interpolation", - node=node, - args=self._format_style_args, - ) - return except utils.UnsupportedFormatCharacter as ex: char = format_string[ex.index] self.add_message( diff --git a/tests/functional/l/logging_format_interpolation.txt b/tests/functional/l/logging_format_interpolation.txt index 36051253c..1b27530b7 100644 --- a/tests/functional/l/logging_format_interpolation.txt +++ b/tests/functional/l/logging_format_interpolation.txt @@ -1,5 +1,5 @@ -logging-format-interpolation:16::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:17::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:18::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:19::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:20::Use % formatting in logging functions and pass the % parameters as arguments +logging-format-interpolation:16::Use lazy % formatting in logging functions +logging-format-interpolation:17::Use lazy % formatting in logging functions +logging-format-interpolation:18::Use lazy % formatting in logging functions +logging-format-interpolation:19::Use lazy % formatting in logging functions +logging-format-interpolation:20::Use lazy % formatting in logging functions diff --git a/tests/functional/l/logging_format_interpolation_py36.py b/tests/functional/l/logging_format_interpolation_py36.py index 92958ae5a..2601c5bfc 100644 --- a/tests/functional/l/logging_format_interpolation_py36.py +++ b/tests/functional/l/logging_format_interpolation_py36.py @@ -1,5 +1,5 @@ -"""Test logging-format-interpolation for Python 3.6""" +"""Test logging-fstring-interpolation for Python 3.6""" import logging as renamed_logging -renamed_logging.info(f'Read {renamed_logging} from globals') # [logging-format-interpolation] +renamed_logging.info(f'Read {renamed_logging} from globals') # [logging-fstring-interpolation] diff --git a/tests/functional/l/logging_format_interpolation_py36.txt b/tests/functional/l/logging_format_interpolation_py36.txt index 7a7dc06c0..bc185c975 100644 --- a/tests/functional/l/logging_format_interpolation_py36.txt +++ b/tests/functional/l/logging_format_interpolation_py36.txt @@ -1 +1 @@ -logging-format-interpolation:5::Use % formatting in logging functions and pass the % parameters as arguments +logging-fstring-interpolation:5::Use lazy % formatting in logging functions diff --git a/tests/functional/l/logging_fstring_interpolation_py36.py b/tests/functional/l/logging_fstring_interpolation_py36.py index 68eaba22f..5aebb7dd2 100644 --- a/tests/functional/l/logging_fstring_interpolation_py36.py +++ b/tests/functional/l/logging_fstring_interpolation_py36.py @@ -1,4 +1,4 @@ -"""Test logging-format-interpolation for Python 3.6""" +"""Test logging-fstring-interpolation for Python 3.6""" # pylint: disable=invalid-name from datetime import datetime @@ -14,8 +14,8 @@ pi = 3.14159265 may_14 = datetime(year=2018, month=5, day=14) # Statements that should be flagged: -renamed_logging.debug(f'{local_var_1} {local_var_2}') # [logging-format-interpolation] -renamed_logging.log(renamed_logging.DEBUG, f'msg: {local_var_2}') # [logging-format-interpolation] -renamed_logging.log(renamed_logging.DEBUG, f'pi: {pi:.3f}') # [logging-format-interpolation] -renamed_logging.info(f"{local_var_2.upper()}") # [logging-format-interpolation] -renamed_logging.info(f"{may_14:'%b %d: %Y'}") # [logging-format-interpolation] +renamed_logging.debug(f'{local_var_1} {local_var_2}') # [logging-fstring-interpolation] +renamed_logging.log(renamed_logging.DEBUG, f'msg: {local_var_2}') # [logging-fstring-interpolation] +renamed_logging.log(renamed_logging.DEBUG, f'pi: {pi:.3f}') # [logging-fstring-interpolation] +renamed_logging.info(f"{local_var_2.upper()}") # [logging-fstring-interpolation] +renamed_logging.info(f"{may_14:'%b %d: %Y'}") # [logging-fstring-interpolation] diff --git a/tests/functional/l/logging_fstring_interpolation_py36.txt b/tests/functional/l/logging_fstring_interpolation_py36.txt index a8c6fd5cd..e0c445c4b 100644 --- a/tests/functional/l/logging_fstring_interpolation_py36.txt +++ b/tests/functional/l/logging_fstring_interpolation_py36.txt @@ -1,5 +1,5 @@ -logging-format-interpolation:17::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:18::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:19::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:20::Use % formatting in logging functions and pass the % parameters as arguments -logging-format-interpolation:21::Use % formatting in logging functions and pass the % parameters as arguments +logging-fstring-interpolation:17::Use lazy % formatting in logging functions +logging-fstring-interpolation:18::Use lazy % formatting in logging functions +logging-fstring-interpolation:19::Use lazy % formatting in logging functions +logging-fstring-interpolation:20::Use lazy % formatting in logging functions +logging-fstring-interpolation:21::Use lazy % formatting in logging functions diff --git a/tests/functional/l/logging_not_lazy.txt b/tests/functional/l/logging_not_lazy.txt index 31e7cc448..95ef675b2 100644 --- a/tests/functional/l/logging_not_lazy.txt +++ b/tests/functional/l/logging_not_lazy.txt @@ -1,6 +1,6 @@ -logging-not-lazy:10::Specify string format arguments as logging function parameters -logging-not-lazy:11::Specify string format arguments as logging function parameters -logging-not-lazy:12::Specify string format arguments as logging function parameters -logging-not-lazy:13::Specify string format arguments as logging function parameters -logging-not-lazy:14::Specify string format arguments as logging function parameters -logging-not-lazy:15::Specify string format arguments as logging function parameters +logging-not-lazy:10::Use lazy % formatting in logging functions +logging-not-lazy:11::Use lazy % formatting in logging functions +logging-not-lazy:12::Use lazy % formatting in logging functions +logging-not-lazy:13::Use lazy % formatting in logging functions +logging-not-lazy:14::Use lazy % formatting in logging functions +logging-not-lazy:15::Use lazy % formatting in logging functions diff --git a/tests/messages/func_bug113231.txt b/tests/messages/func_bug113231.txt index a9d3f7ef3..f05f16020 100644 --- a/tests/messages/func_bug113231.txt +++ b/tests/messages/func_bug113231.txt @@ -1,2 +1,2 @@ -W: 20: Specify string format arguments as logging function parameters -W: 21: Specify string format arguments as logging function parameters +W: 20: Use lazy % formatting in logging functions +W: 21: Use lazy % formatting in logging functions diff --git a/tests/messages/func_logging_not_lazy_with_logger.txt b/tests/messages/func_logging_not_lazy_with_logger.txt index 04823cf33..22e7bc6af 100644 --- a/tests/messages/func_logging_not_lazy_with_logger.txt +++ b/tests/messages/func_logging_not_lazy_with_logger.txt @@ -1,4 +1,4 @@ -W: 8: Specify string format arguments as logging function parameters -W: 9: Specify string format arguments as logging function parameters -W: 11: Specify string format arguments as logging function parameters -W: 13: Specify string format arguments as logging function parameters +W: 8: Use lazy % formatting in logging functions +W: 9: Use lazy % formatting in logging functions +W: 11: Use lazy % formatting in logging functions +W: 13: Use lazy % formatting in logging functions diff --git a/tests/unittest_checker_logging.py b/tests/unittest_checker_logging.py index 50ba2100f..a025fb6a2 100644 --- a/tests/unittest_checker_logging.py +++ b/tests/unittest_checker_logging.py @@ -30,7 +30,7 @@ class TestLoggingModuleDetection(CheckerTestCase): ) self.checker.visit_module(None) self.checker.visit_import(stmts[0]) - with self.assertAddsMessages(Message("logging-not-lazy", node=stmts[1])): + with self.assertAddsMessages(Message("logging-not-lazy", node=stmts[1], args=("lazy %",))): self.checker.visit_call(stmts[1]) def test_dont_crash_on_invalid_format_string(self): @@ -51,7 +51,7 @@ class TestLoggingModuleDetection(CheckerTestCase): ) self.checker.visit_module(None) self.checker.visit_import(stmts[0]) - with self.assertAddsMessages(Message("logging-not-lazy", node=stmts[1])): + with self.assertAddsMessages(Message("logging-not-lazy", node=stmts[1], args=("lazy %",))): self.checker.visit_call(stmts[1]) @set_config(logging_modules=["logging", "my.logging"]) @@ -64,7 +64,7 @@ class TestLoggingModuleDetection(CheckerTestCase): ) self.checker.visit_module(None) self.checker.visit_import(stmts[0]) - with self.assertAddsMessages(Message("logging-not-lazy", node=stmts[1])): + with self.assertAddsMessages(Message("logging-not-lazy", node=stmts[1], args=("lazy %",))): self.checker.visit_call(stmts[1]) def _assert_logging_format_no_messages(self, stmt): @@ -140,42 +140,6 @@ class TestLoggingModuleDetection(CheckerTestCase): @pytest.mark.skipif(sys.version_info < (3, 6), reason="F-string require >=3.6") @set_config(logging_format_style="new") def test_fstr_not_new_format_style_matching_arguments(self): - msg = "logging-format-interpolation" - args = ("{", "") + msg = "logging-fstring-interpolation" + args = ("lazy %",) self._assert_logging_format_message(msg, "(f'{named}')", args) - - @set_config(logging_format_style="fstr") - def test_modulo_not_fstr_format_style_matching_arguments(self): - msg = "logging-format-interpolation" - args = ("f-string", "") - with_too_many = False - self._assert_logging_format_message(msg, "('%s', 1)", args, with_too_many) - self._assert_logging_format_message( - msg, "('%(named)s', {'named': 1})", args, with_too_many - ) - self._assert_logging_format_message( - msg, "('%s %(named)s', 1, {'named': 1})", args, with_too_many - ) - - @set_config(logging_format_style="fstr") - def test_brace_not_fstr_format_style_matching_arguments(self): - msg = "logging-format-interpolation" - args = ("f-string", "") - with_too_many = False - self._assert_logging_format_message(msg, "('{}', 1)", args, with_too_many) - self._assert_logging_format_message(msg, "('{0}', 1)", args, with_too_many) - self._assert_logging_format_message( - msg, "('{named}', {'named': 1})", args, with_too_many - ) - self._assert_logging_format_message( - msg, "('{} {named}', 1, {'named': 1})", args, with_too_many - ) - self._assert_logging_format_message( - msg, "('{0} {named}', 1, {'named': 1})", args, with_too_many - ) - - @pytest.mark.skipif(sys.version_info < (3, 6), reason="F-string require >=3.6") - @set_config(logging_format_style="fstr") - def test_fstr_format_style_matching_arguments(self): - self._assert_logging_format_no_messages("(f'constant string')") - self._assert_logging_format_no_messages("(f'{named}')") |