From df77a71538b5735cedafe9d79d6942dd77786ca8 Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Thu, 6 Jan 2022 12:13:34 +0100 Subject: [PATCH 01/16] improve non-ascii check --- pylint/checkers/base.py | 27 +- pylint/checkers/non_ascii_names.py | 240 ++++++++++++++++++ tests/checkers/unittest_non_ascii_name.py | 204 +++++++++++++++ tests/functional/n/non_ascii_name/__init__.py | 0 .../non_ascii_name_assignment_expressions.py | 4 + .../non_ascii_name_assignment_expressions.rc | 2 + .../non_ascii_name_assignment_expressions.txt | 1 + .../n/non_ascii_name/non_ascii_name_class.py | 17 ++ .../n/non_ascii_name/non_ascii_name_class.txt | 1 + .../non_ascii_name_class_attribute.py | 25 ++ .../non_ascii_name_class_attribute.txt | 1 + .../non_ascii_name_class_constant.py | 23 ++ .../non_ascii_name_class_constant.txt | 1 + .../non_ascii_name_class_method.py | 18 ++ .../non_ascii_name_class_method.txt | 1 + .../non_ascii_name_dict_kwargs.py | 13 + .../non_ascii_name/non_ascii_name_for_loop.py | 14 + .../non_ascii_name_for_loop.txt | 1 + .../non_ascii_name/non_ascii_name_function.py | 19 ++ .../non_ascii_name_function.txt | 1 + ..._ascii_name_function_argument_py37minus.py | 22 ++ ..._ascii_name_function_argument_py37minus.rc | 2 + ...ascii_name_function_argument_py37minus.txt | 2 + ...n_ascii_name_function_argument_py39plus.py | 22 ++ ...n_ascii_name_function_argument_py39plus.rc | 2 + ..._ascii_name_function_argument_py39plus.txt | 2 + .../non_ascii_name_import_as.py | 6 + .../non_ascii_name_import_as.txt | 1 + .../non_ascii_name_import_from_as.py | 6 + .../non_ascii_name_import_from_as.txt | 1 + .../non_ascii_name_inline_var.py | 8 + .../non_ascii_name_inline_var.txt | 1 + .../non_ascii_name_kwargs_py37minus.py | 15 ++ .../non_ascii_name_kwargs_py37minus.rc | 2 + .../non_ascii_name_kwargs_py37minus.txt | 1 + .../non_ascii_name_kwargs_py39plus.py | 15 ++ .../non_ascii_name_kwargs_py39plus.rc | 2 + .../non_ascii_name_kwargs_py39plus.txt | 1 + .../n/non_ascii_name/non_ascii_name_local.py | 9 + .../n/non_ascii_name/non_ascii_name_local.txt | 1 + .../non_ascii_name_pos_and_kwonly_function.py | 21 ++ .../non_ascii_name_pos_and_kwonly_function.rc | 2 + ...non_ascii_name_pos_and_kwonly_function.txt | 4 + .../non_ascii_name_staticmethod.py | 17 ++ .../non_ascii_name_staticmethod.txt | 1 + .../non_ascii_name_try_except.py | 11 + .../non_ascii_name_try_except.txt | 1 + .../non_ascii_name/non_ascii_name_variable.py | 9 + .../non_ascii_name_variable.txt | 2 + 49 files changed, 780 insertions(+), 22 deletions(-) create mode 100644 pylint/checkers/non_ascii_names.py create mode 100644 tests/checkers/unittest_non_ascii_name.py create mode 100644 tests/functional/n/non_ascii_name/__init__.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_method.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_dict_kwargs.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_import_as.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_local.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_local.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_try_except.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_variable.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_variable.txt diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 2fe6123f1d..2f79f852e0 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -1737,11 +1737,6 @@ class NameChecker(_BasicChecker): ] }, ), - "C0144": ( - '%s name "%s" contains a non-ASCII unicode character', - "non-ascii-name", - "Used when the name contains at least one non-ASCII unicode character.", - ), "W0111": ( "Name %s will become a keyword in Python %s", "assign-to-new-keyword", @@ -1838,7 +1833,6 @@ def __init__(self, linter): self._name_hints = {} self._good_names_rgxs_compiled = [] self._bad_names_rgxs_compiled = [] - self._non_ascii_rgx_compiled = re.compile("[^\u0000-\u007F]") def open(self): self.linter.stats.reset_bad_names() @@ -1878,7 +1872,7 @@ def _create_naming_rules(self): return regexps, hints - @utils.check_messages("disallowed-name", "invalid-name", "non-ascii-name") + @utils.check_messages("disallowed-name", "invalid-name") def visit_module(self, node: nodes.Module) -> None: self._check_name("module", node.name.split(".")[-1], node) self._bad_names = {} @@ -1904,9 +1898,7 @@ def leave_module(self, _: nodes.Module) -> None: for args in warnings: self._raise_name_warning(prevalent_group, *args) - @utils.check_messages( - "disallowed-name", "invalid-name", "assign-to-new-keyword", "non-ascii-name" - ) + @utils.check_messages("disallowed-name", "invalid-name", "assign-to-new-keyword") def visit_classdef(self, node: nodes.ClassDef) -> None: self._check_assign_to_new_keyword_violation(node.name, node) self._check_name("class", node.name, node) @@ -1914,9 +1906,7 @@ def visit_classdef(self, node: nodes.ClassDef) -> None: if not any(node.instance_attr_ancestors(attr)): self._check_name("attr", attr, anodes[0]) - @utils.check_messages( - "disallowed-name", "invalid-name", "assign-to-new-keyword", "non-ascii-name" - ) + @utils.check_messages("disallowed-name", "invalid-name", "assign-to-new-keyword") def visit_functiondef(self, node: nodes.FunctionDef) -> None: # Do not emit any warnings if the method is just an implementation # of a base class method. @@ -1944,14 +1934,12 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: visit_asyncfunctiondef = visit_functiondef - @utils.check_messages("disallowed-name", "invalid-name", "non-ascii-name") + @utils.check_messages("disallowed-name", "invalid-name") def visit_global(self, node: nodes.Global) -> None: for name in node.names: self._check_name("const", name, node) - @utils.check_messages( - "disallowed-name", "invalid-name", "assign-to-new-keyword", "non-ascii-name" - ) + @utils.check_messages("disallowed-name", "invalid-name", "assign-to-new-keyword") def visit_assignname(self, node: nodes.AssignName) -> None: """check module level assigned names""" self._check_assign_to_new_keyword_violation(node.name, node) @@ -2041,11 +2029,6 @@ def _name_disallowed_by_regex(self, name: str) -> bool: def _check_name(self, node_type, name, node, confidence=interfaces.HIGH): """check for a name using the type's regexp""" - non_ascii_match = self._non_ascii_rgx_compiled.match(name) - if non_ascii_match is not None: - self._raise_name_warning( - None, node, node_type, name, confidence, warning="non-ascii-name" - ) def _should_exempt_from_invalid_name(node): if node_type == "variable": diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py new file mode 100644 index 0000000000..6438b8ca91 --- /dev/null +++ b/pylint/checkers/non_ascii_names.py @@ -0,0 +1,240 @@ +# Copyright (c) 2021-2022 Carli Freudenberg + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE +"""All alphanumeric unicode character are allowed in Python but due +to similarities in how they look they can be confused. + +See: https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers + +The following checkers are intended to make users are aware of these issues. +""" + +import re +import sys +from typing import Iterable, List, Optional, Union + +from astroid import nodes + +import pylint.checkers.utils +from pylint import interfaces +from pylint.constants import HUMAN_READABLE_TYPES +from pylint.lint import PyLinter + +if sys.version_info >= (3, 8): + from typing import Protocol +else: + from typing_extensions import Protocol + + +if sys.version_info[:2] >= (3, 7): + # pylint: disable-next=fixme + # TODO: Remove after 3.6 has been deprecated + Py37Str = str +else: + + class Py37Str(str): + # Allow Python 3.6 compatibility + def isascii(self: str) -> bool: + return all("\u0000" <= x <= "\u007F" for x in self) + + +class _AsciiOnlyCheckedNode(Protocol): + _is_ascii_only: bool + + +class NonAsciiNamesChecker(pylint.checkers.BaseChecker): + """A strict name checker only allowing ASCII + + If your programming guideline defines that you are programming in English, + then there should be no need for non ASCII characters in Python Names. + Everybody else can simply not use this check. + + Note: This check only checks Names, so it ignores the content of + docstrings and comments! + """ + + __implements__ = interfaces.IAstroidChecker + priority = -1 + + msgs = { + "C0144": ( + '%s name "%s" contains a non-ASCII character, rename it or use an alias for import', + "non-ascii-name", + ( + "Used when the name contains at least one non-ASCII unicode character. " + "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" + " for a background why this could be bad." + ), + ), + } + + name = "NonASCII-Checker" + + def __init__(self, linter: PyLinter) -> None: + super().__init__(linter) + self._non_ascii_rgx_compiled = re.compile("[^A-Za-z0-9_]") + + def _raise_name_warning( + self, + node: nodes.NodeNG, + node_type: str, + name: str, + ) -> None: + type_label = HUMAN_READABLE_TYPES[node_type] + args = (type_label.capitalize(), name) + + self.add_message( + "non-ascii-name", node=node, args=args, confidence=interfaces.HIGH + ) + + def _check_name( + self, + node_type: str, + names: Union[str, List[str]], + node: Union[nodes.NodeNG, _AsciiOnlyCheckedNode], + ) -> None: + """Check whether a name is using non-ASCII characters. + + Also set the dynamic attribute ``_is_ascii_only`` that is used to + determine if a node has been already checked, so we don't have to handle + too many edge cases. + """ + if not isinstance(names, list): + names = [names] + + current_state = getattr(node, "_is_ascii_only", True) + for name in names: + if name is None: + # For some nodes i.e. *kwargs from a dict, the name will be empty + continue + if not ( + Py37Str(name).isascii() + and self._non_ascii_rgx_compiled.match(name) is None + ): + # Note that we require the `.isascii` method as it is fast and + # handles the complexities of unicode, so we can use simple regex. + self._raise_name_warning(node, node_type, name) + current_state = False + + node._is_ascii_only = current_state # pylint: disable=protected-access + + def _recursive_check_names(self, args: Iterable[nodes.AssignName]) -> None: + """check names in a possibly recursive list """ + for arg in args: + if isinstance(arg, nodes.AssignName): + self._check_name("argument", arg.name, arg) + else: + # pylint: disable-next=fixme + # TODO: Check if we can remove this branch because of + # the up to date astroid version used + self._recursive_check_names(arg.elts) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_module(self, node: nodes.Module) -> None: + # pylint: disable-next=fixme + # TODO check how the node name is defined when calling the real checker + # in the test using the astroid manager the node.name attribute corresponds + # to the filename -> so we always have ".py" as result of the following + # function. + # It would be nice if we could check for an ASCII filename, if not done + # already by other checkers... + self._check_name("module", node.name.split(".")[-1], node) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_functiondef( + self, node: Union[nodes.FunctionDef, nodes.AsyncFunctionDef] + ) -> None: + self._check_name("function", node.name, node) + + # Check argument names + arguments = node.args + + # Check position only arguments + if arguments.posonlyargs is not None: + for pos_only_arg in arguments.posonlyargs: + self._check_name("argument", pos_only_arg.name, pos_only_arg) + + # Check "normal" arguments + args = arguments.args + if args is not None: + self._recursive_check_names(args) + + # Check key word only arguments + if arguments.kwonlyargs is not None: + for kwarg in arguments.kwonlyargs: + self._check_name("argument", kwarg.name, kwarg) + + visit_asyncfunctiondef = visit_functiondef + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_global(self, node: nodes.Global) -> None: + for name in node.names: + self._check_name("const", name, node) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_assignname(self, node: nodes.AssignName) -> None: + """check module level assigned names""" + # The NameChecker from which this Checker originates knows a lot of different + # versions of variables, i.e. constants, inline variables etc. + # To simplify we use only `variable` here, as we don't need to apply different + # rules to different types of variables. + frame = node.frame() + assign_type = node.assign_type() + if isinstance(assign_type, nodes.Comprehension): + # called inlinevar in NamesChecker + self._check_name("variable", node.name, node) + elif isinstance(frame, nodes.Module): + self._check_name("variable", node.name, node) + elif isinstance(frame, nodes.FunctionDef): + if not hasattr(node, "_is_ascii_only"): + # only check if not already done + self._check_name("variable", node.name, node) + elif isinstance(frame, nodes.ClassDef): + self._check_name("attr", node.name, node) + else: + # Just to make sure we check EVERYTHING (!) + self._check_name("variable", node.name, node) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_classdef(self, node: nodes.ClassDef) -> None: + self._check_name("class", node.name, node) + for attr, anodes in node.instance_attrs.items(): + if not any(node.instance_attr_ancestors(attr)): + self._check_name("attr", attr, anodes[0]) + + @staticmethod + def _get_module_names(module_name: str, alias: Optional[str] = None) -> List[str]: + result = module_name.split(".") + if alias is not None: + result.append(alias) + return result + + def _check_module_import( + self, node: Union[nodes.ImportFrom, nodes.Import], is_import_from: bool = False + ): + names = [] + for module_name, alias in node.names: + names += self._get_module_names(module_name, alias) + if not (is_import_from and names == ["*"]): + # Ignore ``from xyz import *`` + self._check_name("module", names, node) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_import(self, node: nodes.Import) -> None: + self._check_module_import(node) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_importfrom(self, node: nodes.ImportFrom) -> None: + self._check_name("module", self._get_module_names(node.modname), node) + self._check_module_import(node, is_import_from=True) + + @pylint.checkers.utils.check_messages("non-ascii-name") + def visit_call(self, node: nodes.Call) -> None: + # lets check if the used keyword args are correct + for keyword in node.keywords: + self._check_name("argument", keyword.arg, keyword) + + +def register(linter: PyLinter) -> None: + linter.register_checker(NonAsciiNamesChecker(linter)) diff --git a/tests/checkers/unittest_non_ascii_name.py b/tests/checkers/unittest_non_ascii_name.py new file mode 100644 index 0000000000..499114a86e --- /dev/null +++ b/tests/checkers/unittest_non_ascii_name.py @@ -0,0 +1,204 @@ +import sys + +import astroid +import pytest +from astroid import nodes + +import pylint.checkers.non_ascii_names +import pylint.interfaces +import pylint.testutils + + +class TestNonAsciiChecker(pylint.testutils.CheckerTestCase): + CHECKER_CLASS = pylint.checkers.non_ascii_names.NonAsciiNamesChecker + checker: pylint.checkers.non_ascii_names.NonAsciiNamesChecker + + EXPECTED_MSG = "non-ascii-name" + + def test_get_module_names(self): + """The static function _get_modules_names shall resolve module names correctly""" + assert self.CHECKER_CLASS._get_module_names("foo.bar.test") == [ + "foo", + "bar", + "test", + ] + assert self.CHECKER_CLASS._get_module_names("foo.bar", "test") == [ + "foo", + "bar", + "test", + ] + + @pytest.mark.skipif( + sys.version_info < (3, 8), reason="requires python3.8 or higher" + ) + def test_kwargs_and_position_only(self): + """Even the new position only and keyword only should be found""" + node = astroid.extract_node( + """ + def name( + ok, + not_økay, + not_okay_defaułt=None, + /, + p_or_kw_okay=None, + p_or_kw_not_økay=None, + *, + kw_arg_okay, + kw_arg_not_økay, + ): + ... + """ + ) + assert isinstance(node, nodes.FunctionDef) + arguments: nodes.Arguments = node.args + + posargs = list(arguments.posonlyargs) + args = list(arguments.args) + kwargs = list(arguments.kwonlyargs) + + with self.assertAddsMessages( + pylint.testutils.MessageTest( + msg_id=self.EXPECTED_MSG, + node=posargs[1], + args=("Argument", "not_økay"), + confidence=pylint.interfaces.HIGH, + ), + pylint.testutils.MessageTest( + msg_id=self.EXPECTED_MSG, + node=posargs[2], + args=("Argument", "not_okay_defaułt"), + confidence=pylint.interfaces.HIGH, + ), + pylint.testutils.MessageTest( + msg_id=self.EXPECTED_MSG, + node=args[1], + args=("Argument", "p_or_kw_not_økay"), + confidence=pylint.interfaces.HIGH, + ), + pylint.testutils.MessageTest( + msg_id=self.EXPECTED_MSG, + node=kwargs[1], + args=("Argument", "kw_arg_not_økay"), + confidence=pylint.interfaces.HIGH, + ), + ignore_position=True, + ): + self.checker.visit_functiondef(node) + + @pytest.mark.parametrize( + "code, assign_type", + [ + pytest.param( + """ + try: + ... + except ValueError as łol: #@ + ... + """, + "Variable", + id="try-except", + ), + pytest.param( + """ + class FooBar: + łol = "test" #@ + """, + "Attribute", + id="class_attribute", + ), + pytest.param( + """ + łol = "test" #@ + """, + "Variable", + id="global_assign", + ), + pytest.param( + """ + def foobar(): + łol="test" #@ + """, + "Variable", + id="function_variable", + ), + pytest.param( + """ + for łol in os.listdir("."): #@ + ... + """, + "Variable", + id="for_loop_variable", + ), + pytest.param( + """ + [łoł + for łol in os.listdir(".") #@ + ] + """, + "Variable", + id="inline_for_loop_variable", + ), + ], + ) + def test_assignname( + self, + code: str, + assign_type: str, + ): + """Variables defined no matter where, should be checked for non ascii""" + assign_node = astroid.extract_node(code) + + if not isinstance(assign_node, nodes.AssignName): + # For some elements we can't directly extract the assign + # node, so we have to manually look in the children for it + for child in assign_node.get_children(): + if isinstance(child, nodes.AssignName): + assign_node = child + break + + # Just to make sure we found the correct node + assert isinstance(assign_node, nodes.AssignName) + + with self.assertAddsMessages( + pylint.testutils.MessageTest( + msg_id=self.EXPECTED_MSG, + node=assign_node, + args=(assign_type, "łol"), + confidence=pylint.interfaces.HIGH, + ), + ignore_position=True, + ): + self.checker.visit_assignname(assign_node) + + def test_class_definition(self): + node = astroid.extract_node( + """ + class FooBär: #@ + ... + """ + ) + assert isinstance(node, nodes.ClassDef) + + with self.assertAddsMessages( + pylint.testutils.MessageTest( + msg_id=self.EXPECTED_MSG, + node=node, + args=("Class", "FooBär"), + confidence=pylint.interfaces.HIGH, + line=2, + col_offset=0, + # pylint: disable-next=fixme + # TODO: Maybe we have to select something different + # here, as line 3 is not that thing we expect + end_line=3, + end_col_offset=7, + ) + ): + self.checker.visit_classdef(node) + + def test_import_ignore_star(self): + """Special case from xyz import *, where '*' is not A-Za-z0-9 but still valid""" + node = astroid.parse("from urllib.parse import *") + + with self.assertAddsMessages(): + self.walk(node) diff --git a/tests/functional/n/non_ascii_name/__init__.py b/tests/functional/n/non_ascii_name/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py new file mode 100644 index 0000000000..ac51b9c4dc --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py @@ -0,0 +1,4 @@ +"""Assigment Expression as defined in https://www.python.org/dev/peps/pep-0572/""" + +if (loł := __name__) == "__main__": # [non-ascii-name] + print(loł) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.rc b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.rc new file mode 100644 index 0000000000..85fc502b37 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.8 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt new file mode 100644 index 0000000000..121321dbc1 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt @@ -0,0 +1 @@ +non-ascii-name:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class.py b/tests/functional/n/non_ascii_name/non_ascii_name_class.py new file mode 100644 index 0000000000..f2e68426a7 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class.py @@ -0,0 +1,17 @@ +""" Non ASCII char in class name """ +# pylint: disable=too-few-public-methods + + +class НoldIt: # [non-ascii-name] + """nice classs""" + + def public(self): + """do something""" + print(self) + + +def main(): + """Main function""" + # Usage should not raise a second error + foobar = НoldIt() + print(foobar) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class.txt new file mode 100644 index 0000000000..889d905c49 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class.txt @@ -0,0 +1 @@ +non-ascii-name:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py b/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py new file mode 100644 index 0000000000..07d95bba56 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py @@ -0,0 +1,25 @@ +"""Non ASCII name in class variable""" + + +class OkayIsh: + """Class docstring""" + + def public(self): + """Be public!""" + print(self) + + def __init__(self): + self.łoopback = "invalid" # [non-ascii-name] + + def foobar(self): + """do something""" + # Usage should not raise a second error + return self.łoopback + +def main(): + """main function""" + # Usage should not raise a second error + barrrr = OkayIsh() + barrrr.foobar() + test = barrrr.łoopback + print(test) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt new file mode 100644 index 0000000000..8d27e71eec --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt @@ -0,0 +1 @@ +non-ascii-name:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py b/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py new file mode 100644 index 0000000000..c3f96cadd9 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py @@ -0,0 +1,23 @@ +"""non ASCII name in global class variable/class constant""" + + +class OkayIsh: + """Class docstring""" + ŁOOPBACK = "invalid" # [non-ascii-name] + + + def more_public(self): + """yet another public method""" + print(self) + + def public(self): + """something public""" + print(self) + + + +def main(): + """Main func""" + # Usage should not raise a second error + foobar = OkayIsh.ŁOOPBACK + print(foobar) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt new file mode 100644 index 0000000000..0001318a89 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt @@ -0,0 +1 @@ +non-ascii-name:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_method.py b/tests/functional/n/non_ascii_name/non_ascii_name_class_method.py new file mode 100644 index 0000000000..ec05b4cf96 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class_method.py @@ -0,0 +1,18 @@ +"""Non ASCII char in classmethod""" + + +class OkayClass: + """We need a class docstring?""" + + def public(self): + """Say something""" + print(self) + + @classmethod + def umlaut_ä(cls): # [non-ascii-name] + """do something""" + return "ä" + + +# Usage should not raise a second error +OkayClass.umlaut_ä() diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt new file mode 100644 index 0000000000..b645bb3f19 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt @@ -0,0 +1 @@ +non-ascii-name:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_dict_kwargs.py b/tests/functional/n/non_ascii_name/non_ascii_name_dict_kwargs.py new file mode 100644 index 0000000000..5d7b4c7f37 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_dict_kwargs.py @@ -0,0 +1,13 @@ +""" +We don't expect this to give any errors! +""" + + +def okay(**kwargs): + """print kwargs""" + print(kwargs) + + +keyword_args = {"łol": "this would be hard to check against"} + +okay(**keyword_args) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py new file mode 100644 index 0000000000..59585645a7 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py @@ -0,0 +1,14 @@ +"""invalid ascii char in a for loop""" + +import os + + +def main(): + """main func""" + # +2: [non-ascii-name] + a_variable = "" + for łol in os.listdir("."): + # Usage should not raise a second error + a_variable += ( + f"{łol} " + ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt new file mode 100644 index 0000000000..1320b15089 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt @@ -0,0 +1 @@ +non-ascii-name:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_function.py new file mode 100644 index 0000000000..e3c558ea65 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.py @@ -0,0 +1,19 @@ +"""invalid ASCII char in a function definition""" +# pylint: disable=invalid-name + + +def sayHello(): + """Greetings""" + print("Hello, World!") + + +# +3: [non-ascii-name] + + +def sayНello(): + """From Russia with Love""" + print("Goodbye, World!") + + +# Usage should not raise a second error +sayНello() diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt new file mode 100644 index 0000000000..f793dcbde2 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt @@ -0,0 +1 @@ +non-ascii-name:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py new file mode 100644 index 0000000000..377bf865e6 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py @@ -0,0 +1,22 @@ +""" +non ascii variable defined in a function +""" + + +def okay( + just_some_thing_long_again: str, + lol_very_long_argument: str, + łol: str, # [non-ascii-name] +) -> bool: + """Be okay, yeah?""" + # Usage should not raise a second error + print(just_some_thing_long_again, lol_very_long_argument, łol) + return True + + +# Usage should raise a second error +okay( + "A VVVVVVVEEEERRRRRRRRRRYYYYYYYYYY LONG TIME ", + lol_very_long_argument="a", + łol="b", # [non-ascii-name] +) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc new file mode 100644 index 0000000000..67a28a36aa --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc @@ -0,0 +1,2 @@ +[testoptions] +max_pyver=3.8 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt new file mode 100644 index 0000000000..9866b040c0 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt @@ -0,0 +1,2 @@ +non-ascii-name:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character":HIGH +non-ascii-name:21:4:21:12::"Argument name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py new file mode 100644 index 0000000000..377bf865e6 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py @@ -0,0 +1,22 @@ +""" +non ascii variable defined in a function +""" + + +def okay( + just_some_thing_long_again: str, + lol_very_long_argument: str, + łol: str, # [non-ascii-name] +) -> bool: + """Be okay, yeah?""" + # Usage should not raise a second error + print(just_some_thing_long_again, lol_very_long_argument, łol) + return True + + +# Usage should raise a second error +okay( + "A VVVVVVVEEEERRRRRRRRRRYYYYYYYYYY LONG TIME ", + lol_very_long_argument="a", + łol="b", # [non-ascii-name] +) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.rc b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.rc new file mode 100644 index 0000000000..16b75eea75 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.9 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt new file mode 100644 index 0000000000..9866b040c0 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt @@ -0,0 +1,2 @@ +non-ascii-name:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character":HIGH +non-ascii-name:21:4:21:12::"Argument name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_as.py b/tests/functional/n/non_ascii_name/non_ascii_name_import_as.py new file mode 100644 index 0000000000..1803151d48 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_import_as.py @@ -0,0 +1,6 @@ +"""import non ascii alias""" +import os.path as łos # [non-ascii-name] + + +# Usage should not raise a second error +foo = łos.join("a", "b") diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt b/tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt new file mode 100644 index 0000000000..50226cb44c --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt @@ -0,0 +1 @@ +non-ascii-name:2:0:2:22::"Module name ""łos"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py b/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py new file mode 100644 index 0000000000..a17c28665f --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py @@ -0,0 +1,6 @@ +"""import as non ascii alias""" +from os.path import join as łos # [non-ascii-name] + + +# Usage should not raise a second error +foo = łos("a", "b") diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt b/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt new file mode 100644 index 0000000000..c8346a76df --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt @@ -0,0 +1 @@ +non-ascii-name:2:0:2:32::"Module name ""łos"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py new file mode 100644 index 0000000000..2d47e58c2d --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py @@ -0,0 +1,8 @@ +"""inline loop non ascii variable definition""" +import os + + +foo = [ + f"{łol} " + for łol in os.listdir(".") # [non-ascii-name] +] diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt new file mode 100644 index 0000000000..90219a2935 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt @@ -0,0 +1 @@ +non-ascii-name:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py new file mode 100644 index 0000000000..fbd382f41d --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py @@ -0,0 +1,15 @@ +""" +Defining non ASCII variables in a function call +""" + + +def okay(**kwargs): + """Print kwargs""" + print(kwargs) + + +okay( + a_long_attribute_that_is_very_okay=1, + b_belongs_to_yet_another_okay_attributed=2, + łol=3, # [non-ascii-name] +) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc new file mode 100644 index 0000000000..67a28a36aa --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc @@ -0,0 +1,2 @@ +[testoptions] +max_pyver=3.8 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt new file mode 100644 index 0000000000..b588a1b804 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt @@ -0,0 +1 @@ +non-ascii-name:14:4:14:10::"Argument name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py new file mode 100644 index 0000000000..fbd382f41d --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py @@ -0,0 +1,15 @@ +""" +Defining non ASCII variables in a function call +""" + + +def okay(**kwargs): + """Print kwargs""" + print(kwargs) + + +okay( + a_long_attribute_that_is_very_okay=1, + b_belongs_to_yet_another_okay_attributed=2, + łol=3, # [non-ascii-name] +) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.rc b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.rc new file mode 100644 index 0000000000..16b75eea75 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.9 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt new file mode 100644 index 0000000000..b588a1b804 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt @@ -0,0 +1 @@ +non-ascii-name:14:4:14:10::"Argument name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.py b/tests/functional/n/non_ascii_name/non_ascii_name_local.py new file mode 100644 index 0000000000..99423fdc8f --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.py @@ -0,0 +1,9 @@ +"""Using non ascii variables in local""" + + +def okay(): + """docstring""" + łol = "foo" # [non-ascii-name] + # Usage should not raise a second error + baring = łol + print(baring) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt new file mode 100644 index 0000000000..d26b0999f8 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt @@ -0,0 +1 @@ +non-ascii-name:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py new file mode 100644 index 0000000000..e6a2b80d85 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py @@ -0,0 +1,21 @@ +""" +Test for names within keyword and position only function +""" +# pylint: disable=unused-argument + + +def name( + some_thing_long_but_okay, + not_okay_łol, # [non-ascii-name] + not_okay_defaułt=None, # [non-ascii-name] + /, + p_or_kw_okay=None, + p_or_kw_not_økay=None, # [non-ascii-name] + *, + kw_arg_okay, + kw_arg_not_økay, # [non-ascii-name] +): + """ + Do something! + """ + return "Foobar" diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.rc b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.rc new file mode 100644 index 0000000000..85fc502b37 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.8 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt new file mode 100644 index 0000000000..ced7a401ee --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt @@ -0,0 +1,4 @@ +non-ascii-name:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character":HIGH +non-ascii-name:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character":HIGH +non-ascii-name:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character":HIGH +non-ascii-name:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py new file mode 100644 index 0000000000..9b10f1cd46 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py @@ -0,0 +1,17 @@ +"""static method with non ascii characters""" + + +class OkayClass: + """Class Docstring""" + + def public(self): + """Say it load""" + + @staticmethod + def umlaut_ä(): # [non-ascii-name] + """Say ä""" + return "ä" + + +# Usage should not raise a second error +OkayClass.umlaut_ä() diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt new file mode 100644 index 0000000000..f4765990ba --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt @@ -0,0 +1 @@ +non-ascii-name:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py new file mode 100644 index 0000000000..beccf4b9a9 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py @@ -0,0 +1,11 @@ +""" +Also variables defined in except can't contain non ascii chars +""" + + +try: + raise AttributeError("Test") + # +1: [non-ascii-name] +except AttributeError as łol: + # Usage should not raise a second error + foo = łol diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt new file mode 100644 index 0000000000..002f4057bc --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt @@ -0,0 +1 @@ +non-ascii-name:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.py b/tests/functional/n/non_ascii_name/non_ascii_name_variable.py new file mode 100644 index 0000000000..2994dfa475 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.py @@ -0,0 +1,9 @@ +""" +Simply variable test +""" +# pylint: disable=invalid-name + +# Test invalid variable name +łol = "Foobar" # [non-ascii-name] +# Usage should not raise a second error +łol += "-" # [non-ascii-name] diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt new file mode 100644 index 0000000000..fa3208c0a1 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt @@ -0,0 +1,2 @@ +non-ascii-name:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character":HIGH +non-ascii-name:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character":HIGH From 7c0411a83caccef2059580bbd195ec93ca1b0dcd Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Thu, 6 Jan 2022 18:54:49 +0100 Subject: [PATCH 02/16] split ``non-ascii-name`` into 3 different msgs - non-ascii-identifier (replaces non-ascii-name) - non-ascii-file-name (a warning) - non-ascii-module-import (only considering the namespace the import is imported in) --- CONTRIBUTORS.txt | 3 + ChangeLog | 8 + doc/whatsnew/2.13.rst | 9 ++ pylint/checkers/__init__.py | 9 +- pylint/checkers/base.py | 37 +++-- pylint/checkers/non_ascii_names.py | 136 +++++++++------- pylint/testutils/checker_test_case.py | 15 +- tests/checkers/unittest_non_ascii_name.py | 150 +++++++++++++++--- .../e/.#emacs_file_lock_redefined_conf.py | 2 +- .../e/.#emacs_file_lock_redefined_conf.txt | 3 +- ...ng_raises_doc_required_exc_inheritance.txt | 2 +- tests/functional/n/non/non_ascii_name.py | 4 +- tests/functional/n/non/non_ascii_name.rc | 3 - tests/functional/n/non/non_ascii_name.txt | 4 +- .../non/non_ascii_name_backward_test_code.py | 7 + .../n/non/non_ascii_name_backward_test_msg.py | 7 + .../functional/n/non_ascii_import/__init__.py | 0 tests/functional/n/non_ascii_import/foobar.py | 0 .../n/non_ascii_import/non_ascii_import.py | 12 ++ .../non_ascii_import_as_bad.py} | 2 +- .../non_ascii_import_as_bad.txt | 1 + .../non_ascii_import_as_okay.py | 12 ++ .../non_ascii_import_from_as.py} | 2 +- .../non_ascii_import_from_as.txt | 1 + .../non_ascii_name_lo\305\202.py" | 1 + .../non_ascii_name_lo\305\202.txt" | 1 + .../non_ascii_name_assignment_expressions.py | 2 +- .../non_ascii_name_assignment_expressions.txt | 2 +- .../n/non_ascii_name/non_ascii_name_class.txt | 1 - .../non_ascii_name_class_attribute.txt | 1 - .../non_ascii_name_class_constant.txt | 1 - .../non_ascii_name_class_method.txt | 1 - .../non_ascii_name/non_ascii_name_for_loop.py | 2 +- .../non_ascii_name_for_loop.txt | 2 +- .../non_ascii_name/non_ascii_name_function.py | 2 +- .../non_ascii_name_function.txt | 2 +- ..._ascii_name_function_argument_py37minus.rc | 2 - ...ascii_name_function_argument_py37minus.txt | 2 - ... non_ascii_name_function_argument_py38.py} | 4 +- .../non_ascii_name_function_argument_py38.rc | 3 + .../non_ascii_name_function_argument_py38.txt | 2 + ...n_ascii_name_function_argument_py39plus.py | 4 +- ..._ascii_name_function_argument_py39plus.txt | 4 +- .../non_ascii_name_import_as.txt | 1 - .../non_ascii_name_import_from_as.txt | 1 - .../non_ascii_name_inline_var.py | 2 +- .../non_ascii_name_inline_var.txt | 2 +- .../non_ascii_name_kwargs_py37minus.rc | 2 - .../non_ascii_name_kwargs_py37minus.txt | 1 - ...minus.py => non_ascii_name_kwargs_py38.py} | 2 +- .../non_ascii_name_kwargs_py38.rc | 3 + .../non_ascii_name_kwargs_py38.txt | 1 + .../non_ascii_name_kwargs_py39plus.py | 2 +- .../non_ascii_name_kwargs_py39plus.txt | 2 +- .../n/non_ascii_name/non_ascii_name_local.py | 2 +- .../n/non_ascii_name/non_ascii_name_local.txt | 2 +- .../non_ascii_name_pos_and_kwonly_function.py | 8 +- ...non_ascii_name_pos_and_kwonly_function.txt | 8 +- .../non_ascii_name_staticmethod.py | 2 +- .../non_ascii_name_staticmethod.txt | 2 +- .../non_ascii_name_try_except.py | 2 +- .../non_ascii_name_try_except.txt | 2 +- .../non_ascii_name/non_ascii_name_variable.py | 4 +- .../non_ascii_name_variable.txt | 4 +- .../n/non_ascii_name_class/__init__.py | 0 .../non_ascii_name_class.py | 2 +- .../non_ascii_name_class.txt | 1 + .../non_ascii_name_class_attribute.py | 2 +- .../non_ascii_name_class_attribute.txt | 1 + .../non_ascii_name_class_constant.py | 2 +- .../non_ascii_name_class_constant.txt | 1 + .../non_ascii_name_class_method.py | 2 +- .../non_ascii_name_class_method.txt | 1 + 73 files changed, 381 insertions(+), 154 deletions(-) delete mode 100644 tests/functional/n/non/non_ascii_name.rc create mode 100644 tests/functional/n/non/non_ascii_name_backward_test_code.py create mode 100644 tests/functional/n/non/non_ascii_name_backward_test_msg.py create mode 100644 tests/functional/n/non_ascii_import/__init__.py create mode 100644 tests/functional/n/non_ascii_import/foobar.py create mode 100644 tests/functional/n/non_ascii_import/non_ascii_import.py rename tests/functional/n/{non_ascii_name/non_ascii_name_import_as.py => non_ascii_import/non_ascii_import_as_bad.py} (65%) create mode 100644 tests/functional/n/non_ascii_import/non_ascii_import_as_bad.txt create mode 100644 tests/functional/n/non_ascii_import/non_ascii_import_as_okay.py rename tests/functional/n/{non_ascii_name/non_ascii_name_import_from_as.py => non_ascii_import/non_ascii_import_from_as.py} (60%) create mode 100644 tests/functional/n/non_ascii_import/non_ascii_import_from_as.txt create mode 100644 "tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.py" create mode 100644 "tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt rename tests/functional/n/non_ascii_name/{non_ascii_name_function_argument_py37minus.py => non_ascii_name_function_argument_py38.py} (84%) create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc delete mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt rename tests/functional/n/non_ascii_name/{non_ascii_name_kwargs_py37minus.py => non_ascii_name_kwargs_py38.py} (85%) create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt create mode 100644 tests/functional/n/non_ascii_name_class/__init__.py rename tests/functional/n/{non_ascii_name => non_ascii_name_class}/non_ascii_name_class.py (87%) create mode 100644 tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt rename tests/functional/n/{non_ascii_name => non_ascii_name_class}/non_ascii_name_class_attribute.py (88%) create mode 100644 tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt rename tests/functional/n/{non_ascii_name => non_ascii_name_class}/non_ascii_name_class_constant.py (88%) create mode 100644 tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt rename tests/functional/n/{non_ascii_name => non_ascii_name_class}/non_ascii_name_class_method.py (85%) create mode 100644 tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index eee4da9a43..aa4fb2e245 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -595,3 +595,6 @@ contributors: * Eero Vuojolahti: contributor * Kian-Meng, Ang: contributor + +* Carli* Freudenberg (CarliJoy): contributor + - Improve non-ascii-name checker diff --git a/ChangeLog b/ChangeLog index 2bf37a089a..6e83f6f7b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,14 @@ Release date: TBA Closes #5588 +* Add ``non-ascii-identifier`` as replacement ``non-ascii-name`` + to ensure really __all__ Python names are ASCII. + Checker now checks properly the names of imports (``non-ascii-module-import``) as + well for as of file names (``non-ascii-file-name``). + Non ASCII characters could be homoglyphs (look alike characters) and hard to + enter on a non specialized keyboard. + See `Confusable Characters in PEP 672 `_ + * When run in parallel mode ``pylint`` now pickles the data passed to subprocesses with the ``dill`` package. The ``dill`` package has therefore been added as a dependency. diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index c1b5922378..d338be05a4 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -14,8 +14,17 @@ New checkers Closes #5460 +* Add ``non-ascii-identifier`` as replacement ``non-ascii-name`` + to ensure really __all__ Python names are ASCII. + Checker now checks properly the names of imports (``non-ascii-module-import``) as + well for as of file names (``non-ascii-file-name``). + Non ASCII characters could be homoglyphs (look alike characters) and hard to + enter on a non specialized keyboard. + See `Confusable Characters in PEP 672 `_ + Removed checkers ================ +* ``non-ascii-name`` has replaced by ``non-ascii-identifier`` Extensions ========== diff --git a/pylint/checkers/__init__.py b/pylint/checkers/__init__.py index 273b085a05..b423c2dc93 100644 --- a/pylint/checkers/__init__.py +++ b/pylint/checkers/__init__.py @@ -39,7 +39,14 @@ 15: stdlib 16: python3 17: refactoring -18-50: not yet used: reserved for future internal checkers. +. +. +. +25: non-ascii-names +25-50: not yet used: reserved for future internal checkers. +This file is not updated. Use + script/get_unused_message_id_category.py +to get the next free checker id. 51-99: perhaps used: reserved for external checkers The raw_metrics checker has no number associated since it doesn't emit any diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 2f79f852e0..664a5bf69e 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -73,7 +73,7 @@ import itertools import re import sys -from typing import TYPE_CHECKING, Any, Dict, Iterator, Optional, Pattern, cast +from typing import TYPE_CHECKING, Any, Dict, Iterable, Iterator, Optional, Pattern, cast import astroid from astroid import nodes @@ -1719,7 +1719,31 @@ def _create_naming_options(): return tuple(name_options) -class NameChecker(_BasicChecker): +class NameCheckerHelper: + """Class containing functions required by NameChecker and NonAsciiNamesChecker""" + + def _check_name( + self, node_type: str, name: str, node: nodes.NodeNG, optional_kwarg: Any = None + ): + """Only Dummy function will be overwritten by implementing classes + + Note: kwarg arguments will be different in implementing classes + """ + raise NotImplementedError + + def _recursive_check_names(self, args: Iterable[nodes.AssignName]): + """check names in a possibly recursive list """ + for arg in args: + if isinstance(arg, nodes.AssignName): + self._check_name("argument", arg.name, arg) + else: + # pylint: disable-next=fixme + # TODO: Check if we can remove this if branch because of + # the up to date astroid version used + self._recursive_check_names(arg.elts) + + +class NameChecker(_BasicChecker, NameCheckerHelper): msgs = { "C0103": ( '%s name "%s" doesn\'t conform to %s', @@ -1979,14 +2003,6 @@ def visit_assignname(self, node: nodes.AssignName) -> None: else: self._check_name("class_attribute", node.name, node) - def _recursive_check_names(self, args): - """check names in a possibly recursive list """ - for arg in args: - if isinstance(arg, nodes.AssignName): - self._check_name("argument", arg.name, arg) - else: - self._recursive_check_names(arg.elts) - def _find_name_group(self, node_type): return self._name_group.get(node_type, node_type) @@ -2027,6 +2043,7 @@ def _name_disallowed_by_regex(self, name: str) -> bool: pattern.match(name) for pattern in self._bad_names_rgxs_compiled ) + # pylint: disable-next=arguments-renamed def _check_name(self, node_type, name, node, confidence=interfaces.HIGH): """check for a name using the type's regexp""" diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index 6438b8ca91..c283390b8f 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -12,10 +12,11 @@ import re import sys -from typing import Iterable, List, Optional, Union +from typing import Optional, Union from astroid import nodes +import pylint.checkers.base import pylint.checkers.utils from pylint import interfaces from pylint.constants import HUMAN_READABLE_TYPES @@ -43,7 +44,9 @@ class _AsciiOnlyCheckedNode(Protocol): _is_ascii_only: bool -class NonAsciiNamesChecker(pylint.checkers.BaseChecker): +class NonAsciiNamesChecker( + pylint.checkers.BaseChecker, pylint.checkers.base.NameCheckerHelper +): """A strict name checker only allowing ASCII If your programming guideline defines that you are programming in English, @@ -58,9 +61,36 @@ class NonAsciiNamesChecker(pylint.checkers.BaseChecker): priority = -1 msgs = { - "C0144": ( - '%s name "%s" contains a non-ASCII character, rename it or use an alias for import', - "non-ascii-name", + "C2401": ( + '%s name "%s" contains a non-ASCII character, rename it.', + "non-ascii-identifier", + ( + "Used when the name contains at least one non-ASCII unicode character." + "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" + " for a background why this could be bad." + ), + {"old_names": [("C0144", "non-ascii-name")]}, + ), + # First %s will always be "file" + "W2402": ( + '%s name "%s" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers!', + "non-ascii-file-name", + ( + # Some = PyCharm at the time of writing didn't display the non_ascii_name_loł + # files. Probably only a bug shows the problem quite good. + # That's also why this is a warning and not only a convention! + "Some editors don't support non-ASCII file names properly. " + "Even so Python supports UTF-8 files since Python 3.5 this isn't recommended for" + "interoperability. Further reading: \n" + "- https://www.python.org/dev/peps/pep-0489/#export-hook-name \n" + "- https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers\n" + "- https://bugs.python.org/issue20485\n" + ), + ), + # First %s will always be "module" + "C2403": ( + '%s name "%s" contains a non-ASCII character, use an ASCII-only alias for import.', + "non-ascii-module-import", ( "Used when the name contains at least one non-ASCII unicode character. " "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" @@ -81,18 +111,26 @@ def _raise_name_warning( node_type: str, name: str, ) -> None: - type_label = HUMAN_READABLE_TYPES[node_type] + type_label = HUMAN_READABLE_TYPES.get(node_type, node_type) args = (type_label.capitalize(), name) - self.add_message( - "non-ascii-name", node=node, args=args, confidence=interfaces.HIGH - ) + msg = "non-ascii-name" + + # Some node types have customized messages + if node_type == "file": + msg = "non-ascii-file-name" + elif node_type == "module": + msg = "non-ascii-module-import" + + self.add_message(msg, node=node, args=args, confidence=interfaces.HIGH) + # pylint: disable-next=arguments-renamed def _check_name( self, node_type: str, - names: Union[str, List[str]], + name: str, node: Union[nodes.NodeNG, _AsciiOnlyCheckedNode], + check_string: Optional[str] = None, ) -> None: """Check whether a name is using non-ASCII characters. @@ -100,46 +138,30 @@ def _check_name( determine if a node has been already checked, so we don't have to handle too many edge cases. """ - if not isinstance(names, list): - names = [names] current_state = getattr(node, "_is_ascii_only", True) - for name in names: - if name is None: - # For some nodes i.e. *kwargs from a dict, the name will be empty - continue - if not ( - Py37Str(name).isascii() - and self._non_ascii_rgx_compiled.match(name) is None - ): - # Note that we require the `.isascii` method as it is fast and - # handles the complexities of unicode, so we can use simple regex. - self._raise_name_warning(node, node_type, name) - current_state = False - node._is_ascii_only = current_state # pylint: disable=protected-access + if name is None: + # For some nodes i.e. *kwargs from a dict, the name will be empty + return - def _recursive_check_names(self, args: Iterable[nodes.AssignName]) -> None: - """check names in a possibly recursive list """ - for arg in args: - if isinstance(arg, nodes.AssignName): - self._check_name("argument", arg.name, arg) - else: - # pylint: disable-next=fixme - # TODO: Check if we can remove this branch because of - # the up to date astroid version used - self._recursive_check_names(arg.elts) + if check_string is None: + check_string = name + + if not ( + Py37Str(check_string).isascii() + and self._non_ascii_rgx_compiled.match(check_string) is None + ): + # Note that we require the `.isascii` method as it is fast and + # handles the complexities of unicode, so we can use simple regex. + self._raise_name_warning(node, node_type, name) + current_state = False + + node._is_ascii_only = current_state # pylint: disable=protected-access @pylint.checkers.utils.check_messages("non-ascii-name") def visit_module(self, node: nodes.Module) -> None: - # pylint: disable-next=fixme - # TODO check how the node name is defined when calling the real checker - # in the test using the astroid manager the node.name attribute corresponds - # to the filename -> so we always have ".py" as result of the following - # function. - # It would be nice if we could check for an ASCII filename, if not done - # already by other checkers... - self._check_name("module", node.name.split(".")[-1], node) + self._check_name("file", node.name.split(".")[-1], node) @pylint.checkers.utils.check_messages("non-ascii-name") def visit_functiondef( @@ -203,22 +225,25 @@ def visit_classdef(self, node: nodes.ClassDef) -> None: if not any(node.instance_attr_ancestors(attr)): self._check_name("attr", attr, anodes[0]) - @staticmethod - def _get_module_names(module_name: str, alias: Optional[str] = None) -> List[str]: - result = module_name.split(".") - if alias is not None: - result.append(alias) - return result - def _check_module_import( self, node: Union[nodes.ImportFrom, nodes.Import], is_import_from: bool = False ): - names = [] for module_name, alias in node.names: - names += self._get_module_names(module_name, alias) - if not (is_import_from and names == ["*"]): - # Ignore ``from xyz import *`` - self._check_name("module", names, node) + if alias: + name = alias + else: + if is_import_from and module_name == "*": + # Ignore ``from xyz import *`` + continue + name = module_name + + if is_import_from or alias: + self._check_name("module", name, node) + else: + # Normal module import can contain "." for which we don't want to check + self._check_name( + "module", name, node, check_string=name.replace(".", "") + ) @pylint.checkers.utils.check_messages("non-ascii-name") def visit_import(self, node: nodes.Import) -> None: @@ -226,7 +251,6 @@ def visit_import(self, node: nodes.Import) -> None: @pylint.checkers.utils.check_messages("non-ascii-name") def visit_importfrom(self, node: nodes.ImportFrom) -> None: - self._check_name("module", self._get_module_names(node.modname), node) self._check_module_import(node, is_import_from=True) @pylint.checkers.utils.check_messages("non-ascii-name") diff --git a/pylint/testutils/checker_test_case.py b/pylint/testutils/checker_test_case.py index af72136a9d..5fabf97c5b 100644 --- a/pylint/testutils/checker_test_case.py +++ b/pylint/testutils/checker_test_case.py @@ -32,12 +32,18 @@ def assertNoMessages(self): yield @contextlib.contextmanager - def assertAddsMessages(self, *messages: MessageTest) -> Generator[None, None, None]: + def assertAddsMessages( + self, *messages: MessageTest, ignore_position: bool = False + ) -> Generator[None, None, None]: """Assert that exactly the given method adds the given messages. The list of messages must exactly match *all* the messages added by the method. Additionally, we check to see whether the args in each message can actually be substituted into the message string. + + Using the keyword argument `ignore_position`, all checks for position + arguments (line, col_offset, ...) will be skipped. This can be used to + just test messages for the correct node. """ yield got = self.linter.release_messages() @@ -53,10 +59,15 @@ def assertAddsMessages(self, *messages: MessageTest) -> Generator[None, None, No for expected_msg, gotten_msg in zip(messages, got): assert expected_msg.msg_id == gotten_msg.msg_id, msg - assert expected_msg.line == gotten_msg.line, msg assert expected_msg.node == gotten_msg.node, msg assert expected_msg.args == gotten_msg.args, msg assert expected_msg.confidence == gotten_msg.confidence, msg + + if ignore_position: + # Do not check for line, col_offset etc... + continue + + assert expected_msg.line == gotten_msg.line, msg assert expected_msg.col_offset == gotten_msg.col_offset, msg if PY38_PLUS: # pylint: disable=fixme diff --git a/tests/checkers/unittest_non_ascii_name.py b/tests/checkers/unittest_non_ascii_name.py index 499114a86e..a7f6393f4a 100644 --- a/tests/checkers/unittest_non_ascii_name.py +++ b/tests/checkers/unittest_non_ascii_name.py @@ -1,4 +1,5 @@ import sys +from typing import Iterable, Optional import astroid import pytest @@ -13,21 +14,6 @@ class TestNonAsciiChecker(pylint.testutils.CheckerTestCase): CHECKER_CLASS = pylint.checkers.non_ascii_names.NonAsciiNamesChecker checker: pylint.checkers.non_ascii_names.NonAsciiNamesChecker - EXPECTED_MSG = "non-ascii-name" - - def test_get_module_names(self): - """The static function _get_modules_names shall resolve module names correctly""" - assert self.CHECKER_CLASS._get_module_names("foo.bar.test") == [ - "foo", - "bar", - "test", - ] - assert self.CHECKER_CLASS._get_module_names("foo.bar", "test") == [ - "foo", - "bar", - "test", - ] - @pytest.mark.skipif( sys.version_info < (3, 8), reason="requires python3.8 or higher" ) @@ -58,25 +44,25 @@ def name( with self.assertAddsMessages( pylint.testutils.MessageTest( - msg_id=self.EXPECTED_MSG, + msg_id="non-ascii-name", node=posargs[1], args=("Argument", "not_økay"), confidence=pylint.interfaces.HIGH, ), pylint.testutils.MessageTest( - msg_id=self.EXPECTED_MSG, + msg_id="non-ascii-name", node=posargs[2], args=("Argument", "not_okay_defaułt"), confidence=pylint.interfaces.HIGH, ), pylint.testutils.MessageTest( - msg_id=self.EXPECTED_MSG, + msg_id="non-ascii-name", node=args[1], args=("Argument", "p_or_kw_not_økay"), confidence=pylint.interfaces.HIGH, ), pylint.testutils.MessageTest( - msg_id=self.EXPECTED_MSG, + msg_id="non-ascii-name", node=kwargs[1], args=("Argument", "kw_arg_not_økay"), confidence=pylint.interfaces.HIGH, @@ -161,7 +147,7 @@ def test_assignname( with self.assertAddsMessages( pylint.testutils.MessageTest( - msg_id=self.EXPECTED_MSG, + msg_id="non-ascii-name", node=assign_node, args=(assign_type, "łol"), confidence=pylint.interfaces.HIGH, @@ -181,7 +167,7 @@ class FooBär: #@ with self.assertAddsMessages( pylint.testutils.MessageTest( - msg_id=self.EXPECTED_MSG, + msg_id="non-ascii-name", node=node, args=("Class", "FooBär"), confidence=pylint.interfaces.HIGH, @@ -202,3 +188,125 @@ def test_import_ignore_star(self): with self.assertAddsMessages(): self.walk(node) + + @pytest.mark.parametrize( + "import_statement, wrong_name", + [ + pytest.param("import fürimma", "fürimma", id="bad_single_main_module"), + pytest.param( + "import fürimma as okay", + None, + id="bad_single_main_module_with_okay_alias", + ), + pytest.param( + "import fürimma, pathlib", + "fürimma", + id="bad_single_main_module_with_stdlib_import", + ), + pytest.param( + "import pathlib, os, foobar, fürimma", + "fürimma", + id="stdlib_with_bad_single_main_module", + ), + pytest.param( + "import pathlib, os, foobar, sys as systëm", + "systëm", + id="stdlib_with_bad_alias", + ), + pytest.param( + "import fürimma as okay, pathlib", + None, + id="bad_single_main_module_with_okay_alias_with_stdlib_import", + ), + pytest.param( + "import fürimma.submodule", "fürimma.submodule", id="bad_main_module" + ), + pytest.param( + "import fürimma.submodule as submodule", + None, + id="bad_main_module_with_okay_alias", + ), + pytest.param( + "import main_module.fürimma", "main_module.fürimma", id="bad_submodule" + ), + pytest.param( + "import main_module.fürimma as okay", + None, + id="bad_submodule_with_okay_alias", + ), + pytest.param( + "import main_module.fürimma as not_økay", + "not_økay", + id="bad_submodule_with_bad_alias", + ), + pytest.param( + "from foo.bar import function", None, id="from_okay_module_import_okay" + ), + pytest.param( + "from foo.bär import function", None, id="from_bad_module_import_okay" + ), + pytest.param( + "from foo.bar import functiøn", + "functiøn", + id="from_okay_module_import_bad", + ), + pytest.param( + "from foo.bar import functiøn as function", + None, + id="from_okay_module_import_bad_as_good", + ), + pytest.param( + "from foo.bär import functiøn as function", + None, + id="from_bad_module_import_bad_as_good", + ), + pytest.param( + "from foo.bar import functiøn as føl", + "føl", + id="from_okay_module_import_bad_as_bad", + ), + pytest.param( + "from foo.bar import functiøn as good, bäd", + "bäd", + id="from_okay_module_import_bad_as_good_and_bad", + ), + pytest.param( + "from foo.bar import functiøn as good, bäd", + "bäd", + id="from_okay_module_import_bad_as_good_and_bad", + ), + pytest.param( + "from foo.bar import functiøn as good, *", + # We still have functiøn within our namespace and could detect this + # But to do this properly we would need to check all `*` imports + # -> Too much efford! + "functiøn", + id="from_okay_module_import_bad_as_good_and_star", + marks=pytest.mark.xfail( + reason="We don't what is imported when using star" + ), + ), + ], + ) + def test_check_import(self, import_statement: str, wrong_name: Optional[str]): + """We expect that for everything that user can change there is a message""" + node = astroid.extract_node(f"{import_statement} #@") + + expected_msgs: Iterable[pylint.testutils.MessageTest] = tuple() + + if wrong_name: + expected_msgs = ( + pylint.testutils.MessageTest( + msg_id="non-ascii-module-import", + node=node, + args=("Module", wrong_name), + confidence=pylint.interfaces.HIGH, + ), + ) + with self.assertAddsMessages(*expected_msgs, ignore_position=True): + if import_statement.startswith("from"): + assert isinstance(node, nodes.ImportFrom) + self.checker.visit_importfrom(node) + else: + assert isinstance(node, nodes.Import) + self.checker.visit_import(node) diff --git a/tests/functional/e/.#emacs_file_lock_redefined_conf.py b/tests/functional/e/.#emacs_file_lock_redefined_conf.py index 4b26dee73a..2c31f21ea7 100644 --- a/tests/functional/e/.#emacs_file_lock_redefined_conf.py +++ b/tests/functional/e/.#emacs_file_lock_redefined_conf.py @@ -1,3 +1,3 @@ -# [invalid-name] +# [invalid-name, non-ascii-file-name] # The name is invalid and we should analyse this file # as ignore-patterns is redefined in the configuration diff --git a/tests/functional/e/.#emacs_file_lock_redefined_conf.txt b/tests/functional/e/.#emacs_file_lock_redefined_conf.txt index 52050dcc84..4b8376e02d 100644 --- a/tests/functional/e/.#emacs_file_lock_redefined_conf.txt +++ b/tests/functional/e/.#emacs_file_lock_redefined_conf.txt @@ -1 +1,2 @@ -invalid-name:1:0:None:None::Module name "#emacs_file_lock_redefined_conf" doesn't conform to snake_case naming style:HIGH +invalid-name:1:0:None:None::"Module name ""#emacs_file_lock_redefined_conf"" doesn't conform to snake_case naming style":HIGH +non-ascii-file-name:1:0:None:None::"File name ""#emacs_file_lock_redefined_conf"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers!":HIGH diff --git a/tests/functional/ext/docparams/raise/missing_raises_doc_required_exc_inheritance.txt b/tests/functional/ext/docparams/raise/missing_raises_doc_required_exc_inheritance.txt index 411cb77d5c..e566c8a856 100644 --- a/tests/functional/ext/docparams/raise/missing_raises_doc_required_exc_inheritance.txt +++ b/tests/functional/ext/docparams/raise/missing_raises_doc_required_exc_inheritance.txt @@ -1 +1 @@ -missing-raises-doc:12:0:18:25:test_find_missing_raise_for_parent:"""NameError""" not documented as being raised:UNDEFINED +missing-raises-doc:12:0:18:25:test_find_missing_raise_for_parent:"""NameError"" not documented as being raised":UNDEFINED diff --git a/tests/functional/n/non/non_ascii_name.py b/tests/functional/n/non/non_ascii_name.py index 276a23f753..f90e449392 100644 --- a/tests/functional/n/non/non_ascii_name.py +++ b/tests/functional/n/non/non_ascii_name.py @@ -1,6 +1,6 @@ """ Tests for non-ascii-name checker. """ -áéíóú = 4444 # [non-ascii-name] +áéíóú = 4444 # [non-ascii-identifier] -def úóíéá(): # [non-ascii-name] +def úóíéá(): # [non-ascii-identifier] """yo""" diff --git a/tests/functional/n/non/non_ascii_name.rc b/tests/functional/n/non/non_ascii_name.rc deleted file mode 100644 index ff09ea1f60..0000000000 --- a/tests/functional/n/non/non_ascii_name.rc +++ /dev/null @@ -1,3 +0,0 @@ -[testoptions] -# This test cannot run on Windows due to Unicode error formatting. -exclude_platforms=win32 diff --git a/tests/functional/n/non/non_ascii_name.txt b/tests/functional/n/non/non_ascii_name.txt index ba5338bb96..5fd5f7c461 100644 --- a/tests/functional/n/non/non_ascii_name.txt +++ b/tests/functional/n/non/non_ascii_name.txt @@ -1,2 +1,2 @@ -non-ascii-name:3:0:3:10::"Constant name ""áéíóú"" contains a non-ASCII unicode character":HIGH -non-ascii-name:5:0:6:12:úóíéá:"Function name ""úóíéá"" contains a non-ASCII unicode character":HIGH +non-ascii-identifier:3:0:3:10::"Variable name ""áéíóú"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:5:0:6:12:úóíéá:"Function name ""úóíéá"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non/non_ascii_name_backward_test_code.py b/tests/functional/n/non/non_ascii_name_backward_test_code.py new file mode 100644 index 0000000000..c26a9333a2 --- /dev/null +++ b/tests/functional/n/non/non_ascii_name_backward_test_code.py @@ -0,0 +1,7 @@ +""" Tests for non-ascii-name checker working as expected """ +# pylint: disable=C0144, use-symbolic-message-instead + +áéíóú = 4444 + +def úóíéá(): + """yo""" diff --git a/tests/functional/n/non/non_ascii_name_backward_test_msg.py b/tests/functional/n/non/non_ascii_name_backward_test_msg.py new file mode 100644 index 0000000000..7caee6210f --- /dev/null +++ b/tests/functional/n/non/non_ascii_name_backward_test_msg.py @@ -0,0 +1,7 @@ +""" Tests for non-ascii-name checker working as expected """ +# pylint: disable=non-ascii-name + +áéíóú = 4444 + +def úóíéá(): + """yo""" diff --git a/tests/functional/n/non_ascii_import/__init__.py b/tests/functional/n/non_ascii_import/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/functional/n/non_ascii_import/foobar.py b/tests/functional/n/non_ascii_import/foobar.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/functional/n/non_ascii_import/non_ascii_import.py b/tests/functional/n/non_ascii_import/non_ascii_import.py new file mode 100644 index 0000000000..26ca724934 --- /dev/null +++ b/tests/functional/n/non_ascii_import/non_ascii_import.py @@ -0,0 +1,12 @@ +"""Test that invalid module name imports causes correct error""" +# pylint: disable=import-error, wrong-import-position +import sys +import os + +# allow module imports to test that this is indeed a valid python file +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.dirname(SCRIPT_DIR)) + +import non_ascii_name_loł as ok + +print(ok) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_as.py b/tests/functional/n/non_ascii_import/non_ascii_import_as_bad.py similarity index 65% rename from tests/functional/n/non_ascii_name/non_ascii_name_import_as.py rename to tests/functional/n/non_ascii_import/non_ascii_import_as_bad.py index 1803151d48..df392961f4 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_import_as.py +++ b/tests/functional/n/non_ascii_import/non_ascii_import_as_bad.py @@ -1,5 +1,5 @@ """import non ascii alias""" -import os.path as łos # [non-ascii-name] +import os.path as łos # [non-ascii-module-import] # Usage should not raise a second error diff --git a/tests/functional/n/non_ascii_import/non_ascii_import_as_bad.txt b/tests/functional/n/non_ascii_import/non_ascii_import_as_bad.txt new file mode 100644 index 0000000000..595d387f71 --- /dev/null +++ b/tests/functional/n/non_ascii_import/non_ascii_import_as_bad.txt @@ -0,0 +1 @@ +non-ascii-module-import:2:0:2:22::"Module name ""łos"" contains a non-ASCII character, use an ASCII-only alias for import.":HIGH diff --git a/tests/functional/n/non_ascii_import/non_ascii_import_as_okay.py b/tests/functional/n/non_ascii_import/non_ascii_import_as_okay.py new file mode 100644 index 0000000000..35f8513fa9 --- /dev/null +++ b/tests/functional/n/non_ascii_import/non_ascii_import_as_okay.py @@ -0,0 +1,12 @@ +"""Test that invalid module name do not cause errors when using an alias""" +# pylint: disable=import-error, wrong-import-position +import sys +import os + +# allow module imports to test that this is indeed a valid python file +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.dirname(SCRIPT_DIR)) + +import non_ascii_name_loł as foobar + +print(foobar) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py b/tests/functional/n/non_ascii_import/non_ascii_import_from_as.py similarity index 60% rename from tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py rename to tests/functional/n/non_ascii_import/non_ascii_import_from_as.py index a17c28665f..68beba0ec6 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.py +++ b/tests/functional/n/non_ascii_import/non_ascii_import_from_as.py @@ -1,5 +1,5 @@ """import as non ascii alias""" -from os.path import join as łos # [non-ascii-name] +from os.path import join as łos # [non-ascii-module-import] # Usage should not raise a second error diff --git a/tests/functional/n/non_ascii_import/non_ascii_import_from_as.txt b/tests/functional/n/non_ascii_import/non_ascii_import_from_as.txt new file mode 100644 index 0000000000..58daa481ba --- /dev/null +++ b/tests/functional/n/non_ascii_import/non_ascii_import_from_as.txt @@ -0,0 +1 @@ +non-ascii-module-import:2:0:2:32::"Module name ""łos"" contains a non-ASCII character, use an ASCII-only alias for import.":HIGH diff --git "a/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.py" "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.py" new file mode 100644 index 0000000000..bc59418e1e --- /dev/null +++ "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.py" @@ -0,0 +1 @@ +# [non-ascii-file-name] diff --git "a/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" new file mode 100644 index 0000000000..77ed29b510 --- /dev/null +++ "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" @@ -0,0 +1 @@ +non-ascii-file-name:1:0:None:None::"File name ""non_ascii_name_loł"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers!":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py index ac51b9c4dc..f11057e8b6 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py @@ -1,4 +1,4 @@ """Assigment Expression as defined in https://www.python.org/dev/peps/pep-0572/""" -if (loł := __name__) == "__main__": # [non-ascii-name] +if (loł := __name__) == "__main__": # [non-ascii-identifier] print(loł) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt index 121321dbc1..5258d3a557 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt @@ -1 +1 @@ -non-ascii-name:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character":HIGH +non-ascii-identifier:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class.txt deleted file mode 100644 index 889d905c49..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt deleted file mode 100644 index 8d27e71eec..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt deleted file mode 100644 index 0001318a89..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt b/tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt deleted file mode 100644 index b645bb3f19..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class_method.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py index 59585645a7..e9b2dc8316 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py @@ -5,7 +5,7 @@ def main(): """main func""" - # +2: [non-ascii-name] + # +2: [non-ascii-identifier] a_variable = "" for łol in os.listdir("."): # Usage should not raise a second error diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt index 1320b15089..873e61099f 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt @@ -1 +1 @@ -non-ascii-name:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_function.py index e3c558ea65..514757c38b 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.py @@ -7,7 +7,7 @@ def sayHello(): print("Hello, World!") -# +3: [non-ascii-name] +# +3: [non-ascii-identifier] def sayНello(): diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt index f793dcbde2..34c735861a 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt @@ -1 +1 @@ -non-ascii-name:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character":HIGH +non-ascii-identifier:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc deleted file mode 100644 index 67a28a36aa..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.8 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt deleted file mode 100644 index 9866b040c0..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.txt +++ /dev/null @@ -1,2 +0,0 @@ -non-ascii-name:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character":HIGH -non-ascii-name:21:4:21:12::"Argument name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py similarity index 84% rename from tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py rename to tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py index 377bf865e6..3c495fce89 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py37minus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py @@ -6,7 +6,7 @@ def okay( just_some_thing_long_again: str, lol_very_long_argument: str, - łol: str, # [non-ascii-name] + łol: str, # [non-ascii-identifier] ) -> bool: """Be okay, yeah?""" # Usage should not raise a second error @@ -18,5 +18,5 @@ def okay( okay( "A VVVVVVVEEEERRRRRRRRRRYYYYYYYYYY LONG TIME ", lol_very_long_argument="a", - łol="b", # [non-ascii-name] + łol="b", # [non-ascii-identifier] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.rc b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.rc new file mode 100644 index 0000000000..35b185fdbc --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.rc @@ -0,0 +1,3 @@ +[testoptions] +min_pyver=3.8 +max_pyver=3.9 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt new file mode 100644 index 0000000000..e29c6c6beb --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt @@ -0,0 +1,2 @@ +non-ascii-identifier:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:21:0:None:None::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py index 377bf865e6..3c495fce89 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py @@ -6,7 +6,7 @@ def okay( just_some_thing_long_again: str, lol_very_long_argument: str, - łol: str, # [non-ascii-name] + łol: str, # [non-ascii-identifier] ) -> bool: """Be okay, yeah?""" # Usage should not raise a second error @@ -18,5 +18,5 @@ def okay( okay( "A VVVVVVVEEEERRRRRRRRRRYYYYYYYYYY LONG TIME ", lol_very_long_argument="a", - łol="b", # [non-ascii-name] + łol="b", # [non-ascii-identifier] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt index 9866b040c0..b461762f6e 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt @@ -1,2 +1,2 @@ -non-ascii-name:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character":HIGH -non-ascii-name:21:4:21:12::"Argument name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:21:4:21:12::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt b/tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt deleted file mode 100644 index 50226cb44c..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_import_as.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:2:0:2:22::"Module name ""łos"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt b/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt deleted file mode 100644 index c8346a76df..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_import_from_as.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:2:0:2:32::"Module name ""łos"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py index 2d47e58c2d..003bf2e855 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py @@ -4,5 +4,5 @@ foo = [ f"{łol} " - for łol in os.listdir(".") # [non-ascii-name] + for łol in os.listdir(".") # [non-ascii-identifier] ] diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt index 90219a2935..960ad9ba5c 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt @@ -1 +1 @@ -non-ascii-name:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc deleted file mode 100644 index 67a28a36aa..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.8 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt deleted file mode 100644 index b588a1b804..0000000000 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.txt +++ /dev/null @@ -1 +0,0 @@ -non-ascii-name:14:4:14:10::"Argument name ""łol"" contains a non-ASCII character":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py similarity index 85% rename from tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py rename to tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py index fbd382f41d..4bbe38b5dc 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py37minus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py @@ -11,5 +11,5 @@ def okay(**kwargs): okay( a_long_attribute_that_is_very_okay=1, b_belongs_to_yet_another_okay_attributed=2, - łol=3, # [non-ascii-name] + łol=3, # [non-ascii-identifier] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.rc b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.rc new file mode 100644 index 0000000000..35b185fdbc --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.rc @@ -0,0 +1,3 @@ +[testoptions] +min_pyver=3.8 +max_pyver=3.9 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt new file mode 100644 index 0000000000..bac06629b0 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt @@ -0,0 +1 @@ +non-ascii-identifier:14:0:None:None::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py index fbd382f41d..4bbe38b5dc 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py @@ -11,5 +11,5 @@ def okay(**kwargs): okay( a_long_attribute_that_is_very_okay=1, b_belongs_to_yet_another_okay_attributed=2, - łol=3, # [non-ascii-name] + łol=3, # [non-ascii-identifier] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt index b588a1b804..0dc5db52a2 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt @@ -1 +1 @@ -non-ascii-name:14:4:14:10::"Argument name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:14:4:14:10::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.py b/tests/functional/n/non_ascii_name/non_ascii_name_local.py index 99423fdc8f..1f7bd6cb56 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_local.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.py @@ -3,7 +3,7 @@ def okay(): """docstring""" - łol = "foo" # [non-ascii-name] + łol = "foo" # [non-ascii-identifier] # Usage should not raise a second error baring = łol print(baring) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt index d26b0999f8..5833bcdbc5 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt @@ -1 +1 @@ -non-ascii-name:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py index e6a2b80d85..d74c2bbdde 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py @@ -6,14 +6,14 @@ def name( some_thing_long_but_okay, - not_okay_łol, # [non-ascii-name] - not_okay_defaułt=None, # [non-ascii-name] + not_okay_łol, # [non-ascii-identifier] + not_okay_defaułt=None, # [non-ascii-identifier] /, p_or_kw_okay=None, - p_or_kw_not_økay=None, # [non-ascii-name] + p_or_kw_not_økay=None, # [non-ascii-identifier] *, kw_arg_okay, - kw_arg_not_økay, # [non-ascii-name] + kw_arg_not_økay, # [non-ascii-identifier] ): """ Do something! diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt index ced7a401ee..2e96ba3209 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt @@ -1,4 +1,4 @@ -non-ascii-name:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character":HIGH -non-ascii-name:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character":HIGH -non-ascii-name:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character":HIGH -non-ascii-name:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character":HIGH +non-ascii-identifier:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py index 9b10f1cd46..83169be045 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py @@ -8,7 +8,7 @@ def public(self): """Say it load""" @staticmethod - def umlaut_ä(): # [non-ascii-name] + def umlaut_ä(): # [non-ascii-identifier] """Say ä""" return "ä" diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt index f4765990ba..0d2af83654 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt @@ -1 +1 @@ -non-ascii-name:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character":HIGH +non-ascii-identifier:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py index beccf4b9a9..2acaebfe43 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py @@ -5,7 +5,7 @@ try: raise AttributeError("Test") - # +1: [non-ascii-name] + # +1: [non-ascii-identifier] except AttributeError as łol: # Usage should not raise a second error foo = łol diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt index 002f4057bc..5edeb34fab 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt @@ -1 +1 @@ -non-ascii-name:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.py b/tests/functional/n/non_ascii_name/non_ascii_name_variable.py index 2994dfa475..3f613a7fe8 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_variable.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.py @@ -4,6 +4,6 @@ # pylint: disable=invalid-name # Test invalid variable name -łol = "Foobar" # [non-ascii-name] +łol = "Foobar" # [non-ascii-identifier] # Usage should not raise a second error -łol += "-" # [non-ascii-name] +łol += "-" # [non-ascii-identifier] diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt index fa3208c0a1..2e5645cc90 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt @@ -1,2 +1,2 @@ -non-ascii-name:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character":HIGH -non-ascii-name:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character":HIGH +non-ascii-identifier:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/__init__.py b/tests/functional/n/non_ascii_name_class/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py similarity index 87% rename from tests/functional/n/non_ascii_name/non_ascii_name_class.py rename to tests/functional/n/non_ascii_name_class/non_ascii_name_class.py index f2e68426a7..a5c77fc05f 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py @@ -2,7 +2,7 @@ # pylint: disable=too-few-public-methods -class НoldIt: # [non-ascii-name] +class НoldIt: # [non-ascii-identifier] """nice classs""" def public(self): diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt new file mode 100644 index 0000000000..280626012c --- /dev/null +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt @@ -0,0 +1 @@ +non-ascii-identifier:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py similarity index 88% rename from tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py rename to tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py index 07d95bba56..c256683225 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class_attribute.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py @@ -9,7 +9,7 @@ def public(self): print(self) def __init__(self): - self.łoopback = "invalid" # [non-ascii-name] + self.łoopback = "invalid" # [non-ascii-identifier] def foobar(self): """do something""" diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt new file mode 100644 index 0000000000..3afcf33325 --- /dev/null +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt @@ -0,0 +1 @@ +non-ascii-identifier:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py similarity index 88% rename from tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py rename to tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py index c3f96cadd9..5b861e832f 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class_constant.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py @@ -3,7 +3,7 @@ class OkayIsh: """Class docstring""" - ŁOOPBACK = "invalid" # [non-ascii-name] + ŁOOPBACK = "invalid" # [non-ascii-identifier] def more_public(self): diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt new file mode 100644 index 0000000000..0fd49c6e01 --- /dev/null +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt @@ -0,0 +1 @@ +non-ascii-identifier:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character, rename it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_class_method.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py similarity index 85% rename from tests/functional/n/non_ascii_name/non_ascii_name_class_method.py rename to tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py index ec05b4cf96..47b20097cc 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_class_method.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py @@ -9,7 +9,7 @@ def public(self): print(self) @classmethod - def umlaut_ä(cls): # [non-ascii-name] + def umlaut_ä(cls): # [non-ascii-identifier] """do something""" return "ä" diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt new file mode 100644 index 0000000000..f69dbf7e80 --- /dev/null +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt @@ -0,0 +1 @@ +non-ascii-identifier:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, rename it.":HIGH From 54709b884ab1d60e9ea61e3db062dc94ae09af01 Mon Sep 17 00:00:00 2001 From: Kound Date: Fri, 7 Jan 2022 14:34:21 +0100 Subject: [PATCH 03/16] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniël van Noord <13665637+DanielNoord@users.noreply.github.com> --- ChangeLog | 9 +++++---- doc/whatsnew/2.13.rst | 11 ++++++----- pylint/checkers/base.py | 2 +- pylint/checkers/non_ascii_names.py | 18 +++++++++--------- tests/checkers/unittest_non_ascii_name.py | 2 +- .../e/.#emacs_file_lock_redefined_conf.txt | 2 +- tests/functional/n/non/non_ascii_name.txt | 4 ++-- .../n/non/non_ascii_name_backward_test_code.py | 2 +- .../n/non/non_ascii_name_backward_test_msg.py | 2 +- tests/functional/n/non_ascii_import/foobar.py | 0 .../non_ascii_name_lo\305\202.txt" | 2 +- .../non_ascii_name_assignment_expressions.txt | 2 +- .../non_ascii_name/non_ascii_name_for_loop.txt | 2 +- .../non_ascii_name/non_ascii_name_function.txt | 2 +- .../non_ascii_name_function_argument_py38.py | 2 ++ .../non_ascii_name_function_argument_py38.txt | 4 ++-- ...on_ascii_name_function_argument_py39plus.py | 3 +++ ...n_ascii_name_function_argument_py39plus.txt | 4 ++-- .../non_ascii_name_inline_var.txt | 2 +- .../non_ascii_name_kwargs_py38.py | 2 ++ .../non_ascii_name_kwargs_py38.txt | 2 +- .../non_ascii_name_kwargs_py39plus.py | 3 +++ .../non_ascii_name_kwargs_py39plus.txt | 2 +- .../n/non_ascii_name/non_ascii_name_local.txt | 2 +- .../non_ascii_name_pos_and_kwonly_function.txt | 8 ++++---- .../non_ascii_name_staticmethod.txt | 2 +- .../non_ascii_name_try_except.txt | 2 +- .../non_ascii_name/non_ascii_name_variable.txt | 4 ++-- .../non_ascii_name_class.txt | 2 +- .../non_ascii_name_class_attribute.txt | 2 +- .../non_ascii_name_class_constant.txt | 2 +- .../non_ascii_name_class_method.txt | 2 +- 32 files changed, 61 insertions(+), 49 deletions(-) delete mode 100644 tests/functional/n/non_ascii_import/foobar.py diff --git a/ChangeLog b/ChangeLog index 6e83f6f7b2..8f85c2889e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,10 +14,11 @@ Release date: TBA Closes #5588 -* Add ``non-ascii-identifier`` as replacement ``non-ascii-name`` - to ensure really __all__ Python names are ASCII. - Checker now checks properly the names of imports (``non-ascii-module-import``) as - well for as of file names (``non-ascii-file-name``). +* Renamed ``non-ascii-name`` to ``non-ascii-identifier`` and rewrote the checker. + It now ensures __all__ Python names are ASCII and also properly + checks the names of imports (``non-ascii-module-import``) as + well as file names (``non-ascii-file-name``) and emits their respective new warnings. + Non ASCII characters could be homoglyphs (look alike characters) and hard to enter on a non specialized keyboard. See `Confusable Characters in PEP 672 `_ diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index d338be05a4..f24c0b72ed 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -14,17 +14,18 @@ New checkers Closes #5460 -* Add ``non-ascii-identifier`` as replacement ``non-ascii-name`` - to ensure really __all__ Python names are ASCII. - Checker now checks properly the names of imports (``non-ascii-module-import``) as - well for as of file names (``non-ascii-file-name``). +* Renamed ``non-ascii-name`` to ``non-ascii-identifier`` and rewrote the checker. + It now ensures __all__ Python names are ASCII and also properly + checks the names of imports (``non-ascii-module-import``) as + well as file names (``non-ascii-file-name``) and emits their respective new warnings. + Non ASCII characters could be homoglyphs (look alike characters) and hard to enter on a non specialized keyboard. See `Confusable Characters in PEP 672 `_ Removed checkers ================ -* ``non-ascii-name`` has replaced by ``non-ascii-identifier`` +* ``non-ascii-name`` has been renamed to ``non-ascii-identifier`` Extensions ========== diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 664a5bf69e..77a97de9b9 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -1732,7 +1732,7 @@ def _check_name( raise NotImplementedError def _recursive_check_names(self, args: Iterable[nodes.AssignName]): - """check names in a possibly recursive list """ + """Check names in a possibly recursive list """ for arg in args: if isinstance(arg, nodes.AssignName): self._check_name("argument", arg.name, arg) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index c283390b8f..7d09b89fb5 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -62,10 +62,10 @@ class NonAsciiNamesChecker( msgs = { "C2401": ( - '%s name "%s" contains a non-ASCII character, rename it.', + '%s name "%s" contains a non-ASCII character, consider renaming it.', "non-ascii-identifier", ( - "Used when the name contains at least one non-ASCII unicode character." + "Used when the name contains at least one non-ASCII unicode character. " "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" " for a background why this could be bad." ), @@ -73,16 +73,16 @@ class NonAsciiNamesChecker( ), # First %s will always be "file" "W2402": ( - '%s name "%s" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers!', + '%s name "%s" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers.', "non-ascii-file-name", ( # Some = PyCharm at the time of writing didn't display the non_ascii_name_loł # files. Probably only a bug shows the problem quite good. # That's also why this is a warning and not only a convention! "Some editors don't support non-ASCII file names properly. " - "Even so Python supports UTF-8 files since Python 3.5 this isn't recommended for" - "interoperability. Further reading: \n" - "- https://www.python.org/dev/peps/pep-0489/#export-hook-name \n" + "Even so Python supports UTF-8 files since Python 3.5 this isn't recommended for " + "interoperability. Further reading:\n" + "- https://www.python.org/dev/peps/pep-0489/#export-hook-name\n" "- https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers\n" "- https://bugs.python.org/issue20485\n" ), @@ -173,17 +173,17 @@ def visit_functiondef( arguments = node.args # Check position only arguments - if arguments.posonlyargs is not None: + if arguments.posonlyargs: for pos_only_arg in arguments.posonlyargs: self._check_name("argument", pos_only_arg.name, pos_only_arg) # Check "normal" arguments args = arguments.args - if args is not None: + if args: self._recursive_check_names(args) # Check key word only arguments - if arguments.kwonlyargs is not None: + if arguments.kwonlyargs: for kwarg in arguments.kwonlyargs: self._check_name("argument", kwarg.name, kwarg) diff --git a/tests/checkers/unittest_non_ascii_name.py b/tests/checkers/unittest_non_ascii_name.py index a7f6393f4a..92e303435c 100644 --- a/tests/checkers/unittest_non_ascii_name.py +++ b/tests/checkers/unittest_non_ascii_name.py @@ -36,7 +36,7 @@ def name( """ ) assert isinstance(node, nodes.FunctionDef) - arguments: nodes.Arguments = node.args + arguments = node.args posargs = list(arguments.posonlyargs) args = list(arguments.args) diff --git a/tests/functional/e/.#emacs_file_lock_redefined_conf.txt b/tests/functional/e/.#emacs_file_lock_redefined_conf.txt index 4b8376e02d..79c4a53d1b 100644 --- a/tests/functional/e/.#emacs_file_lock_redefined_conf.txt +++ b/tests/functional/e/.#emacs_file_lock_redefined_conf.txt @@ -1,2 +1,2 @@ invalid-name:1:0:None:None::"Module name ""#emacs_file_lock_redefined_conf"" doesn't conform to snake_case naming style":HIGH -non-ascii-file-name:1:0:None:None::"File name ""#emacs_file_lock_redefined_conf"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers!":HIGH +non-ascii-file-name:1:0:None:None::"File name ""#emacs_file_lock_redefined_conf"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers.":HIGH diff --git a/tests/functional/n/non/non_ascii_name.txt b/tests/functional/n/non/non_ascii_name.txt index 5fd5f7c461..2551322d33 100644 --- a/tests/functional/n/non/non_ascii_name.txt +++ b/tests/functional/n/non/non_ascii_name.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:3:0:3:10::"Variable name ""áéíóú"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:5:0:6:12:úóíéá:"Function name ""úóíéá"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:3:0:3:10::"Variable name ""áéíóú"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:5:0:6:12:úóíéá:"Function name ""úóíéá"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non/non_ascii_name_backward_test_code.py b/tests/functional/n/non/non_ascii_name_backward_test_code.py index c26a9333a2..36a22ca521 100644 --- a/tests/functional/n/non/non_ascii_name_backward_test_code.py +++ b/tests/functional/n/non/non_ascii_name_backward_test_code.py @@ -1,4 +1,4 @@ -""" Tests for non-ascii-name checker working as expected """ +""" Tests for non-ascii-name checker working as expected after a major refactor """ # pylint: disable=C0144, use-symbolic-message-instead áéíóú = 4444 diff --git a/tests/functional/n/non/non_ascii_name_backward_test_msg.py b/tests/functional/n/non/non_ascii_name_backward_test_msg.py index 7caee6210f..e63f3a4db6 100644 --- a/tests/functional/n/non/non_ascii_name_backward_test_msg.py +++ b/tests/functional/n/non/non_ascii_name_backward_test_msg.py @@ -1,4 +1,4 @@ -""" Tests for non-ascii-name checker working as expected """ +""" Tests for non-ascii-name checker working as expected after a major refactor """ # pylint: disable=non-ascii-name áéíóú = 4444 diff --git a/tests/functional/n/non_ascii_import/foobar.py b/tests/functional/n/non_ascii_import/foobar.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git "a/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" index 77ed29b510..c30827ed3a 100644 --- "a/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" +++ "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" @@ -1 +1 @@ -non-ascii-file-name:1:0:None:None::"File name ""non_ascii_name_loł"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers!":HIGH +non-ascii-file-name:1:0:None:None::"File name ""non_ascii_name_loł"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt index 5258d3a557..98331a8e1d 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt @@ -1 +1 @@ -non-ascii-identifier:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt index 873e61099f..1ea25c2085 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt @@ -1 +1 @@ -non-ascii-identifier:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt index 34c735861a..d4bf53ba1e 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt @@ -1 +1 @@ -non-ascii-identifier:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py index 3c495fce89..c5ce8bf9b6 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py @@ -1,5 +1,7 @@ """ non ascii variable defined in a function + +This test is only for 3.8 as the starting column is incorrect """ diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt index e29c6c6beb..150fc0dccd 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:21:0:None:None::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:11:4:11:13:okay:"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:23:0:None:None::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py index 3c495fce89..69e0614ef5 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py @@ -1,5 +1,8 @@ """ non ascii variable defined in a function + +This test is 3.9+ and not using 'min_pyver_end_position' +as the starting column is also incorrect on < 3.9 """ diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt index b461762f6e..26a932c9ce 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:9:4:9:13:okay:"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:21:4:21:12::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:12:4:12:13:okay:"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:24:4:24:12::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt index 960ad9ba5c..410057395a 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt @@ -1 +1 @@ -non-ascii-identifier:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py index 4bbe38b5dc..0253ce0b99 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py @@ -1,5 +1,7 @@ """ Defining non ASCII variables in a function call + +This test is only for 3.8 as the starting column is incorrect """ diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt index bac06629b0..66e0bef6bd 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt @@ -1 +1 @@ -non-ascii-identifier:14:0:None:None::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:16:0:None:None::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py index 4bbe38b5dc..fbf2ab7491 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py @@ -1,5 +1,8 @@ """ Defining non ASCII variables in a function call + +This test is 3.9+ and not using 'min_pyver_end_position' +as the starting column is also incorrect on < 3.9 """ diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt index 0dc5db52a2..466e02d0f4 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt @@ -1 +1 @@ -non-ascii-identifier:14:4:14:10::"Argument name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:17:4:17:10::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt index 5833bcdbc5..c6172b985e 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt @@ -1 +1 @@ -non-ascii-identifier:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt index 2e96ba3209..2dc0a01f5a 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt @@ -1,4 +1,4 @@ -non-ascii-identifier:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt index 0d2af83654..1223b73146 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt @@ -1 +1 @@ -non-ascii-identifier:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt index 5edeb34fab..2af7c4588d 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt @@ -1 +1 @@ -non-ascii-identifier:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt index 2e5645cc90..5b73ae0b07 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH -non-ascii-identifier:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-identifier:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt index 280626012c..d8ce001182 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt @@ -1 +1 @@ -non-ascii-identifier:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt index 3afcf33325..49183b6f73 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt @@ -1 +1 @@ -non-ascii-identifier:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt index 0fd49c6e01..f403626d96 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt @@ -1 +1 @@ -non-ascii-identifier:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt index f69dbf7e80..68adb19047 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt @@ -1 +1 @@ -non-ascii-identifier:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, rename it.":HIGH +non-ascii-identifier:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, consider renaming it.":HIGH From c36c1eb15fa974417d2d18e4957a5ace27d242ed Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Fri, 7 Jan 2022 16:04:41 +0100 Subject: [PATCH 04/16] Keep the original message name --- ChangeLog | 2 +- doc/whatsnew/2.13.rst | 2 +- pylint/checkers/non_ascii_names.py | 4 ++-- tests/functional/n/non/non_ascii_name.py | 4 ++-- tests/functional/n/non/non_ascii_name.txt | 4 ++-- .../non_ascii_name_assignment_expressions.py | 2 +- .../non_ascii_name_assignment_expressions.txt | 2 +- .../non_ascii_name_decorator.py | 19 +++++++++++++++++++ .../non_ascii_name_decorator.rc | 2 ++ .../non_ascii_name_decorator.txt | 1 + .../non_ascii_name/non_ascii_name_for_loop.py | 2 +- .../non_ascii_name_for_loop.txt | 2 +- .../non_ascii_name/non_ascii_name_function.py | 2 +- .../non_ascii_name_function.txt | 2 +- .../non_ascii_name_function_argument_py38.py | 4 ++-- .../non_ascii_name_function_argument_py38.txt | 4 ++-- ...n_ascii_name_function_argument_py39plus.py | 4 ++-- ..._ascii_name_function_argument_py39plus.txt | 4 ++-- .../non_ascii_name_inline_var.py | 2 +- .../non_ascii_name_inline_var.txt | 2 +- .../non_ascii_name_kwargs_py38.py | 2 +- .../non_ascii_name_kwargs_py38.txt | 2 +- .../non_ascii_name_kwargs_py39plus.py | 2 +- .../non_ascii_name_kwargs_py39plus.txt | 2 +- .../n/non_ascii_name/non_ascii_name_local.py | 2 +- .../n/non_ascii_name/non_ascii_name_local.txt | 2 +- .../non_ascii_name_pos_and_kwonly_function.py | 8 ++++---- ...non_ascii_name_pos_and_kwonly_function.txt | 8 ++++---- .../non_ascii_name_staticmethod.py | 2 +- .../non_ascii_name_staticmethod.txt | 2 +- .../non_ascii_name_try_except.py | 2 +- .../non_ascii_name_try_except.txt | 2 +- .../non_ascii_name/non_ascii_name_variable.py | 4 ++-- .../non_ascii_name_variable.txt | 4 ++-- .../non_ascii_name_class.py | 2 +- .../non_ascii_name_class.txt | 2 +- .../non_ascii_name_class_attribute.py | 2 +- .../non_ascii_name_class_attribute.txt | 2 +- .../non_ascii_name_class_constant.py | 2 +- .../non_ascii_name_class_constant.txt | 2 +- .../non_ascii_name_class_method.py | 2 +- .../non_ascii_name_class_method.txt | 2 +- 42 files changed, 76 insertions(+), 54 deletions(-) create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_decorator.py create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_decorator.rc create mode 100644 tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt diff --git a/ChangeLog b/ChangeLog index 8f85c2889e..eeecd574ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,7 @@ Release date: TBA Closes #5588 -* Renamed ``non-ascii-name`` to ``non-ascii-identifier`` and rewrote the checker. +* Rewrote checker for ``non-ascii-name``. It now ensures __all__ Python names are ASCII and also properly checks the names of imports (``non-ascii-module-import``) as well as file names (``non-ascii-file-name``) and emits their respective new warnings. diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index f24c0b72ed..64137f0eed 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -14,7 +14,7 @@ New checkers Closes #5460 -* Renamed ``non-ascii-name`` to ``non-ascii-identifier`` and rewrote the checker. +* Rewrote Checker of ``non-ascii-name``. It now ensures __all__ Python names are ASCII and also properly checks the names of imports (``non-ascii-module-import``) as well as file names (``non-ascii-file-name``) and emits their respective new warnings. diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index 7d09b89fb5..bd245b8fa0 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -63,13 +63,13 @@ class NonAsciiNamesChecker( msgs = { "C2401": ( '%s name "%s" contains a non-ASCII character, consider renaming it.', - "non-ascii-identifier", + "non-ascii-name", ( "Used when the name contains at least one non-ASCII unicode character. " "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" " for a background why this could be bad." ), - {"old_names": [("C0144", "non-ascii-name")]}, + {"old_names": [("C0144", "old-non-ascii-name")]}, ), # First %s will always be "file" "W2402": ( diff --git a/tests/functional/n/non/non_ascii_name.py b/tests/functional/n/non/non_ascii_name.py index f90e449392..276a23f753 100644 --- a/tests/functional/n/non/non_ascii_name.py +++ b/tests/functional/n/non/non_ascii_name.py @@ -1,6 +1,6 @@ """ Tests for non-ascii-name checker. """ -áéíóú = 4444 # [non-ascii-identifier] +áéíóú = 4444 # [non-ascii-name] -def úóíéá(): # [non-ascii-identifier] +def úóíéá(): # [non-ascii-name] """yo""" diff --git a/tests/functional/n/non/non_ascii_name.txt b/tests/functional/n/non/non_ascii_name.txt index 2551322d33..2cda6962ef 100644 --- a/tests/functional/n/non/non_ascii_name.txt +++ b/tests/functional/n/non/non_ascii_name.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:3:0:3:10::"Variable name ""áéíóú"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:5:0:6:12:úóíéá:"Function name ""úóíéá"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:3:0:3:10::"Variable name ""áéíóú"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:5:0:6:12:úóíéá:"Function name ""úóíéá"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py index f11057e8b6..ac51b9c4dc 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.py @@ -1,4 +1,4 @@ """Assigment Expression as defined in https://www.python.org/dev/peps/pep-0572/""" -if (loł := __name__) == "__main__": # [non-ascii-identifier] +if (loł := __name__) == "__main__": # [non-ascii-name] print(loł) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt index 98331a8e1d..8a5acceb86 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_assignment_expressions.txt @@ -1 +1 @@ -non-ascii-identifier:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:3:4:3:8::"Variable name ""loł"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_decorator.py b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.py new file mode 100644 index 0000000000..06900ac7ca --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.py @@ -0,0 +1,19 @@ +""" +Ensure that also decorator calls caught correctly +Column and line not correctly detected with Python 3.8, so we +skip it and only test versions after that. +""" + + +def decoractor_func(*args, **kwargs): + """A docstring""" + return lambda x: f"Foobar {args} {kwargs}" + + +@decoractor_func( + aaaaaaaaaaaaaaaaaaalllllllooooooooooooonnngggggggggglllline=1, + normal=2, + fåling=3, # [non-ascii-name] +) +def a_function(): + """A docstring""" diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_decorator.rc b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.rc new file mode 100644 index 0000000000..16b75eea75 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.9 diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt new file mode 100644 index 0000000000..869d4e94a9 --- /dev/null +++ b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt @@ -0,0 +1 @@ +non-ascii-name:14:4:14:13:a_function:"Argument name ""fåling"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py index e9b2dc8316..59585645a7 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.py @@ -5,7 +5,7 @@ def main(): """main func""" - # +2: [non-ascii-identifier] + # +2: [non-ascii-name] a_variable = "" for łol in os.listdir("."): # Usage should not raise a second error diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt index 1ea25c2085..8995dc0eb3 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_for_loop.txt @@ -1 +1 @@ -non-ascii-identifier:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:10:8:10:12:main:"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_function.py index 514757c38b..e3c558ea65 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.py @@ -7,7 +7,7 @@ def sayHello(): print("Hello, World!") -# +3: [non-ascii-identifier] +# +3: [non-ascii-name] def sayНello(): diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt index d4bf53ba1e..949059da9e 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function.txt @@ -1 +1 @@ -non-ascii-identifier:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:13:0:15:28:sayНello:"Function name ""sayНello"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py index c5ce8bf9b6..a75e1c6b78 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.py @@ -8,7 +8,7 @@ def okay( just_some_thing_long_again: str, lol_very_long_argument: str, - łol: str, # [non-ascii-identifier] + łol: str, # [non-ascii-name] ) -> bool: """Be okay, yeah?""" # Usage should not raise a second error @@ -20,5 +20,5 @@ def okay( okay( "A VVVVVVVEEEERRRRRRRRRRYYYYYYYYYY LONG TIME ", lol_very_long_argument="a", - łol="b", # [non-ascii-identifier] + łol="b", # [non-ascii-name] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt index 150fc0dccd..7813364747 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py38.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:11:4:11:13:okay:"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:23:0:None:None::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:11:4:11:13:okay:"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:23:0:None:None::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py index 69e0614ef5..a2d87ac4d7 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.py @@ -9,7 +9,7 @@ def okay( just_some_thing_long_again: str, lol_very_long_argument: str, - łol: str, # [non-ascii-identifier] + łol: str, # [non-ascii-name] ) -> bool: """Be okay, yeah?""" # Usage should not raise a second error @@ -21,5 +21,5 @@ def okay( okay( "A VVVVVVVEEEERRRRRRRRRRYYYYYYYYYY LONG TIME ", lol_very_long_argument="a", - łol="b", # [non-ascii-identifier] + łol="b", # [non-ascii-name] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt index 26a932c9ce..0222308af6 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_function_argument_py39plus.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:12:4:12:13:okay:"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:24:4:24:12::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:12:4:12:13:okay:"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:24:4:24:12::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py index 003bf2e855..2d47e58c2d 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.py @@ -4,5 +4,5 @@ foo = [ f"{łol} " - for łol in os.listdir(".") # [non-ascii-identifier] + for łol in os.listdir(".") # [non-ascii-name] ] diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt index 410057395a..64515296b6 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_inline_var.txt @@ -1 +1 @@ -non-ascii-identifier:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:7:8:7:12::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py index 0253ce0b99..3c7b8c6835 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.py @@ -13,5 +13,5 @@ def okay(**kwargs): okay( a_long_attribute_that_is_very_okay=1, b_belongs_to_yet_another_okay_attributed=2, - łol=3, # [non-ascii-identifier] + łol=3, # [non-ascii-name] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt index 66e0bef6bd..b43189658f 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py38.txt @@ -1 +1 @@ -non-ascii-identifier:16:0:None:None::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:16:0:None:None::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py index fbf2ab7491..0dfceb38f4 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.py @@ -14,5 +14,5 @@ def okay(**kwargs): okay( a_long_attribute_that_is_very_okay=1, b_belongs_to_yet_another_okay_attributed=2, - łol=3, # [non-ascii-identifier] + łol=3, # [non-ascii-name] ) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt index 466e02d0f4..7595a9d082 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_kwargs_py39plus.txt @@ -1 +1 @@ -non-ascii-identifier:17:4:17:10::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:17:4:17:10::"Argument name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.py b/tests/functional/n/non_ascii_name/non_ascii_name_local.py index 1f7bd6cb56..99423fdc8f 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_local.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.py @@ -3,7 +3,7 @@ def okay(): """docstring""" - łol = "foo" # [non-ascii-identifier] + łol = "foo" # [non-ascii-name] # Usage should not raise a second error baring = łol print(baring) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt index c6172b985e..8e5e684fa9 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_local.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_local.txt @@ -1 +1 @@ -non-ascii-identifier:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:6:4:6:8:okay:"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py index d74c2bbdde..e6a2b80d85 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py @@ -6,14 +6,14 @@ def name( some_thing_long_but_okay, - not_okay_łol, # [non-ascii-identifier] - not_okay_defaułt=None, # [non-ascii-identifier] + not_okay_łol, # [non-ascii-name] + not_okay_defaułt=None, # [non-ascii-name] /, p_or_kw_okay=None, - p_or_kw_not_økay=None, # [non-ascii-identifier] + p_or_kw_not_økay=None, # [non-ascii-name] *, kw_arg_okay, - kw_arg_not_økay, # [non-ascii-identifier] + kw_arg_not_økay, # [non-ascii-name] ): """ Do something! diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt index 2dc0a01f5a..031cd9a390 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt @@ -1,4 +1,4 @@ -non-ascii-identifier:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py index 83169be045..9b10f1cd46 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.py @@ -8,7 +8,7 @@ def public(self): """Say it load""" @staticmethod - def umlaut_ä(): # [non-ascii-identifier] + def umlaut_ä(): # [non-ascii-name] """Say ä""" return "ä" diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt index 1223b73146..8bc3e8ce69 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_staticmethod.txt @@ -1 +1 @@ -non-ascii-identifier:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:11:4:13:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py index 2acaebfe43..beccf4b9a9 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.py @@ -5,7 +5,7 @@ try: raise AttributeError("Test") - # +1: [non-ascii-identifier] + # +1: [non-ascii-name] except AttributeError as łol: # Usage should not raise a second error foo = łol diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt index 2af7c4588d..f6b0d6c6c4 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_try_except.txt @@ -1 +1 @@ -non-ascii-identifier:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:9:0:11:14::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.py b/tests/functional/n/non_ascii_name/non_ascii_name_variable.py index 3f613a7fe8..2994dfa475 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_variable.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.py @@ -4,6 +4,6 @@ # pylint: disable=invalid-name # Test invalid variable name -łol = "Foobar" # [non-ascii-identifier] +łol = "Foobar" # [non-ascii-name] # Usage should not raise a second error -łol += "-" # [non-ascii-identifier] +łol += "-" # [non-ascii-name] diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt index 5b73ae0b07..5c142ee7e4 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_variable.txt @@ -1,2 +1,2 @@ -non-ascii-identifier:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-identifier:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:7:0:7:4::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:9:0:9:4::"Variable name ""łol"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py index a5c77fc05f..f2e68426a7 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py @@ -2,7 +2,7 @@ # pylint: disable=too-few-public-methods -class НoldIt: # [non-ascii-identifier] +class НoldIt: # [non-ascii-name] """nice classs""" def public(self): diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt index d8ce001182..101b534a0f 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt @@ -1 +1 @@ -non-ascii-identifier:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py index c256683225..07d95bba56 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.py @@ -9,7 +9,7 @@ def public(self): print(self) def __init__(self): - self.łoopback = "invalid" # [non-ascii-identifier] + self.łoopback = "invalid" # [non-ascii-name] def foobar(self): """do something""" diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt index 49183b6f73..7e3f5327c2 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_attribute.txt @@ -1 +1 @@ -non-ascii-identifier:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:12:8:12:22:OkayIsh.__init__:"Attribute name ""łoopback"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py index 5b861e832f..c3f96cadd9 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.py @@ -3,7 +3,7 @@ class OkayIsh: """Class docstring""" - ŁOOPBACK = "invalid" # [non-ascii-identifier] + ŁOOPBACK = "invalid" # [non-ascii-name] def more_public(self): diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt index f403626d96..26cf27ef78 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_constant.txt @@ -1 +1 @@ -non-ascii-identifier:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:6:4:6:13:OkayIsh:"Attribute name ""ŁOOPBACK"" contains a non-ASCII character, consider renaming it.":HIGH diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py index 47b20097cc..ec05b4cf96 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.py @@ -9,7 +9,7 @@ def public(self): print(self) @classmethod - def umlaut_ä(cls): # [non-ascii-identifier] + def umlaut_ä(cls): # [non-ascii-name] """do something""" return "ä" diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt index 68adb19047..8d7606e679 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class_method.txt @@ -1 +1 @@ -non-ascii-identifier:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:12:4:14:19:OkayClass.umlaut_ä:"Function name ""umlaut_ä"" contains a non-ASCII character, consider renaming it.":HIGH From 1a0fed34756c6d4b3e2acfc748c16c5cbcc37da4 Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Fri, 7 Jan 2022 16:36:45 +0100 Subject: [PATCH 05/16] simplify checker --- doc/whatsnew/2.13.rst | 1 - pylint/checkers/base.py | 48 ++---- pylint/checkers/base_checker.py | 32 +++- pylint/checkers/non_ascii_names.py | 142 ++++++------------ tests/checkers/unittest_non_ascii_name.py | 4 +- .../e/.#emacs_file_lock_redefined_conf.py | 2 +- .../e/.#emacs_file_lock_redefined_conf.txt | 1 - .../non_ascii_name_decorator.txt | 2 +- 8 files changed, 87 insertions(+), 145 deletions(-) diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index 64137f0eed..eb67dda694 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -25,7 +25,6 @@ New checkers Removed checkers ================ -* ``non-ascii-name`` has been renamed to ``non-ascii-identifier`` Extensions ========== diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 77a97de9b9..6af205ed66 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -73,14 +73,14 @@ import itertools import re import sys -from typing import TYPE_CHECKING, Any, Dict, Iterable, Iterator, Optional, Pattern, cast +from typing import TYPE_CHECKING, Any, Dict, Iterator, Optional, Pattern, cast import astroid from astroid import nodes -from pylint import checkers, constants, interfaces +from pylint import constants, interfaces from pylint import utils as lint_utils -from pylint.checkers import utils +from pylint.checkers import base_checker, utils from pylint.checkers.utils import ( infer_all, is_overload_stub, @@ -456,12 +456,7 @@ def x(self, value): self._x = value return False -class _BasicChecker(checkers.BaseChecker): - __implements__ = interfaces.IAstroidChecker - name = "basic" - - -class BasicErrorChecker(_BasicChecker): +class BasicErrorChecker(base_checker._BasicChecker): msgs = { "E0100": ( "__init__ method is a generator", @@ -937,7 +932,7 @@ def _check_redefinition(self, redeftype, node): ) -class BasicChecker(_BasicChecker): +class BasicChecker(base_checker._BasicChecker): """checks for : * doc strings * number of arguments, local variables, branches, returns and statements in @@ -1719,31 +1714,7 @@ def _create_naming_options(): return tuple(name_options) -class NameCheckerHelper: - """Class containing functions required by NameChecker and NonAsciiNamesChecker""" - - def _check_name( - self, node_type: str, name: str, node: nodes.NodeNG, optional_kwarg: Any = None - ): - """Only Dummy function will be overwritten by implementing classes - - Note: kwarg arguments will be different in implementing classes - """ - raise NotImplementedError - - def _recursive_check_names(self, args: Iterable[nodes.AssignName]): - """Check names in a possibly recursive list """ - for arg in args: - if isinstance(arg, nodes.AssignName): - self._check_name("argument", arg.name, arg) - else: - # pylint: disable-next=fixme - # TODO: Check if we can remove this if branch because of - # the up to date astroid version used - self._recursive_check_names(arg.elts) - - -class NameChecker(_BasicChecker, NameCheckerHelper): +class NameChecker(base_checker._NameCheckerBase): msgs = { "C0103": ( '%s name "%s" doesn\'t conform to %s', @@ -2043,7 +2014,6 @@ def _name_disallowed_by_regex(self, name: str) -> bool: pattern.match(name) for pattern in self._bad_names_rgxs_compiled ) - # pylint: disable-next=arguments-renamed def _check_name(self, node_type, name, node, confidence=interfaces.HIGH): """check for a name using the type's regexp""" @@ -2092,7 +2062,7 @@ def _name_became_keyword_in_version(name, rules): return None -class DocStringChecker(_BasicChecker): +class DocStringChecker(base_checker._BasicChecker): msgs = { "C0112": ( "Empty %s docstring", @@ -2258,7 +2228,7 @@ def _check_docstring( ) -class PassChecker(_BasicChecker): +class PassChecker(base_checker._BasicChecker): """check if the pass statement is really necessary""" msgs = { @@ -2300,7 +2270,7 @@ def _infer_dunder_doc_attribute(node): return docstring.value -class ComparisonChecker(_BasicChecker): +class ComparisonChecker(base_checker._BasicChecker): """Checks for comparisons - singleton comparison: 'expr == True', 'expr == False' and 'expr == None' diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 5a6efd20c2..1dc155be75 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -19,10 +19,11 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE import functools from inspect import cleandoc -from typing import Any, Optional +from typing import Any, Iterable, Optional from astroid import nodes +from pylint import interfaces from pylint.config import OptionsProviderMixIn from pylint.constants import _MSG_ORDER, WarningScope from pylint.exceptions import InvalidMessageError @@ -201,3 +202,32 @@ class BaseTokenChecker(BaseChecker): def process_tokens(self, tokens): """Should be overridden by subclasses.""" raise NotImplementedError() + + +class _BasicChecker(BaseChecker): + __implements__ = interfaces.IAstroidChecker + name = "basic" + + +class _NameCheckerBase(_BasicChecker): + """Class containing functions required by NameChecker and NonAsciiNameChecker""" + + def _check_name( + self, node_type: str, name: str, node: nodes.NodeNG, confidence=interfaces.HIGH + ): + """Only Dummy function will be overwritten by implementing classes + + Note: kwarg arguments will be different in implementing classes + """ + raise NotImplementedError + + def _recursive_check_names(self, args: Iterable[nodes.AssignName]): + """Check names in a possibly recursive list """ + for arg in args: + if isinstance(arg, nodes.AssignName): + self._check_name("argument", arg.name, arg) + else: + # pylint: disable-next=fixme + # TODO: Check if we can remove this if branch because of + # the up to date astroid version used + self._recursive_check_names(arg.elts) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index bd245b8fa0..f40fc744bf 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -10,23 +10,13 @@ The following checkers are intended to make users are aware of these issues. """ -import re import sys from typing import Optional, Union from astroid import nodes -import pylint.checkers.base -import pylint.checkers.utils -from pylint import interfaces -from pylint.constants import HUMAN_READABLE_TYPES -from pylint.lint import PyLinter - -if sys.version_info >= (3, 8): - from typing import Protocol -else: - from typing_extensions import Protocol - +from pylint import constants, interfaces, lint +from pylint.checkers import base_checker, utils if sys.version_info[:2] >= (3, 7): # pylint: disable-next=fixme @@ -40,13 +30,7 @@ def isascii(self: str) -> bool: return all("\u0000" <= x <= "\u007F" for x in self) -class _AsciiOnlyCheckedNode(Protocol): - _is_ascii_only: bool - - -class NonAsciiNamesChecker( - pylint.checkers.BaseChecker, pylint.checkers.base.NameCheckerHelper -): +class NonAsciiNameChecker(base_checker._NameCheckerBase): """A strict name checker only allowing ASCII If your programming guideline defines that you are programming in English, @@ -101,36 +85,12 @@ class NonAsciiNamesChecker( name = "NonASCII-Checker" - def __init__(self, linter: PyLinter) -> None: - super().__init__(linter) - self._non_ascii_rgx_compiled = re.compile("[^A-Za-z0-9_]") - - def _raise_name_warning( - self, - node: nodes.NodeNG, - node_type: str, - name: str, - ) -> None: - type_label = HUMAN_READABLE_TYPES.get(node_type, node_type) - args = (type_label.capitalize(), name) - - msg = "non-ascii-name" - - # Some node types have customized messages - if node_type == "file": - msg = "non-ascii-file-name" - elif node_type == "module": - msg = "non-ascii-module-import" - - self.add_message(msg, node=node, args=args, confidence=interfaces.HIGH) - - # pylint: disable-next=arguments-renamed def _check_name( self, node_type: str, - name: str, - node: Union[nodes.NodeNG, _AsciiOnlyCheckedNode], - check_string: Optional[str] = None, + name: Optional[str], + node: nodes.NodeNG, + confidence=interfaces.HIGH, ) -> None: """Check whether a name is using non-ASCII characters. @@ -139,31 +99,29 @@ def _check_name( too many edge cases. """ - current_state = getattr(node, "_is_ascii_only", True) - if name is None: # For some nodes i.e. *kwargs from a dict, the name will be empty return - if check_string is None: - check_string = name + if not (Py37Str(name).isascii()): + type_label = constants.HUMAN_READABLE_TYPES.get(node_type, node_type) + args = (type_label.capitalize(), name) + + msg = "non-ascii-name" - if not ( - Py37Str(check_string).isascii() - and self._non_ascii_rgx_compiled.match(check_string) is None - ): - # Note that we require the `.isascii` method as it is fast and - # handles the complexities of unicode, so we can use simple regex. - self._raise_name_warning(node, node_type, name) - current_state = False + # Some node types have customized messages + if node_type == "file": + msg = "non-ascii-file-name" + elif node_type == "module": + msg = "non-ascii-module-import" - node._is_ascii_only = current_state # pylint: disable=protected-access + self.add_message(msg, node=node, args=args, confidence=confidence) - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_module(self, node: nodes.Module) -> None: self._check_name("file", node.name.split(".")[-1], node) - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_functiondef( self, node: Union[nodes.FunctionDef, nodes.AsyncFunctionDef] ) -> None: @@ -189,12 +147,12 @@ def visit_functiondef( visit_asyncfunctiondef = visit_functiondef - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_global(self, node: nodes.Global) -> None: for name in node.names: self._check_name("const", name, node) - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_assignname(self, node: nodes.AssignName) -> None: """check module level assigned names""" # The NameChecker from which this Checker originates knows a lot of different @@ -202,63 +160,49 @@ def visit_assignname(self, node: nodes.AssignName) -> None: # To simplify we use only `variable` here, as we don't need to apply different # rules to different types of variables. frame = node.frame() - assign_type = node.assign_type() - if isinstance(assign_type, nodes.Comprehension): - # called inlinevar in NamesChecker - self._check_name("variable", node.name, node) - elif isinstance(frame, nodes.Module): - self._check_name("variable", node.name, node) - elif isinstance(frame, nodes.FunctionDef): - if not hasattr(node, "_is_ascii_only"): - # only check if not already done + + if isinstance(frame, nodes.FunctionDef): + if node.parent in frame.body: + # Only perform the check if the assigment was done in within the body + # of the function (and not the function parameter definition + # (will be handled in visit_functiondef) + # or within a decorator (handled in visit_call) self._check_name("variable", node.name, node) elif isinstance(frame, nodes.ClassDef): self._check_name("attr", node.name, node) else: - # Just to make sure we check EVERYTHING (!) + # Possibilities here: + # - isinstance(node.assign_type(), nodes.Comprehension) == inlinevar + # - isinstance(frame, nodes.Module) == variable (constant?) + # - some other kind of assigment missed but still most likely a variable self._check_name("variable", node.name, node) - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_classdef(self, node: nodes.ClassDef) -> None: self._check_name("class", node.name, node) for attr, anodes in node.instance_attrs.items(): if not any(node.instance_attr_ancestors(attr)): self._check_name("attr", attr, anodes[0]) - def _check_module_import( - self, node: Union[nodes.ImportFrom, nodes.Import], is_import_from: bool = False - ): + def _check_module_import(self, node: Union[nodes.ImportFrom, nodes.Import]): for module_name, alias in node.names: - if alias: - name = alias - else: - if is_import_from and module_name == "*": - # Ignore ``from xyz import *`` - continue - name = module_name - - if is_import_from or alias: - self._check_name("module", name, node) - else: - # Normal module import can contain "." for which we don't want to check - self._check_name( - "module", name, node, check_string=name.replace(".", "") - ) - - @pylint.checkers.utils.check_messages("non-ascii-name") + name = alias or module_name + self._check_name("module", name, node) + + @utils.check_messages("non-ascii-name") def visit_import(self, node: nodes.Import) -> None: self._check_module_import(node) - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_importfrom(self, node: nodes.ImportFrom) -> None: - self._check_module_import(node, is_import_from=True) + self._check_module_import(node) - @pylint.checkers.utils.check_messages("non-ascii-name") + @utils.check_messages("non-ascii-name") def visit_call(self, node: nodes.Call) -> None: # lets check if the used keyword args are correct for keyword in node.keywords: self._check_name("argument", keyword.arg, keyword) -def register(linter: PyLinter) -> None: - linter.register_checker(NonAsciiNamesChecker(linter)) +def register(linter: lint.PyLinter) -> None: + linter.register_checker(NonAsciiNameChecker(linter)) diff --git a/tests/checkers/unittest_non_ascii_name.py b/tests/checkers/unittest_non_ascii_name.py index 92e303435c..ff2d5f4a52 100644 --- a/tests/checkers/unittest_non_ascii_name.py +++ b/tests/checkers/unittest_non_ascii_name.py @@ -11,8 +11,8 @@ class TestNonAsciiChecker(pylint.testutils.CheckerTestCase): - CHECKER_CLASS = pylint.checkers.non_ascii_names.NonAsciiNamesChecker - checker: pylint.checkers.non_ascii_names.NonAsciiNamesChecker + CHECKER_CLASS = pylint.checkers.non_ascii_names.NonAsciiNameChecker + checker: pylint.checkers.non_ascii_names.NonAsciiNameChecker @pytest.mark.skipif( sys.version_info < (3, 8), reason="requires python3.8 or higher" diff --git a/tests/functional/e/.#emacs_file_lock_redefined_conf.py b/tests/functional/e/.#emacs_file_lock_redefined_conf.py index 2c31f21ea7..4b26dee73a 100644 --- a/tests/functional/e/.#emacs_file_lock_redefined_conf.py +++ b/tests/functional/e/.#emacs_file_lock_redefined_conf.py @@ -1,3 +1,3 @@ -# [invalid-name, non-ascii-file-name] +# [invalid-name] # The name is invalid and we should analyse this file # as ignore-patterns is redefined in the configuration diff --git a/tests/functional/e/.#emacs_file_lock_redefined_conf.txt b/tests/functional/e/.#emacs_file_lock_redefined_conf.txt index 79c4a53d1b..41b31279f7 100644 --- a/tests/functional/e/.#emacs_file_lock_redefined_conf.txt +++ b/tests/functional/e/.#emacs_file_lock_redefined_conf.txt @@ -1,2 +1 @@ invalid-name:1:0:None:None::"Module name ""#emacs_file_lock_redefined_conf"" doesn't conform to snake_case naming style":HIGH -non-ascii-file-name:1:0:None:None::"File name ""#emacs_file_lock_redefined_conf"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers.":HIGH diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt index 869d4e94a9..6c4944009d 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_decorator.txt @@ -1 +1 @@ -non-ascii-name:14:4:14:13:a_function:"Argument name ""fåling"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:16:4:16:13:a_function:"Argument name ""fåling"" contains a non-ASCII character, consider renaming it.":HIGH From 737d51c6ea152142e30d2ab3a94f2a590cf1b65a Mon Sep 17 00:00:00 2001 From: Kound Date: Mon, 10 Jan 2022 10:32:17 +0100 Subject: [PATCH 06/16] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniël van Noord <13665637+DanielNoord@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- pylint/checkers/__init__.py | 2 +- pylint/checkers/non_ascii_names.py | 10 +++------- .../non_ascii_name_pos_and_kwonly_function.py | 3 +++ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pylint/checkers/__init__.py b/pylint/checkers/__init__.py index b423c2dc93..914425313e 100644 --- a/pylint/checkers/__init__.py +++ b/pylint/checkers/__init__.py @@ -42,7 +42,7 @@ . . . -25: non-ascii-names +24: non-ascii-names 25-50: not yet used: reserved for future internal checkers. This file is not updated. Use script/get_unused_message_id_category.py diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index f40fc744bf..f947c04972 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -64,7 +64,7 @@ class NonAsciiNameChecker(base_checker._NameCheckerBase): # files. Probably only a bug shows the problem quite good. # That's also why this is a warning and not only a convention! "Some editors don't support non-ASCII file names properly. " - "Even so Python supports UTF-8 files since Python 3.5 this isn't recommended for " + "Even though Python supports UTF-8 files since Python 3.5 this isn't recommended for " "interoperability. Further reading:\n" "- https://www.python.org/dev/peps/pep-0489/#export-hook-name\n" "- https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers\n" @@ -93,10 +93,6 @@ def _check_name( confidence=interfaces.HIGH, ) -> None: """Check whether a name is using non-ASCII characters. - - Also set the dynamic attribute ``_is_ascii_only`` that is used to - determine if a node has been already checked, so we don't have to handle - too many edge cases. """ if name is None: @@ -184,7 +180,7 @@ def visit_classdef(self, node: nodes.ClassDef) -> None: if not any(node.instance_attr_ancestors(attr)): self._check_name("attr", attr, anodes[0]) - def _check_module_import(self, node: Union[nodes.ImportFrom, nodes.Import]): + def _check_module_import(self, node: Union[nodes.ImportFrom, nodes.Import]) -> None: for module_name, alias in node.names: name = alias or module_name self._check_name("module", name, node) @@ -199,7 +195,7 @@ def visit_importfrom(self, node: nodes.ImportFrom) -> None: @utils.check_messages("non-ascii-name") def visit_call(self, node: nodes.Call) -> None: - # lets check if the used keyword args are correct + """Check if the used keyword args are correct.""" for keyword in node.keywords: self._check_name("argument", keyword.arg, keyword) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py index e6a2b80d85..651d78f894 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.py @@ -1,5 +1,8 @@ """ Test for names within keyword and position only function + +This test is 3.8+ as the columns are not correctly identified +by the ast parser < 3.8 """ # pylint: disable=unused-argument From 58524ce2c10698c912ebad9958acb252cae37605 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Jan 2022 09:33:07 +0000 Subject: [PATCH 07/16] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pylint/checkers/non_ascii_names.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index f947c04972..85c298bd4b 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -92,8 +92,7 @@ def _check_name( node: nodes.NodeNG, confidence=interfaces.HIGH, ) -> None: - """Check whether a name is using non-ASCII characters. - """ + """Check whether a name is using non-ASCII characters.""" if name is None: # For some nodes i.e. *kwargs from a dict, the name will be empty From bcc8a394a263e6a4a70ca6d789895c3272396826 Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 10:53:09 +0100 Subject: [PATCH 08/16] Do not change original files, use simple args check --- pylint/checkers/base.py | 29 +++++++++++++++++++-------- pylint/checkers/base_checker.py | 32 +----------------------------- pylint/checkers/non_ascii_names.py | 8 ++++---- 3 files changed, 26 insertions(+), 43 deletions(-) diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 6af205ed66..2f79f852e0 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -78,9 +78,9 @@ import astroid from astroid import nodes -from pylint import constants, interfaces +from pylint import checkers, constants, interfaces from pylint import utils as lint_utils -from pylint.checkers import base_checker, utils +from pylint.checkers import utils from pylint.checkers.utils import ( infer_all, is_overload_stub, @@ -456,7 +456,12 @@ def x(self, value): self._x = value return False -class BasicErrorChecker(base_checker._BasicChecker): +class _BasicChecker(checkers.BaseChecker): + __implements__ = interfaces.IAstroidChecker + name = "basic" + + +class BasicErrorChecker(_BasicChecker): msgs = { "E0100": ( "__init__ method is a generator", @@ -932,7 +937,7 @@ def _check_redefinition(self, redeftype, node): ) -class BasicChecker(base_checker._BasicChecker): +class BasicChecker(_BasicChecker): """checks for : * doc strings * number of arguments, local variables, branches, returns and statements in @@ -1714,7 +1719,7 @@ def _create_naming_options(): return tuple(name_options) -class NameChecker(base_checker._NameCheckerBase): +class NameChecker(_BasicChecker): msgs = { "C0103": ( '%s name "%s" doesn\'t conform to %s', @@ -1974,6 +1979,14 @@ def visit_assignname(self, node: nodes.AssignName) -> None: else: self._check_name("class_attribute", node.name, node) + def _recursive_check_names(self, args): + """check names in a possibly recursive list """ + for arg in args: + if isinstance(arg, nodes.AssignName): + self._check_name("argument", arg.name, arg) + else: + self._recursive_check_names(arg.elts) + def _find_name_group(self, node_type): return self._name_group.get(node_type, node_type) @@ -2062,7 +2075,7 @@ def _name_became_keyword_in_version(name, rules): return None -class DocStringChecker(base_checker._BasicChecker): +class DocStringChecker(_BasicChecker): msgs = { "C0112": ( "Empty %s docstring", @@ -2228,7 +2241,7 @@ def _check_docstring( ) -class PassChecker(base_checker._BasicChecker): +class PassChecker(_BasicChecker): """check if the pass statement is really necessary""" msgs = { @@ -2270,7 +2283,7 @@ def _infer_dunder_doc_attribute(node): return docstring.value -class ComparisonChecker(base_checker._BasicChecker): +class ComparisonChecker(_BasicChecker): """Checks for comparisons - singleton comparison: 'expr == True', 'expr == False' and 'expr == None' diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 1dc155be75..5a6efd20c2 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -19,11 +19,10 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE import functools from inspect import cleandoc -from typing import Any, Iterable, Optional +from typing import Any, Optional from astroid import nodes -from pylint import interfaces from pylint.config import OptionsProviderMixIn from pylint.constants import _MSG_ORDER, WarningScope from pylint.exceptions import InvalidMessageError @@ -202,32 +201,3 @@ class BaseTokenChecker(BaseChecker): def process_tokens(self, tokens): """Should be overridden by subclasses.""" raise NotImplementedError() - - -class _BasicChecker(BaseChecker): - __implements__ = interfaces.IAstroidChecker - name = "basic" - - -class _NameCheckerBase(_BasicChecker): - """Class containing functions required by NameChecker and NonAsciiNameChecker""" - - def _check_name( - self, node_type: str, name: str, node: nodes.NodeNG, confidence=interfaces.HIGH - ): - """Only Dummy function will be overwritten by implementing classes - - Note: kwarg arguments will be different in implementing classes - """ - raise NotImplementedError - - def _recursive_check_names(self, args: Iterable[nodes.AssignName]): - """Check names in a possibly recursive list """ - for arg in args: - if isinstance(arg, nodes.AssignName): - self._check_name("argument", arg.name, arg) - else: - # pylint: disable-next=fixme - # TODO: Check if we can remove this if branch because of - # the up to date astroid version used - self._recursive_check_names(arg.elts) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index f40fc744bf..7bc9e9e550 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -30,7 +30,7 @@ def isascii(self: str) -> bool: return all("\u0000" <= x <= "\u007F" for x in self) -class NonAsciiNameChecker(base_checker._NameCheckerBase): +class NonAsciiNameChecker(base_checker.BaseChecker): """A strict name checker only allowing ASCII If your programming guideline defines that you are programming in English, @@ -136,9 +136,9 @@ def visit_functiondef( self._check_name("argument", pos_only_arg.name, pos_only_arg) # Check "normal" arguments - args = arguments.args - if args: - self._recursive_check_names(args) + args = arguments.args or tuple() + for arg in args: + self._check_name("argument", arg.name, arg) # Check key word only arguments if arguments.kwonlyargs: From 85f7529378dab8e9478b5bdb429523d34c45eca5 Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 10:54:36 +0100 Subject: [PATCH 09/16] fix functional test --- .../non_ascii_name_pos_and_kwonly_function.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt index 031cd9a390..b13a1af3b2 100644 --- a/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt +++ b/tests/functional/n/non_ascii_name/non_ascii_name_pos_and_kwonly_function.txt @@ -1,4 +1,4 @@ -non-ascii-name:9:4:9:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-name:10:4:10:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-name:13:4:13:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH -non-ascii-name:16:4:16:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:12:4:12:17:name:"Argument name ""not_okay_łol"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:13:4:13:21:name:"Argument name ""not_okay_defaułt"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:16:4:16:21:name:"Argument name ""p_or_kw_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:19:4:19:20:name:"Argument name ""kw_arg_not_økay"" contains a non-ASCII character, consider renaming it.":HIGH From 06761c898d4c53c9c3b5187748c6a420972c2d3f Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 11:33:06 +0100 Subject: [PATCH 10/16] Remove not needed unit tests --- tests/checkers/unittest_non_ascii_name.py | 33 ------------------- .../n/non_ascii_import/non_ascii_import.py | 3 +- .../non_ascii_name_class.py | 8 ++++- .../non_ascii_name_class.txt | 2 +- 4 files changed, 10 insertions(+), 36 deletions(-) diff --git a/tests/checkers/unittest_non_ascii_name.py b/tests/checkers/unittest_non_ascii_name.py index ff2d5f4a52..8e34549f16 100644 --- a/tests/checkers/unittest_non_ascii_name.py +++ b/tests/checkers/unittest_non_ascii_name.py @@ -156,39 +156,6 @@ def test_assignname( ): self.checker.visit_assignname(assign_node) - def test_class_definition(self): - node = astroid.extract_node( - """ - class FooBär: #@ - ... - """ - ) - assert isinstance(node, nodes.ClassDef) - - with self.assertAddsMessages( - pylint.testutils.MessageTest( - msg_id="non-ascii-name", - node=node, - args=("Class", "FooBär"), - confidence=pylint.interfaces.HIGH, - line=2, - col_offset=0, - # pylint: disable-next=fixme - # TODO: Maybe we have to select something different - # here, as line 3 is not that thing we expect - end_line=3, - end_col_offset=7, - ) - ): - self.checker.visit_classdef(node) - - def test_import_ignore_star(self): - """Special case from xyz import *, where '*' is not A-Za-z0-9 but still valid""" - node = astroid.parse("from urllib.parse import *") - - with self.assertAddsMessages(): - self.walk(node) - @pytest.mark.parametrize( "import_statement, wrong_name", [ diff --git a/tests/functional/n/non_ascii_import/non_ascii_import.py b/tests/functional/n/non_ascii_import/non_ascii_import.py index 26ca724934..76163b2862 100644 --- a/tests/functional/n/non_ascii_import/non_ascii_import.py +++ b/tests/functional/n/non_ascii_import/non_ascii_import.py @@ -1,5 +1,5 @@ """Test that invalid module name imports causes correct error""" -# pylint: disable=import-error, wrong-import-position +# pylint: disable=import-error, wrong-import-position, unused-wildcard-import, wildcard-import, wrong-import-order import sys import os @@ -8,5 +8,6 @@ sys.path.append(os.path.dirname(SCRIPT_DIR)) import non_ascii_name_loł as ok +from pathlib import * # test that star imports work correctly and give no error print(ok) diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py index f2e68426a7..edcdae6435 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.py @@ -1,4 +1,10 @@ -""" Non ASCII char in class name """ +""" Non ASCII char in class name + +Note that the end line parameter here seems to be off. +We would expect it to be the same as the start, as we only refer +to the class Name and not the complete class definition. +But this is not possible atm with pylint. +""" # pylint: disable=too-few-public-methods diff --git a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt index 101b534a0f..92c4430b31 100644 --- a/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt +++ b/tests/functional/n/non_ascii_name_class/non_ascii_name_class.txt @@ -1 +1 @@ -non-ascii-name:5:0:10:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, consider renaming it.":HIGH +non-ascii-name:11:0:16:19:НoldIt:"Class name ""НoldIt"" contains a non-ASCII character, consider renaming it.":HIGH From c89a5c84cf27e94c30db396ed691d51df3989b7c Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 11:41:41 +0100 Subject: [PATCH 11/16] update help --- pylint/checkers/non_ascii_names.py | 33 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index 31287ebb2d..4282364ff2 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -30,13 +30,19 @@ def isascii(self: str) -> bool: return all("\u0000" <= x <= "\u007F" for x in self) +NON_ASCII_HELP = ( + "Used when the name contains at least one non-ASCII unicode character. " + "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" + " for a background why this could be bad. \n" + "If your programming guideline defines that you are programming in " + "English, then there should be no need for non ASCII characters in " + "Python Names. Everybody else can simply disable this check." +) + + class NonAsciiNameChecker(base_checker.BaseChecker): """A strict name checker only allowing ASCII - If your programming guideline defines that you are programming in English, - then there should be no need for non ASCII characters in Python Names. - Everybody else can simply not use this check. - Note: This check only checks Names, so it ignores the content of docstrings and comments! """ @@ -48,11 +54,7 @@ class NonAsciiNameChecker(base_checker.BaseChecker): "C2401": ( '%s name "%s" contains a non-ASCII character, consider renaming it.', "non-ascii-name", - ( - "Used when the name contains at least one non-ASCII unicode character. " - "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" - " for a background why this could be bad." - ), + NON_ASCII_HELP, {"old_names": [("C0144", "old-non-ascii-name")]}, ), # First %s will always be "file" @@ -61,11 +63,12 @@ class NonAsciiNameChecker(base_checker.BaseChecker): "non-ascii-file-name", ( # Some = PyCharm at the time of writing didn't display the non_ascii_name_loł - # files. Probably only a bug shows the problem quite good. + # files and had big troubles with git. + # Probably only a bug shows the problem quite good. # That's also why this is a warning and not only a convention! "Some editors don't support non-ASCII file names properly. " - "Even though Python supports UTF-8 files since Python 3.5 this isn't recommended for " - "interoperability. Further reading:\n" + "Even though Python supports UTF-8 files since Python 3.5 this isn't " + "recommended for interoperability. Further reading:\n" "- https://www.python.org/dev/peps/pep-0489/#export-hook-name\n" "- https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers\n" "- https://bugs.python.org/issue20485\n" @@ -75,11 +78,7 @@ class NonAsciiNameChecker(base_checker.BaseChecker): "C2403": ( '%s name "%s" contains a non-ASCII character, use an ASCII-only alias for import.', "non-ascii-module-import", - ( - "Used when the name contains at least one non-ASCII unicode character. " - "See https://www.python.org/dev/peps/pep-0672/#confusable-characters-in-identifiers" - " for a background why this could be bad." - ), + NON_ASCII_HELP, ), } From 4575edc44b948d9b26f542e134e437a1e2e3aa0c Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 11:43:21 +0100 Subject: [PATCH 12/16] remove confidence as parameter --- pylint/checkers/non_ascii_names.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index 4282364ff2..71cd3ef702 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -85,11 +85,7 @@ class NonAsciiNameChecker(base_checker.BaseChecker): name = "NonASCII-Checker" def _check_name( - self, - node_type: str, - name: Optional[str], - node: nodes.NodeNG, - confidence=interfaces.HIGH, + self, node_type: str, name: Optional[str], node: nodes.NodeNG ) -> None: """Check whether a name is using non-ASCII characters.""" @@ -109,7 +105,7 @@ def _check_name( elif node_type == "module": msg = "non-ascii-module-import" - self.add_message(msg, node=node, args=args, confidence=confidence) + self.add_message(msg, node=node, args=args, confidence=interfaces.HIGH) @utils.check_messages("non-ascii-name") def visit_module(self, node: nodes.Module) -> None: From b22c2da4ddc1142d843fc7b1f6b2e94463044a9b Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 11:49:31 +0100 Subject: [PATCH 13/16] be more explicit in error message --- pylint/checkers/non_ascii_names.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index 71cd3ef702..4aed95c246 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -59,7 +59,10 @@ class NonAsciiNameChecker(base_checker.BaseChecker): ), # First %s will always be "file" "W2402": ( - '%s name "%s" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers.', + ( + '%s name "%s" contains a non-ASCII character. PEP 3131 only allows ' + "non-ascii identifiers, not file names." + ), "non-ascii-file-name", ( # Some = PyCharm at the time of writing didn't display the non_ascii_name_loł From e2c9a88b5f814e0cec6c75a85b7652e3428f4af2 Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 11:57:21 +0100 Subject: [PATCH 14/16] fix name --- .../n/non_ascii_import/non_ascii_name_lo\305\202.txt" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" index c30827ed3a..eefaa197a9 100644 --- "a/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" +++ "b/tests/functional/n/non_ascii_import/non_ascii_name_lo\305\202.txt" @@ -1 +1 @@ -non-ascii-file-name:1:0:None:None::"File name ""non_ascii_name_loł"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers.":HIGH +non-ascii-file-name:1:0:None:None::"File name ""non_ascii_name_loł"" contains a non-ASCII character. PEP 3131 only allows non-ascii identifiers, not file names.":HIGH From f6b540c167e85f947bba5bbdd1d37c984cedcfab Mon Sep 17 00:00:00 2001 From: Kound Date: Mon, 10 Jan 2022 19:54:19 +0100 Subject: [PATCH 15/16] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniël van Noord <13665637+DanielNoord@users.noreply.github.com> --- pylint/checkers/non_ascii_names.py | 12 ++++++------ tests/checkers/unittest_non_ascii_name.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pylint/checkers/non_ascii_names.py b/pylint/checkers/non_ascii_names.py index 4aed95c246..6ad0df556b 100644 --- a/pylint/checkers/non_ascii_names.py +++ b/pylint/checkers/non_ascii_names.py @@ -36,7 +36,7 @@ def isascii(self: str) -> bool: " for a background why this could be bad. \n" "If your programming guideline defines that you are programming in " "English, then there should be no need for non ASCII characters in " - "Python Names. Everybody else can simply disable this check." + "Python Names. If not you can simply disable this check." ) @@ -97,7 +97,7 @@ def _check_name( return if not (Py37Str(name).isascii()): - type_label = constants.HUMAN_READABLE_TYPES.get(node_type, node_type) + type_label = constants.HUMAN_READABLE_TYPES[node_type] args = (type_label.capitalize(), name) msg = "non-ascii-name" @@ -129,9 +129,9 @@ def visit_functiondef( self._check_name("argument", pos_only_arg.name, pos_only_arg) # Check "normal" arguments - args = arguments.args or tuple() - for arg in args: - self._check_name("argument", arg.name, arg) + if arguments.args: + for arg in arguments.args: + self._check_name("argument", arg.name, arg) # Check key word only arguments if arguments.kwonlyargs: @@ -156,7 +156,7 @@ def visit_assignname(self, node: nodes.AssignName) -> None: if isinstance(frame, nodes.FunctionDef): if node.parent in frame.body: - # Only perform the check if the assigment was done in within the body + # Only perform the check if the assignment was done in within the body # of the function (and not the function parameter definition # (will be handled in visit_functiondef) # or within a decorator (handled in visit_call) diff --git a/tests/checkers/unittest_non_ascii_name.py b/tests/checkers/unittest_non_ascii_name.py index 8e34549f16..d0e3a85ab7 100644 --- a/tests/checkers/unittest_non_ascii_name.py +++ b/tests/checkers/unittest_non_ascii_name.py @@ -246,11 +246,11 @@ def test_assignname( "from foo.bar import functiøn as good, *", # We still have functiøn within our namespace and could detect this # But to do this properly we would need to check all `*` imports - # -> Too much efford! + # -> Too much effort! "functiøn", id="from_okay_module_import_bad_as_good_and_star", marks=pytest.mark.xfail( - reason="We don't what is imported when using star" + reason="We don't know what is imported when using star" ), ), ], From 5ed79c7ea1eddf4f56ce7d4f56074aa53bb20adb Mon Sep 17 00:00:00 2001 From: Carli* Freudenberg Date: Mon, 10 Jan 2022 19:55:38 +0100 Subject: [PATCH 16/16] add missing human-readable type --- pylint/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pylint/constants.py b/pylint/constants.py index eb5b1118a5..db54113ee4 100644 --- a/pylint/constants.py +++ b/pylint/constants.py @@ -57,6 +57,7 @@ class WarningScope: Python {sys.version}""" HUMAN_READABLE_TYPES = { + "file": "file", "module": "module", "const": "constant", "class": "class",