dreader-application/run_dreader.py
2025-11-12 18:52:08 +00:00

189 lines
5.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""
DReader E-Book Reader - Main Entry Point
This script launches the DReader application with a Pygame-based
desktop HAL for testing and development.
Usage:
python run_dreader.py [library_path]
python run_dreader.py ~/Books
python run_dreader.py tests/data/library-epub
Options:
--width WIDTH Window width (default: 800)
--height HEIGHT Window height (default: 1200)
--fullscreen Run in fullscreen mode
--log-level LEVEL Logging level: DEBUG, INFO, WARNING, ERROR (default: INFO)
Examples:
# Run with default library path
python run_dreader.py
# Run with custom library
python run_dreader.py ~/Documents/Books
# Run in fullscreen
python run_dreader.py --fullscreen
# Run with debug logging
python run_dreader.py --log-level DEBUG
"""
import sys
import asyncio
import argparse
import logging
from pathlib import Path
# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent))
from dreader.main import DReaderApplication, AppConfig
from dreader.hal_pygame import PygameDisplayHAL
def parse_args():
"""Parse command line arguments."""
parser = argparse.ArgumentParser(
description="DReader E-Book Reader Application",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s # Use default library path
%(prog)s ~/Books # Custom library path
%(prog)s --width 1200 --height 1600 # Custom window size
%(prog)s --fullscreen # Fullscreen mode
%(prog)s --log-level DEBUG # Debug logging
"""
)
parser.add_argument(
'library_path',
nargs='?',
default=None,
help='Path to directory containing EPUB files (default: tests/data/library-epub)'
)
parser.add_argument(
'--width',
type=int,
default=800,
help='Window width in pixels (default: 800)'
)
parser.add_argument(
'--height',
type=int,
default=1200,
help='Window height in pixels (default: 1200)'
)
parser.add_argument(
'--fullscreen',
action='store_true',
help='Run in fullscreen mode'
)
parser.add_argument(
'--library',
action='store_true',
help='Always start in library mode (ignore saved state)'
)
parser.add_argument(
'--log-level',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'],
default='INFO',
help='Logging level (default: INFO)'
)
return parser.parse_args()
def main():
"""Main entry point."""
args = parse_args()
# Set up logging
log_level = getattr(logging, args.log_level)
logging.basicConfig(
level=log_level,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
logger.info("Starting DReader E-Book Reader")
# Determine library path
if args.library_path:
library_path = Path(args.library_path).expanduser().resolve()
else:
# Default to test library
library_path = Path(__file__).parent / "tests" / "data" / "library-epub"
# Verify library path exists
if not library_path.exists():
logger.error(f"Library path does not exist: {library_path}")
print(f"\nError: Library directory not found: {library_path}")
print("\nPlease provide a valid path to a directory containing EPUB files.")
print("Example:")
print(f" python {sys.argv[0]} ~/Documents/Books")
sys.exit(1)
if not library_path.is_dir():
logger.error(f"Library path is not a directory: {library_path}")
print(f"\nError: Not a directory: {library_path}")
sys.exit(1)
logger.info(f"Library path: {library_path}")
logger.info(f"Window size: {args.width}x{args.height}")
logger.info(f"Fullscreen: {args.fullscreen}")
logger.info(f"Force library mode: {args.library}")
# Create HAL
try:
hal = PygameDisplayHAL(
width=args.width,
height=args.height,
fullscreen=args.fullscreen
)
except RuntimeError as e:
logger.error(f"Failed to initialize Pygame HAL: {e}")
print(f"\nError: {e}")
print("\nTo install Pygame, run:")
print(" pip install pygame")
sys.exit(1)
# Create application config
config = AppConfig(
display_hal=hal,
library_path=str(library_path),
page_size=(args.width, args.height),
force_library_mode=args.library,
log_level=log_level
)
# Create application
app = DReaderApplication(config)
# Run event loop
try:
logger.info("Starting event loop")
asyncio.run(hal.run_event_loop(app))
logger.info("Application exited normally")
except KeyboardInterrupt:
logger.info("Interrupted by user")
print("\nShutting down...")
except Exception as e:
logger.error(f"Application error: {e}", exc_info=True)
print(f"\nError: {e}")
print("\nFor more details, run with --log-level DEBUG")
sys.exit(1)
if __name__ == "__main__":
main()