diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e29621..87e7232 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -357,6 +357,17 @@ repos: types_or: [c, c++] exclude: ^CPP/mini_browser/ + # =========================================================================== + # CHECK PYTHON LOCATION - All Python files must be under python_pkg/ + # =========================================================================== + - repo: local + hooks: + - id: check-python-location + name: check Python files are under python_pkg/ + entry: scripts/check_python_location.sh + language: script + types: [python] + # =========================================================================== # REMOVE EMPTY DIRECTORIES - Clean up empty folders in the repo # =========================================================================== diff --git a/pyproject.toml b/pyproject.toml index e51023d..c33aeb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,10 +66,10 @@ unfixable = [] # Files using urlopen with validated URL schemes "python_pkg/geo_data/_common.py" = ["S310"] "python_pkg/steam_backlog_enforcer/library_hider.py" = ["S310"] -"poker_modifier_app/poker_modifier_app.py" = [ +"python_pkg/poker_modifier_app/poker_modifier_app.py" = [ "FBT003", # Boolean positional values in tkinter API calls ] -"poker_modifier_app/_poker_gui.py" = [ +"python_pkg/poker_modifier_app/_poker_gui.py" = [ "FBT003", # Boolean positional values in tkinter API calls ] "python_pkg/keyboard_coop/main.py" = [ @@ -102,12 +102,11 @@ unfixable = [] "PLC0415", # Lazy imports of split helper modules ] # Moviepy showcase - lazy imports of split helpers -"moviepy_showcase.py" = [ - "INP001", +"python_pkg/moviepy_showcase/moviepy_showcase.py" = [ "PLC0415", # Lazy imports of split helper modules ] # Puzzle solver - late imports for CLI entry point -"puzzle_solver/main.py" = [ +"python_pkg/puzzle_solver/main.py" = [ "PLC0415", # Late imports in __main__ guard ] # Geo data admin helper @@ -125,9 +124,7 @@ unfixable = [] "python_pkg/praca_magisterska_video/visualize_q02.py" = [ "PLC0415", # Late import for conditional dependency ] -# Root-level helper scripts and test files outside packages -"_moviepy_*.py" = ["INP001"] -"tests/test_file_length.py" = ["INP001"] +# Removed: root-level moviepy helper scripts and test files are now inside python_pkg "python_pkg/word_frequency/_translator_cli.py" = [ "SLF001", # Legitimately accesses translator module internals ] @@ -251,7 +248,7 @@ exclude_dirs = ["tests", ".venv", "Bash/ffmpeg-build", "python_pkg/lichess_bot/. # PYTEST - Testing framework configuration # ============================================================================ [tool.pytest.ini_options] -testpaths = ["tests", "python_pkg", "articles"] +testpaths = ["python_pkg"] python_files = ["test_*.py", "*_test.py"] python_classes = ["Test*"] python_functions = ["test_*"] diff --git a/articles/.clang-format b/python_pkg/articles/.clang-format similarity index 100% rename from articles/.clang-format rename to python_pkg/articles/.clang-format diff --git a/articles/.gitignore b/python_pkg/articles/.gitignore similarity index 100% rename from articles/.gitignore rename to python_pkg/articles/.gitignore diff --git a/articles/Makefile b/python_pkg/articles/Makefile similarity index 100% rename from articles/Makefile rename to python_pkg/articles/Makefile diff --git a/articles/README.md b/python_pkg/articles/README.md similarity index 100% rename from articles/README.md rename to python_pkg/articles/README.md diff --git a/articles/__init__.py b/python_pkg/articles/__init__.py similarity index 100% rename from articles/__init__.py rename to python_pkg/articles/__init__.py diff --git a/articles/cppcheck.txt b/python_pkg/articles/cppcheck.txt similarity index 100% rename from articles/cppcheck.txt rename to python_pkg/articles/cppcheck.txt diff --git a/articles/data/articles.json b/python_pkg/articles/data/articles.json similarity index 100% rename from articles/data/articles.json rename to python_pkg/articles/data/articles.json diff --git a/articles/index.html b/python_pkg/articles/index.html similarity index 100% rename from articles/index.html rename to python_pkg/articles/index.html diff --git a/articles/run.sh b/python_pkg/articles/run.sh similarity index 100% rename from articles/run.sh rename to python_pkg/articles/run.sh diff --git a/articles/run_tests.sh b/python_pkg/articles/run_tests.sh similarity index 100% rename from articles/run_tests.sh rename to python_pkg/articles/run_tests.sh diff --git a/articles/server_c.c b/python_pkg/articles/server_c.c similarity index 100% rename from articles/server_c.c rename to python_pkg/articles/server_c.c diff --git a/articles/sw.js b/python_pkg/articles/sw.js similarity index 100% rename from articles/sw.js rename to python_pkg/articles/sw.js diff --git a/articles/test_server_api.py b/python_pkg/articles/test_server_api.py similarity index 100% rename from articles/test_server_api.py rename to python_pkg/articles/test_server_api.py diff --git a/articles/test_site_size.py b/python_pkg/articles/test_site_size.py similarity index 100% rename from articles/test_site_size.py rename to python_pkg/articles/test_site_size.py diff --git a/articles/tools/funcsize.awk b/python_pkg/articles/tools/funcsize.awk similarity index 100% rename from articles/tools/funcsize.awk rename to python_pkg/articles/tools/funcsize.awk diff --git a/python_pkg/moviepy_showcase/__init__.py b/python_pkg/moviepy_showcase/__init__.py new file mode 100644 index 0000000..b113390 --- /dev/null +++ b/python_pkg/moviepy_showcase/__init__.py @@ -0,0 +1 @@ +"""MoviePy 2.x comprehensive showcase package.""" diff --git a/_moviepy_audio_output.py b/python_pkg/moviepy_showcase/_moviepy_audio_output.py similarity index 99% rename from _moviepy_audio_output.py rename to python_pkg/moviepy_showcase/_moviepy_audio_output.py index 1317fb8..b594f87 100644 --- a/_moviepy_audio_output.py +++ b/python_pkg/moviepy_showcase/_moviepy_audio_output.py @@ -31,7 +31,7 @@ from moviepy.video.tools.drawing import ( ) import numpy as np -from moviepy_showcase import ( +from python_pkg.moviepy_showcase.moviepy_showcase import ( CLIP_DUR, FONT_B, FONT_R, diff --git a/_moviepy_clip_types.py b/python_pkg/moviepy_showcase/_moviepy_clip_types.py similarity index 99% rename from _moviepy_clip_types.py rename to python_pkg/moviepy_showcase/_moviepy_clip_types.py index be9a735..46a2130 100644 --- a/_moviepy_clip_types.py +++ b/python_pkg/moviepy_showcase/_moviepy_clip_types.py @@ -18,7 +18,7 @@ from moviepy.video.fx import InvertColors from moviepy.video.tools.drawing import circle import numpy as np -from moviepy_showcase import ( +from python_pkg.moviepy_showcase.moviepy_showcase import ( CLIP_DUR, FONT_B, FONT_R, diff --git a/_moviepy_video_effects.py b/python_pkg/moviepy_showcase/_moviepy_video_effects.py similarity index 99% rename from _moviepy_video_effects.py rename to python_pkg/moviepy_showcase/_moviepy_video_effects.py index b26ba9e..50a05fa 100644 --- a/_moviepy_video_effects.py +++ b/python_pkg/moviepy_showcase/_moviepy_video_effects.py @@ -45,7 +45,7 @@ from moviepy.video.fx import ( from moviepy.video.tools.drawing import circle import numpy as np -from moviepy_showcase import ( +from python_pkg.moviepy_showcase.moviepy_showcase import ( CLIP_DUR, H, W, diff --git a/moviepy_showcase.py b/python_pkg/moviepy_showcase/moviepy_showcase.py similarity index 97% rename from moviepy_showcase.py rename to python_pkg/moviepy_showcase/moviepy_showcase.py index 21814eb..58163cd 100644 --- a/moviepy_showcase.py +++ b/python_pkg/moviepy_showcase/moviepy_showcase.py @@ -197,18 +197,18 @@ def _build(tmpdir: str) -> None: # ── Lazy imports of moved part builders ─────────────────────── from moviepy.audio.fx import MultiplyVolume - from _moviepy_audio_output import ( + from python_pkg.moviepy_showcase._moviepy_audio_output import ( _make_sine, part4_audio, part5_composition, part6_drawing_tools, part7_output, ) - from _moviepy_clip_types import ( + from python_pkg.moviepy_showcase._moviepy_clip_types import ( part1_clip_types, part2_clip_methods, ) - from _moviepy_video_effects import part3_video_effects + from python_pkg.moviepy_showcase._moviepy_video_effects import part3_video_effects # ── Render each part to its own temp file ───────────────────── # Title card diff --git a/poker_modifier_app/README.md b/python_pkg/poker_modifier_app/README.md similarity index 100% rename from poker_modifier_app/README.md rename to python_pkg/poker_modifier_app/README.md diff --git a/poker_modifier_app/README_python.md b/python_pkg/poker_modifier_app/README_python.md similarity index 100% rename from poker_modifier_app/README_python.md rename to python_pkg/poker_modifier_app/README_python.md diff --git a/poker_modifier_app/__init__.py b/python_pkg/poker_modifier_app/__init__.py similarity index 100% rename from poker_modifier_app/__init__.py rename to python_pkg/poker_modifier_app/__init__.py diff --git a/poker_modifier_app/_poker_gui.py b/python_pkg/poker_modifier_app/_poker_gui.py similarity index 99% rename from poker_modifier_app/_poker_gui.py rename to python_pkg/poker_modifier_app/_poker_gui.py index b859295..07da909 100644 --- a/poker_modifier_app/_poker_gui.py +++ b/python_pkg/poker_modifier_app/_poker_gui.py @@ -7,7 +7,7 @@ from tkinter import ttk from typing import TYPE_CHECKING if TYPE_CHECKING: - from poker_modifier_app.poker_modifier_app import PokerModifierApp + from python_pkg.poker_modifier_app.poker_modifier_app import PokerModifierApp class PokerGuiMixin: diff --git a/poker_modifier_app/_poker_modifiers.py b/python_pkg/poker_modifier_app/_poker_modifiers.py similarity index 100% rename from poker_modifier_app/_poker_modifiers.py rename to python_pkg/poker_modifier_app/_poker_modifiers.py diff --git a/poker_modifier_app/index.html b/python_pkg/poker_modifier_app/index.html similarity index 100% rename from poker_modifier_app/index.html rename to python_pkg/poker_modifier_app/index.html diff --git a/poker_modifier_app/poker_modifier_app.py b/python_pkg/poker_modifier_app/poker_modifier_app.py similarity index 98% rename from poker_modifier_app/poker_modifier_app.py rename to python_pkg/poker_modifier_app/poker_modifier_app.py index 61f3ab0..b1942af 100644 --- a/poker_modifier_app/poker_modifier_app.py +++ b/python_pkg/poker_modifier_app/poker_modifier_app.py @@ -4,8 +4,11 @@ import logging import secrets import tkinter as tk -from poker_modifier_app._poker_gui import PokerGuiMixin -from poker_modifier_app._poker_modifiers import ENDGAME_MODIFIERS, REGULAR_MODIFIERS +from python_pkg.poker_modifier_app._poker_gui import PokerGuiMixin +from python_pkg.poker_modifier_app._poker_modifiers import ( + ENDGAME_MODIFIERS, + REGULAR_MODIFIERS, +) _logger = logging.getLogger(__name__) diff --git a/poker_modifier_app/script.js b/python_pkg/poker_modifier_app/script.js similarity index 100% rename from poker_modifier_app/script.js rename to python_pkg/poker_modifier_app/script.js diff --git a/poker_modifier_app/style.css b/python_pkg/poker_modifier_app/style.css similarity index 100% rename from poker_modifier_app/style.css rename to python_pkg/poker_modifier_app/style.css diff --git a/puzzle_solver/README.md b/python_pkg/puzzle_solver/README.md similarity index 100% rename from puzzle_solver/README.md rename to python_pkg/puzzle_solver/README.md diff --git a/puzzle_solver/__init__.py b/python_pkg/puzzle_solver/__init__.py similarity index 100% rename from puzzle_solver/__init__.py rename to python_pkg/puzzle_solver/__init__.py diff --git a/puzzle_solver/__main__.py b/python_pkg/puzzle_solver/__main__.py similarity index 58% rename from puzzle_solver/__main__.py rename to python_pkg/puzzle_solver/__main__.py index 41e0787..5b670fe 100644 --- a/puzzle_solver/__main__.py +++ b/python_pkg/puzzle_solver/__main__.py @@ -1,5 +1,5 @@ """Allow ``python -m puzzle_solver …`` invocation.""" -from puzzle_solver.main import main +from python_pkg.puzzle_solver.main import main main() diff --git a/puzzle_solver/main.py b/python_pkg/puzzle_solver/main.py similarity index 95% rename from puzzle_solver/main.py rename to python_pkg/puzzle_solver/main.py index 1ed011b..6e7b08e 100644 --- a/puzzle_solver/main.py +++ b/python_pkg/puzzle_solver/main.py @@ -22,8 +22,8 @@ import json from pathlib import Path import sys -from puzzle_solver.parse_image import draw_debug, parse_image, save_puzzle -from puzzle_solver.solver import Puzzle, print_puzzle, print_solution, solve +from python_pkg.puzzle_solver.parse_image import draw_debug, parse_image, save_puzzle +from python_pkg.puzzle_solver.solver import Puzzle, print_puzzle, print_solution, solve def cmd_parse(args: argparse.Namespace) -> None: diff --git a/puzzle_solver/parse_image.py b/python_pkg/puzzle_solver/parse_image.py similarity index 100% rename from puzzle_solver/parse_image.py rename to python_pkg/puzzle_solver/parse_image.py diff --git a/puzzle_solver/solver.py b/python_pkg/puzzle_solver/solver.py similarity index 100% rename from puzzle_solver/solver.py rename to python_pkg/puzzle_solver/solver.py diff --git a/python_pkg/tests/__init__.py b/python_pkg/tests/__init__.py new file mode 100644 index 0000000..f44a9a5 --- /dev/null +++ b/python_pkg/tests/__init__.py @@ -0,0 +1 @@ +"""Repository-wide tests package.""" diff --git a/tests/test_file_length.py b/python_pkg/tests/test_file_length.py similarity index 96% rename from tests/test_file_length.py rename to python_pkg/tests/test_file_length.py index 716d53f..1abab19 100644 --- a/tests/test_file_length.py +++ b/python_pkg/tests/test_file_length.py @@ -20,7 +20,7 @@ _SKIP_DIRS = frozenset( } ) -_ROOT = Path(__file__).resolve().parents[1] +_ROOT = Path(__file__).resolve().parents[2] def _python_files() -> list[Path]: diff --git a/scripts/check_python_location.sh b/scripts/check_python_location.sh new file mode 100755 index 0000000..aa5897f --- /dev/null +++ b/scripts/check_python_location.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Check that all Python files are under python_pkg/. +# Exceptions: linux_configuration/, pomodoro_app/, sonic_pi/, Bash/, +# and vendored/generated directories. +# Used as a pre-commit hook; receives staged file paths as arguments. + +set -uo pipefail + +# Directories allowed to contain Python files outside python_pkg/ +ALLOWED_DIRS="linux_configuration/|pomodoro_app/|sonic_pi/" + +errors=() + +for file in "$@"; do + # Only check .py files + [[ "$file" != *.py ]] && continue + + # Skip files already under python_pkg/ + [[ "$file" == python_pkg/* ]] && continue + + # Skip allowed directories (non-Python projects with some Python scripts) + if echo "$file" | grep -qE "^($ALLOWED_DIRS)"; then + continue + fi + + # Skip vendored/generated directories + if echo "$file" | grep -qE '(^|/)(\.venv|venv|__pycache__|build|dist|node_modules|\.git)/'; then + continue + fi + + errors+=("$file") +done + +if [[ ${#errors[@]} -gt 0 ]]; then + echo "ERROR: Python files must be under python_pkg/." + echo "The following files are in the wrong location:" + for err in "${errors[@]}"; do + echo " $err" + done + echo "" + echo "Move them with: git mv python_pkg/" + exit 1 +fi