Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/usethis/_tool/impl/import_linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
if TYPE_CHECKING:
from usethis._io import KeyValueFileManager
from usethis._tool.config import ResolutionT
from usethis._tool.rule import Rule


IMPORT_LINTER_CONTRACT_MIN_MODULE_COUNT = 3
Expand All @@ -57,7 +58,7 @@ def is_used(self) -> bool:
return super().is_used()

def print_how_to_use(self) -> None:
if not RuffTool().is_used():
if not _is_inp_rule_selected():
# If Ruff is used, we enable the INP rules instead.
info_print("Ensure '__init__.py' files are used in your packages.")
info_print(
Expand Down Expand Up @@ -354,3 +355,11 @@ def get_rule_config(self) -> RuleConfig:
def _importlinter_warn_no_packages_found(name: str) -> None:
warn_print("Could not find any importable packages.")
warn_print(f"Assuming the package name is {name}.")


def _is_inp_rule_selected() -> bool:
return any(_is_inp_rule(rule) for rule in RuffTool().get_selected_rules())


def _is_inp_rule(rule: Rule) -> bool:
return rule.startswith("INP") and (not rule[3:] or rule[3:].isdigit())
2 changes: 2 additions & 0 deletions tests/usethis/_tool/impl/test_deptry.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ def test_four_numbers(self):
assert result is True

def test_no_numbers(self):
# N.B. Deptry does not accept rules without number codes, unlike Ruff.

# Arrange
rule = "DEP"

Expand Down
47 changes: 42 additions & 5 deletions tests/usethis/_tool/impl/test_import_linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from usethis._config_file import files_manager
from usethis._test import change_cwd
from usethis._tool.impl.import_linter import ImportLinterTool
from usethis._tool.impl.import_linter import ImportLinterTool, _is_inp_rule


class TestImportLinterTool:
Expand All @@ -22,7 +22,9 @@ def test_pre_commit_and_uv(
name: import-linter
entry: uv run --frozen --offline lint-imports
""")
(tmp_path / "ruff.toml").touch()
(tmp_path / "ruff.toml").write_text( # For avoid info/hint messages
'lint.select=["INP"]'
)

# Act
with change_cwd(tmp_path), files_manager():
Expand All @@ -47,7 +49,9 @@ def test_pre_commit_no_uv(
name: import-linter
entry: uv run --frozen --offline lint-imports
""")
(tmp_path / "ruff.toml").touch() # For avoid info/hint messages
(tmp_path / "ruff.toml").write_text( # For avoid info/hint messages
'lint.select=["INP"]'
)

# Act
with change_cwd(tmp_path), files_manager():
Expand All @@ -63,7 +67,9 @@ def test_pre_commit_no_uv(
def test_uv_only(self, tmp_path: Path, capfd: pytest.CaptureFixture[str]):
# Arrange
(tmp_path / "uv.lock").touch()
(tmp_path / "ruff.toml").touch()
(tmp_path / "ruff.toml").write_text( # For avoid info/hint messages
'lint.select=["INP"]'
)

# Act
with change_cwd(tmp_path), files_manager():
Expand All @@ -76,7 +82,9 @@ def test_uv_only(self, tmp_path: Path, capfd: pytest.CaptureFixture[str]):

def test_basic(self, tmp_path: Path, capfd: pytest.CaptureFixture[str]):
# Arrange
(tmp_path / "ruff.toml").touch()
(tmp_path / "ruff.toml").write_text( # For avoid info/hint messages
'lint.select=["INP"]'
)

# Act
with change_cwd(tmp_path), files_manager():
Expand All @@ -102,3 +110,32 @@ def test_ruff_isnt_used(
"ℹ For more info see <https://docs.python.org/3/tutorial/modules.html#packages>\n" # noqa: RUF001
"☐ Run 'lint-imports' to run Import Linter.\n"
)

def test_ruff_is_used_without_inp_rules(
self, tmp_path: Path, capfd: pytest.CaptureFixture[str]
):
# https://github.com/usethis-python/usethis-python/issues/817

# Arrange
(tmp_path / "ruff.toml").touch()

# Act
with change_cwd(tmp_path), files_manager():
ImportLinterTool().print_how_to_use()

# Assert
out, err = capfd.readouterr()
assert not err
assert out == (
"ℹ Ensure '__init__.py' files are used in your packages.\n" # noqa: RUF001
"ℹ For more info see <https://docs.python.org/3/tutorial/modules.html#packages>\n" # noqa: RUF001
"☐ Run 'lint-imports' to run Import Linter.\n"
)


class TestIsINPRule:
def test_inp_rule(self):
assert _is_inp_rule("INP001")

def test_no_digits(self):
assert _is_inp_rule("INP")