mirror of
https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git
synced 2026-03-12 02:31:45 +01:00
feat: Introduce isort and Python-based code quality tools (#446)
This commit is contained in:
@@ -56,6 +56,7 @@ dev = [
|
||||
"pylint",
|
||||
"mypy",
|
||||
"pyright",
|
||||
"isort>=5.13.2",
|
||||
# security:
|
||||
"bandit",
|
||||
# packaging:
|
||||
@@ -83,8 +84,8 @@ app = "python -m kleinanzeigen_bot"
|
||||
compile.cmd = "python -O -m PyInstaller pyinstaller.spec --clean"
|
||||
compile.env = {PYTHONHASHSEED = "1", SOURCE_DATE_EPOCH = "0"} # https://pyinstaller.org/en/stable/advanced-topics.html#creating-a-reproducible-build
|
||||
debug = "python -m pdb -m kleinanzeigen_bot"
|
||||
format = "autopep8 --recursive --in-place src tests --verbose"
|
||||
lint = {shell = "pylint -v src tests && autopep8 -v --exit-code --recursive --diff src tests && mypy" }
|
||||
format = "python -m scripts.format_code"
|
||||
lint = "python -m scripts.lint_code"
|
||||
audit = "bandit -c pyproject.toml -r src"
|
||||
test = "python -m pytest --capture=tee-sys -v"
|
||||
utest = "python -m pytest --capture=tee-sys -v -m 'not itest'"
|
||||
@@ -266,3 +267,15 @@ filterwarnings = [
|
||||
"ignore:Exception ignored in:pytest.PytestUnraisableExceptionWarning",
|
||||
"ignore::DeprecationWarning"
|
||||
]
|
||||
|
||||
# Add isort configuration to format imports
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 160
|
||||
combine_as_imports = true
|
||||
combine_star = true
|
||||
multi_line_output = 3
|
||||
force_grid_wrap = 0
|
||||
ensure_newline_before_comments = true
|
||||
no_lines_before = ["LOCALFOLDER"]
|
||||
combine_straight_imports = true
|
||||
|
||||
1
scripts/__init__.py
Normal file
1
scripts/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Helper scripts for development tasks."""
|
||||
33
scripts/format_code.py
Normal file
33
scripts/format_code.py
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Helper script to format Python code using isort and autopep8."""
|
||||
|
||||
import subprocess, sys
|
||||
|
||||
from scripts.git_utils import get_modified_python_files
|
||||
|
||||
|
||||
def format_files() -> int:
|
||||
"""Format Python files using isort and autopep8.
|
||||
|
||||
Returns:
|
||||
int: 0 on success, non-zero on failure
|
||||
"""
|
||||
try:
|
||||
# Format imports in modified files
|
||||
py_files = get_modified_python_files()
|
||||
if py_files:
|
||||
subprocess.run(['isort', *py_files], check=True)
|
||||
|
||||
# Format all files with autopep8
|
||||
subprocess.run(
|
||||
['autopep8', '--recursive', '--in-place', 'src', 'tests', '--verbose'],
|
||||
check=True
|
||||
)
|
||||
return 0
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error during formatting: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(format_files())
|
||||
18
scripts/git_utils.py
Normal file
18
scripts/git_utils.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Utility functions for git operations."""
|
||||
|
||||
import subprocess
|
||||
from collections.abc import Sequence
|
||||
|
||||
|
||||
def get_modified_python_files() -> Sequence[str]:
|
||||
"""Get list of modified Python files from git.
|
||||
|
||||
Returns:
|
||||
Sequence[str]: List of modified Python file paths
|
||||
"""
|
||||
git_cmd = ['git', 'diff', '--name-only', '--diff-filter=ACMR', 'HEAD']
|
||||
result = subprocess.run(git_cmd, capture_output=True, text=True, check=True)
|
||||
if not result.stdout.strip():
|
||||
return []
|
||||
return [f for f in result.stdout.splitlines() if f.endswith('.py')]
|
||||
65
scripts/lint_code.py
Normal file
65
scripts/lint_code.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Helper script to lint Python code using multiple tools."""
|
||||
|
||||
import subprocess, sys
|
||||
from collections.abc import Sequence
|
||||
|
||||
from scripts.git_utils import get_modified_python_files
|
||||
|
||||
|
||||
def run_tool(cmd: Sequence[str], tool_name: str) -> tuple[int, str]:
|
||||
"""Run a lint tool and return its exit code and error message.
|
||||
|
||||
Args:
|
||||
cmd: Command to run as list of strings
|
||||
tool_name: Name of the tool for error messages
|
||||
|
||||
Returns:
|
||||
tuple[int, str]: tuple of (exit_code, error_message)
|
||||
"""
|
||||
try:
|
||||
subprocess.run(list(cmd), check=True)
|
||||
return 0, ""
|
||||
except subprocess.CalledProcessError as e:
|
||||
return e.returncode, f"{tool_name} fehlgeschlagen\n"
|
||||
|
||||
|
||||
def lint_files() -> int:
|
||||
"""Run all linting tools.
|
||||
|
||||
Returns:
|
||||
int: Number of errors encountered
|
||||
"""
|
||||
errors = 0
|
||||
error_messages = []
|
||||
|
||||
# Run isort on modified files
|
||||
py_files = get_modified_python_files()
|
||||
if py_files:
|
||||
code, msg = run_tool(['isort', *py_files], 'isort')
|
||||
errors += code
|
||||
if msg:
|
||||
error_messages.append(msg)
|
||||
|
||||
# Run other linting tools
|
||||
tools = [
|
||||
(['pylint', '-v', 'src', 'tests'], 'pylint'),
|
||||
(['autopep8', '-v', '--in-place', '--recursive', 'src', 'tests'], 'autopep8'),
|
||||
(['mypy', 'src', 'tests'], 'mypy')
|
||||
]
|
||||
|
||||
for cmd, name in tools:
|
||||
code, msg = run_tool(cmd, name)
|
||||
errors += code
|
||||
if msg:
|
||||
error_messages.append(msg)
|
||||
|
||||
# Print all error messages at the end
|
||||
if error_messages:
|
||||
print("\n".join(error_messages), file=sys.stderr)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(lint_files())
|
||||
Reference in New Issue
Block a user