diff --git a/pyproject.toml b/pyproject.toml index d78a5c8..f65136b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,6 +145,8 @@ py-version = "3.10" ignore = ["Bash", ".venv", "__pycache__"] # Ignore patterns ignore-patterns = [".*\\.pyi$"] +# Allow C extension modules to be introspected +extension-pkg-allow-list = ["cv2", "pygame", "lxml"] [tool.pylint.messages_control] # Enable all checks by disabling disable @@ -152,91 +154,28 @@ enable = "all" # No disabled checks - maximum strictness disable = [] -[tool.pylint.format] -# Maximum line length (same as ruff/black) -max-line-length = 88 -# Maximum module lines -max-module-lines = 1000 - [tool.pylint.design] -# Maximum arguments for function/method -max-args = 5 -# Maximum local variables -max-locals = 15 -# Maximum return statements -max-returns = 6 -# Maximum branches in function body -max-branches = 12 -# Maximum statements in function body -max-statements = 50 -# Maximum parents for a class -max-parents = 7 -# Maximum attributes for a class -max-attributes = 10 -# Maximum public methods for a class -max-public-methods = 20 -# Minimum public methods for a class +# A class with just run() as public API is valid for games/apps min-public-methods = 1 -[tool.pylint.similarities] -# Minimum lines for similarity check -min-similarity-lines = 4 -# Ignore comments when computing similarities -ignore-comments = true -# Ignore docstrings when computing similarities -ignore-docstrings = true -# Ignore imports when computing similarities -ignore-imports = true - [tool.pylint.spelling] # No spelling dictionary to avoid false positives spelling-dict = "" [tool.pylint.typecheck] -# Ignore missing members for dynamic modules (optional dependencies) -ignored-modules = ["chess", "pygame", "cv2", "PIL", "mitmproxy", "selenium", "bs4", "lxml", "berserk", "bottle"] +# cv2 (OpenCV) dynamically loads members from C extension at runtime +generated-members = ["cv2.*"] # ============================================================================ # BANDIT - Security linter # ============================================================================ [tool.bandit] # Exclude test directories and vendored code -exclude_dirs = ["tests", ".venv", "Bash/ffmpeg-build"] -# Use all tests -tests = [] -# No skipped tests (most aggressive) -skips = [] -# Severity level: all (1=low, 2=medium, 3=high) -severity = 1 -# Confidence level: all -confidence = 1 +exclude_dirs = ["tests", ".venv", "Bash/ffmpeg-build", "python_pkg/lichess_bot/.venv"] # ============================================================================ -# BLACK - Code formatter (for comparison/fallback) +# BLACK & ISORT - Removed (ruff handles formatting and import sorting) # ============================================================================ -[tool.black] -line-length = 88 -target-version = ["py310"] -include = '\.pyi?$' -extend-exclude = ''' -/( - \.git - | \.venv - | __pycache__ - | Bash/ffmpeg-build -)/ -''' - -# ============================================================================ -# ISORT - Import sorting (for comparison/fallback, ruff handles this) -# ============================================================================ -[tool.isort] -profile = "black" -line_length = 88 -force_single_line = false -force_sort_within_sections = true -known_first_party = ["PYTHON"] -skip = [".venv", "__pycache__", "Bash/ffmpeg-build"] # ============================================================================ # PYTEST - Testing framework configuration diff --git a/python_pkg/keyboard_coop/main.py b/python_pkg/keyboard_coop/main.py index c969176..4a993b3 100644 --- a/python_pkg/keyboard_coop/main.py +++ b/python_pkg/keyboard_coop/main.py @@ -93,6 +93,15 @@ class KeyboardState: positions: dict[str, pygame.Rect] = field(default_factory=dict) +@dataclass +class FontSet: + """Collection of fonts used in the game.""" + + normal: pygame.font.Font + large: pygame.font.Font + small: pygame.font.Font + + class KeyboardCoopGame: """Main game class for the keyboard cooperative word game.""" @@ -101,9 +110,11 @@ class KeyboardCoopGame: self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Keyboard Coop Game") self.clock = pygame.time.Clock() - self.font = pygame.font.Font(None, 24) - self.large_font = pygame.font.Font(None, 32) - self.small_font = pygame.font.Font(None, 20) + self.fonts = FontSet( + normal=pygame.font.Font(None, 24), + large=pygame.font.Font(None, 32), + small=pygame.font.Font(None, 20), + ) # Load dictionary self.dictionary = self._load_dictionary() @@ -397,7 +408,7 @@ class KeyboardCoopGame: pygame.draw.rect(self.screen, TEXT_COLOR, rect, 2) # Draw letter - text = self.small_font.render(letter.upper(), True, TEXT_COLOR) + text = self.fonts.small.render(letter.upper(), True, TEXT_COLOR) text_rect = text.get_rect(center=rect.center) self.screen.blit(text, text_rect) @@ -412,27 +423,29 @@ class KeyboardCoopGame: """Draw a button with the given label.""" pygame.draw.rect(self.screen, KEY_COLOR, rect) pygame.draw.rect(self.screen, TEXT_COLOR, rect, 2) - text = self.small_font.render(label, True, TEXT_COLOR) + text = self.fonts.small.render(label, True, TEXT_COLOR) self.screen.blit(text, text.get_rect(center=rect.center)) def _draw_ui(self) -> tuple[pygame.Rect, pygame.Rect]: """Draw the user interface.""" # Title and status - self._draw_text_line("Keyboard Coop Game", (30, 20), self.large_font) + self._draw_text_line("Keyboard Coop Game", (30, 20), self.fonts.large) self._draw_text_line( - f"Current Word: {self.state.current_word.upper()}", (30, 50), self.font + f"Current Word: {self.state.current_word.upper()}", + (30, 50), + self.fonts.normal, ) - self._draw_text_line(f"Score: {self.state.score}", (30, 75), self.font) + self._draw_text_line(f"Score: {self.state.score}", (30, 75), self.fonts.normal) # Current player with color player_color = PLAYER_COLORS[self.state.current_player] - player_text = self.font.render( + player_text = self.fonts.normal.render( f"Current Player: {self.state.current_player + 1}", True, player_color ) self.screen.blit(player_text, (30, 100)) # Message - self._draw_text_line(self.state.message, (30, 125), self.font) + self._draw_text_line(self.state.message, (30, 125), self.fonts.normal) # Instructions instructions = [ @@ -446,7 +459,7 @@ class KeyboardCoopGame: "• Keyboard randomizes after each valid word!", ] for idx, instruction in enumerate(instructions): - self._draw_text_line(instruction, (750, 20 + idx * 22), self.small_font) + self._draw_text_line(instruction, (750, 20 + idx * 22), self.fonts.small) # Buttons enter_rect = pygame.Rect(750, 190, 120, 40) diff --git a/requirements.txt b/requirements.txt index 237e7a8..bd18982 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,14 @@ +beautifulsoup4>=4.0 +berserk>=0.13 +bottle>=0.12 +lxml>=5.0 +mitmproxy>=10.0 + +# Optional dependencies for specific scripts (needed for full pylint analysis) +opencv-python>=4.0 +pillow>=10.0 +pygame>=2.0 pytest>=7.0 python-chess>=1.999 +requests>=2.0 +selenium>=4.0