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",
|
"pylint",
|
||||||
"mypy",
|
"mypy",
|
||||||
"pyright",
|
"pyright",
|
||||||
|
"isort>=5.13.2",
|
||||||
# security:
|
# security:
|
||||||
"bandit",
|
"bandit",
|
||||||
# packaging:
|
# packaging:
|
||||||
@@ -83,8 +84,8 @@ app = "python -m kleinanzeigen_bot"
|
|||||||
compile.cmd = "python -O -m PyInstaller pyinstaller.spec --clean"
|
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
|
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"
|
debug = "python -m pdb -m kleinanzeigen_bot"
|
||||||
format = "autopep8 --recursive --in-place src tests --verbose"
|
format = "python -m scripts.format_code"
|
||||||
lint = {shell = "pylint -v src tests && autopep8 -v --exit-code --recursive --diff src tests && mypy" }
|
lint = "python -m scripts.lint_code"
|
||||||
audit = "bandit -c pyproject.toml -r src"
|
audit = "bandit -c pyproject.toml -r src"
|
||||||
test = "python -m pytest --capture=tee-sys -v"
|
test = "python -m pytest --capture=tee-sys -v"
|
||||||
utest = "python -m pytest --capture=tee-sys -v -m 'not itest'"
|
utest = "python -m pytest --capture=tee-sys -v -m 'not itest'"
|
||||||
@@ -266,3 +267,15 @@ filterwarnings = [
|
|||||||
"ignore:Exception ignored in:pytest.PytestUnraisableExceptionWarning",
|
"ignore:Exception ignored in:pytest.PytestUnraisableExceptionWarning",
|
||||||
"ignore::DeprecationWarning"
|
"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