blob: 2ef6c55e3ae3d177c8e3ee64a9c1a574c9f37a3f [file] [log] [blame]
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
from __future__ import annotations
from collections.abc import Iterable
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.NonAsciiNameChecker
checker: pylint.checkers.non_ascii_names.NonAsciiNameChecker
def test_kwargs_and_position_only(self) -> None:
"""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 = node.args
posargs = list(arguments.posonlyargs)
args = list(arguments.args)
kwargs = list(arguments.kwonlyargs)
with self.assertAddsMessages(
pylint.testutils.MessageTest(
msg_id="non-ascii-name",
node=posargs[1],
args=("Argument", "not_økay"),
confidence=pylint.interfaces.HIGH,
),
pylint.testutils.MessageTest(
msg_id="non-ascii-name",
node=posargs[2],
args=("Argument", "not_okay_defaułt"),
confidence=pylint.interfaces.HIGH,
),
pylint.testutils.MessageTest(
msg_id="non-ascii-name",
node=args[1],
args=("Argument", "p_or_kw_not_økay"),
confidence=pylint.interfaces.HIGH,
),
pylint.testutils.MessageTest(
msg_id="non-ascii-name",
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,
) -> None:
"""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="non-ascii-name",
node=assign_node,
args=(assign_type, "łol"),
confidence=pylint.interfaces.HIGH,
),
ignore_position=True,
):
self.checker.visit_assignname(assign_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 effort!
"functiøn",
id="from_okay_module_import_bad_as_good_and_star",
marks=pytest.mark.xfail(
reason="We don't know what is imported when using star"
),
),
],
)
def test_check_import(self, import_statement: str, wrong_name: str | None) -> None:
"""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)