mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 20:23:11 +02:00
Fix ruff violations in ~15 source files and ~60+ test files to minimize per-file-ignores in pyproject.toml. Remaining ignores are justified with comments explaining why each suppression is necessary. Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001 (private access), T201 (print→logging), C901 (complexity), E501 (line length), E402 (import order). Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108 (tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type annotations), RUF059 (unused unpacked vars), PT019 (fixture naming). Remaining per-file-ignores (with justifications): - Tests: ARG, D, PLC0415, PLR2004, S101, SLF001 - music_gen sources: PLC0415 (heavy ML lazy imports) - moviepy_showcase: PLC0415 (circular dependency) - generate_images: PLR0913 (matplotlib helpers need many params) - praca_magisterska_video: E501, E402 (long paths, mpl.use)
285 lines
10 KiB
Python
285 lines
10 KiB
Python
"""Tests for python_pkg.repo_explorer._discovery."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path, PurePosixPath
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from python_pkg.repo_explorer._discovery import (
|
|
IGNORED_DIRS,
|
|
_desc_from_run_sh,
|
|
_find_terminal,
|
|
_is_ignored,
|
|
_strip_ansi,
|
|
find_projects,
|
|
get_description,
|
|
)
|
|
|
|
# ── _strip_ansi ──────────────────────────────────────────────────────
|
|
|
|
|
|
class TestStripAnsi:
|
|
def test_removes_colour_codes(self) -> None:
|
|
assert _strip_ansi("\x1b[31mred\x1b[0m") == "red"
|
|
|
|
def test_no_ansi(self) -> None:
|
|
assert _strip_ansi("plain text") == "plain text"
|
|
|
|
def test_empty_string(self) -> None:
|
|
assert _strip_ansi("") == ""
|
|
|
|
def test_complex_ansi(self) -> None:
|
|
assert _strip_ansi("\x1b[1;32mgreen\x1b[0m rest") == "green rest"
|
|
|
|
|
|
# ── _find_terminal ───────────────────────────────────────────────────
|
|
|
|
|
|
class TestFindTerminal:
|
|
@patch("python_pkg.repo_explorer._discovery.shutil.which")
|
|
def test_first_candidate_found(self, mock_which: MagicMock) -> None:
|
|
mock_which.return_value = "/usr/bin/kitty"
|
|
result = _find_terminal()
|
|
assert result == ["kitty", "--"]
|
|
|
|
@patch("python_pkg.repo_explorer._discovery.shutil.which")
|
|
def test_later_candidate_found(self, mock_which: MagicMock) -> None:
|
|
def side_effect(exe: str) -> str | None:
|
|
return "/usr/bin/xterm" if exe == "xterm" else None
|
|
|
|
mock_which.side_effect = side_effect
|
|
result = _find_terminal()
|
|
assert result == ["xterm", "-e"]
|
|
|
|
@patch("python_pkg.repo_explorer._discovery.shutil.which")
|
|
def test_none_found(self, mock_which: MagicMock) -> None:
|
|
mock_which.return_value = None
|
|
result = _find_terminal()
|
|
assert result == []
|
|
|
|
|
|
# ── _is_ignored ──────────────────────────────────────────────────────
|
|
|
|
|
|
class TestIsIgnored:
|
|
def test_ignored_dir(self) -> None:
|
|
assert _is_ignored(Path("project/.git/config"))
|
|
|
|
def test_not_ignored(self) -> None:
|
|
assert not _is_ignored(Path("project/src/main.py"))
|
|
|
|
def test_ignored_pycache(self) -> None:
|
|
assert _is_ignored(Path("a/__pycache__/b.pyc"))
|
|
|
|
def test_all_ignored_dirs_recognized(self) -> None:
|
|
for d in IGNORED_DIRS:
|
|
assert _is_ignored(Path(d) / "file.txt")
|
|
|
|
|
|
# ── find_projects ────────────────────────────────────────────────────
|
|
|
|
|
|
class TestFindProjects:
|
|
@patch("python_pkg.repo_explorer._discovery._is_ignored")
|
|
def test_finds_run_sh(self, mock_ignored: MagicMock) -> None:
|
|
mock_ignored.return_value = False
|
|
root = MagicMock(spec=Path)
|
|
run1 = MagicMock(spec=Path)
|
|
proj1 = MagicMock(spec=Path)
|
|
run1.parent = proj1
|
|
proj1.name = "proj1"
|
|
proj1.relative_to.return_value = PurePosixPath("sub/proj1")
|
|
root.rglob.return_value = [run1]
|
|
result = find_projects(root)
|
|
assert len(result) == 1
|
|
assert result[0]["path"] is proj1
|
|
assert result[0]["name"] == "proj1"
|
|
|
|
@patch("python_pkg.repo_explorer._discovery._is_ignored")
|
|
def test_filters_ignored(self, mock_ignored: MagicMock) -> None:
|
|
mock_ignored.return_value = True
|
|
root = MagicMock(spec=Path)
|
|
run1 = MagicMock(spec=Path)
|
|
root.rglob.return_value = [run1]
|
|
result = find_projects(root)
|
|
assert result == []
|
|
|
|
def test_empty_root(self) -> None:
|
|
root = MagicMock(spec=Path)
|
|
root.rglob.return_value = []
|
|
result = find_projects(root)
|
|
assert result == []
|
|
|
|
|
|
# ── _desc_from_run_sh ────────────────────────────────────────────────
|
|
|
|
|
|
class TestDescFromRunSh:
|
|
def test_with_shebang_and_comments(self) -> None:
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.read_text.return_value = (
|
|
"#!/bin/bash\n# First line\n# Second line\necho hi"
|
|
)
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert result == "First line Second line"
|
|
|
|
def test_only_shebang(self) -> None:
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.read_text.return_value = "#!/bin/bash\necho hi"
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert result == ""
|
|
|
|
def test_comments_only(self) -> None:
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.read_text.return_value = "# Just a comment\n# Another one"
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert result == "Just a comment Another one"
|
|
|
|
def test_empty_file(self) -> None:
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.read_text.return_value = ""
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert result == ""
|
|
|
|
def test_truncates_at_300(self) -> None:
|
|
run_sh = MagicMock(spec=Path)
|
|
long_comment = "# " + "x" * 400
|
|
run_sh.read_text.return_value = long_comment
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert len(result) == 300
|
|
|
|
def test_non_comment_line_without_prior_comments(self) -> None:
|
|
"""Non-comment before comments: comments still collected."""
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.read_text.return_value = "echo hello\n# comment after code"
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert result == "comment after code"
|
|
|
|
def test_break_on_non_comment_after_comments(self) -> None:
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.read_text.return_value = "# first\ncode\n# ignored"
|
|
result = _desc_from_run_sh(run_sh)
|
|
assert result == "first"
|
|
|
|
|
|
# ── get_description ──────────────────────────────────────────────────
|
|
|
|
|
|
class TestGetDescription:
|
|
def test_readme_md_with_heading(self) -> None:
|
|
mock_path = MagicMock(spec=Path)
|
|
readme = MagicMock(spec=Path)
|
|
readme.exists.return_value = True
|
|
readme.read_text.return_value = "# My Project\nDetails here"
|
|
|
|
def truediv(_self: object, name: str) -> MagicMock:
|
|
if name == "README.md":
|
|
return readme
|
|
m = MagicMock(spec=Path)
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
result = get_description(mock_path)
|
|
assert result == "My Project"
|
|
|
|
def test_readme_txt(self) -> None:
|
|
mock_path = MagicMock(spec=Path)
|
|
|
|
def truediv(_self: object, name: str) -> MagicMock:
|
|
m = MagicMock(spec=Path)
|
|
if name == "README.txt":
|
|
m.exists.return_value = True
|
|
m.read_text.return_value = "Text readme content"
|
|
else:
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
result = get_description(mock_path)
|
|
assert result == "Text readme content"
|
|
|
|
def test_readme_lower(self) -> None:
|
|
mock_path = MagicMock(spec=Path)
|
|
|
|
def truediv(_self: object, name: str) -> MagicMock:
|
|
m = MagicMock(spec=Path)
|
|
if name == "readme.md":
|
|
m.exists.return_value = True
|
|
m.read_text.return_value = "## Lower readme"
|
|
else:
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
result = get_description(mock_path)
|
|
assert result == "Lower readme"
|
|
|
|
def test_readme_all_empty_lines(self) -> None:
|
|
"""README exists but all lines strip to empty."""
|
|
mock_path = MagicMock(spec=Path)
|
|
|
|
def truediv(_self: object, name: str) -> MagicMock:
|
|
m = MagicMock(spec=Path)
|
|
if name == "README.md":
|
|
m.exists.return_value = True
|
|
m.read_text.return_value = "###\n \n"
|
|
else:
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
# README.md has only empty/whitespace lines → falls through
|
|
# README.txt and readme.md don't exist → falls to run.sh
|
|
result = get_description(mock_path)
|
|
# run.sh also doesn't exist so "(no description)"
|
|
assert result == "(no description)"
|
|
|
|
@patch("python_pkg.repo_explorer._discovery._desc_from_run_sh")
|
|
def test_no_readme_run_sh_with_desc(self, mock_desc: MagicMock) -> None:
|
|
mock_desc.return_value = "From run.sh"
|
|
mock_path = MagicMock(spec=Path)
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.exists.return_value = True
|
|
|
|
def truediv(_self: object, name: str) -> MagicMock:
|
|
if name == "run.sh":
|
|
return run_sh
|
|
m = MagicMock(spec=Path)
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
result = get_description(mock_path)
|
|
assert result == "From run.sh"
|
|
|
|
@patch("python_pkg.repo_explorer._discovery._desc_from_run_sh")
|
|
def test_no_readme_run_sh_empty_desc(self, mock_desc: MagicMock) -> None:
|
|
mock_desc.return_value = ""
|
|
mock_path = MagicMock(spec=Path)
|
|
run_sh = MagicMock(spec=Path)
|
|
run_sh.exists.return_value = True
|
|
|
|
def truediv(_self: object, name: str) -> MagicMock:
|
|
if name == "run.sh":
|
|
return run_sh
|
|
m = MagicMock(spec=Path)
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
result = get_description(mock_path)
|
|
assert result == "(no description)"
|
|
|
|
def test_no_readme_no_run_sh(self) -> None:
|
|
mock_path = MagicMock(spec=Path)
|
|
|
|
def truediv(_self: object, _name: str) -> MagicMock:
|
|
m = MagicMock(spec=Path)
|
|
m.exists.return_value = False
|
|
return m
|
|
|
|
mock_path.__truediv__ = truediv
|
|
result = get_description(mock_path)
|
|
assert result == "(no description)"
|