fix: Fix initialization order bug in ScreenshotService

BUG: AttributeError: 'ScreenshotService' object has no attribute '_platform'

Root cause: In __init__, _get_default_save_path() was called BEFORE
_platform was initialized. The method tried to access self._platform
to determine the save path.

FIX: Moved platform detection BEFORE save path initialization in:
- core/screenshot.py
- core/screenshot_secure.py
- core/screenshot_vulnerable.py

Order changed from:
  1. self._save_path = self._get_default_save_path()  # FAILS - needs _platform
  2. self._platform = platform.system().lower()

To:
  1. self._platform = platform.system().lower()
  2. self._save_path = self._get_default_save_path()  # WORKS - _platform exists

This is a common Python initialization order bug where methods called
in __init__ reference attributes that haven't been set yet.
This commit is contained in:
LemonNexus 2026-02-14 18:50:45 +00:00
parent dbdd78c1bd
commit 721b5e14a6
3 changed files with 12 additions and 6 deletions

View File

@ -53,7 +53,6 @@ class ScreenshotService:
# Configuration # Configuration
self._auto_save: bool = True self._auto_save: bool = True
self._save_path: Path = self._get_default_save_path()
self._format: str = "PNG" self._format: str = "PNG"
self._quality: int = 95 # For JPEG self._quality: int = 95 # For JPEG
self._history_size: int = 20 self._history_size: int = 20
@ -62,10 +61,13 @@ class ScreenshotService:
self._history: deque = deque(maxlen=self._history_size) self._history: deque = deque(maxlen=self._history_size)
self._last_screenshot: Optional[Image.Image] = None self._last_screenshot: Optional[Image.Image] = None
# Platform detection # Platform detection - MUST be before _get_default_save_path()
self._platform = platform.system().lower() self._platform = platform.system().lower()
self._use_pil = self._platform == "windows" self._use_pil = self._platform == "windows"
# Set save path AFTER platform detection
self._save_path: Path = self._get_default_save_path()
# Lazy init for capture backends # Lazy init for capture backends
self._pil_available: Optional[bool] = None self._pil_available: Optional[bool] = None
self._pyautogui_available: Optional[bool] = None self._pyautogui_available: Optional[bool] = None

View File

@ -53,7 +53,6 @@ class ScreenshotService:
# Configuration # Configuration
self._auto_save: bool = True self._auto_save: bool = True
self._save_path: Path = self._get_default_save_path()
self._format: str = "PNG" self._format: str = "PNG"
self._quality: int = 95 # For JPEG self._quality: int = 95 # For JPEG
self._history_size: int = 20 self._history_size: int = 20
@ -62,10 +61,13 @@ class ScreenshotService:
self._history: deque = deque(maxlen=self._history_size) self._history: deque = deque(maxlen=self._history_size)
self._last_screenshot: Optional[Image.Image] = None self._last_screenshot: Optional[Image.Image] = None
# Platform detection # Platform detection - MUST be before _get_default_save_path()
self._platform = platform.system().lower() self._platform = platform.system().lower()
self._use_pil = self._platform == "windows" self._use_pil = self._platform == "windows"
# Set save path AFTER platform detection
self._save_path: Path = self._get_default_save_path()
# Lazy init for capture backends # Lazy init for capture backends
self._pil_available: Optional[bool] = None self._pil_available: Optional[bool] = None
self._pyautogui_available: Optional[bool] = None self._pyautogui_available: Optional[bool] = None

View File

@ -55,7 +55,6 @@ class ScreenshotService:
# Configuration # Configuration
self._auto_save: bool = True self._auto_save: bool = True
self._save_path: Path = self._get_default_save_path()
self._format: str = "PNG" self._format: str = "PNG"
self._quality: int = 95 # For JPEG self._quality: int = 95 # For JPEG
self._history_size: int = 20 self._history_size: int = 20
@ -64,10 +63,13 @@ class ScreenshotService:
self._history: deque = deque(maxlen=self._history_size) self._history: deque = deque(maxlen=self._history_size)
self._last_screenshot = None self._last_screenshot = None
# Platform detection # Platform detection - MUST be before _get_default_save_path()
self._platform = platform.system().lower() self._platform = platform.system().lower()
self._use_pil = self._platform == "windows" self._use_pil = self._platform == "windows"
# Set save path AFTER platform detection
self._save_path: Path = self._get_default_save_path()
# Lazy init for capture backends # Lazy init for capture backends
self._pil_available: Optional[bool] = None self._pil_available: Optional[bool] = None
self._pyautogui_available: Optional[bool] = None self._pyautogui_available: Optional[bool] = None