2024-12-04 14:22:20 -08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2025-01-14 09:06:59 -08:00
|
|
|
# Standard library imports
|
2024-12-05 12:03:06 -08:00
|
|
|
import sys
|
2025-01-13 11:35:11 -08:00
|
|
|
import logging
|
2025-01-14 10:10:30 -08:00
|
|
|
import os
|
2024-12-05 12:03:06 -08:00
|
|
|
from pathlib import Path
|
2025-01-13 11:35:11 -08:00
|
|
|
from typing import NoReturn, Optional
|
2024-12-04 16:56:03 -08:00
|
|
|
|
2025-01-14 09:06:59 -08:00
|
|
|
# Third-party imports
|
2025-01-17 17:04:02 -08:00
|
|
|
import inquirer.prompt
|
2025-01-14 09:06:59 -08:00
|
|
|
|
|
|
|
# Local imports
|
2025-01-17 17:04:02 -08:00
|
|
|
import deck_builder
|
2024-12-05 12:03:06 -08:00
|
|
|
import setup
|
2025-01-13 11:35:11 -08:00
|
|
|
import tagger
|
2024-12-04 14:22:20 -08:00
|
|
|
|
2025-01-14 09:06:59 -08:00
|
|
|
"""Command-line interface for the MTG Python Deckbuilder application.
|
|
|
|
|
|
|
|
This module provides the main menu and user interaction functionality for the
|
|
|
|
MTG Python Deckbuilder. It handles menu display, user input processing, and
|
|
|
|
routing to different application features like setup, deck building, card info
|
|
|
|
lookup and CSV file tagging.
|
|
|
|
"""
|
2025-01-14 10:10:30 -08:00
|
|
|
# Create logs directory if it doesn't exist
|
|
|
|
if not os.path.exists('logs'):
|
|
|
|
os.makedirs('logs')
|
|
|
|
|
2025-01-13 11:35:11 -08:00
|
|
|
logging.basicConfig(
|
|
|
|
level=logging.INFO,
|
|
|
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
|
|
|
handlers=[
|
|
|
|
logging.StreamHandler(),
|
2025-01-14 10:10:30 -08:00
|
|
|
logging.FileHandler('logs/main.log', mode='a', encoding='utf-8')
|
2025-01-13 11:35:11 -08:00
|
|
|
]
|
|
|
|
)
|
2025-01-14 10:10:30 -08:00
|
|
|
logger = logging.getLogger(__name__)
|
2024-12-04 14:22:20 -08:00
|
|
|
|
2025-01-13 11:35:11 -08:00
|
|
|
# Menu constants
|
|
|
|
MENU_SETUP = 'Setup'
|
|
|
|
MAIN_TAG = 'Tag CSV Files'
|
2025-01-17 17:04:02 -08:00
|
|
|
MENU_BUILD_DECK = 'Build a Deck'
|
2025-01-13 11:35:11 -08:00
|
|
|
MENU_QUIT = 'Quit'
|
|
|
|
|
2025-01-17 17:04:02 -08:00
|
|
|
MENU_CHOICES = [MENU_SETUP, MAIN_TAG, MENU_BUILD_DECK, MENU_QUIT]
|
2025-01-13 11:35:11 -08:00
|
|
|
def get_menu_choice() -> Optional[str]:
|
|
|
|
"""Display the main menu and get user choice.
|
|
|
|
|
2025-01-14 09:06:59 -08:00
|
|
|
Presents a menu of options to the user using inquirer and returns their selection.
|
|
|
|
Handles potential errors from inquirer gracefully.
|
|
|
|
|
2025-01-13 11:35:11 -08:00
|
|
|
Returns:
|
2025-01-14 09:06:59 -08:00
|
|
|
Optional[str]: The selected menu option or None if cancelled/error occurs
|
|
|
|
|
|
|
|
Example:
|
|
|
|
>>> choice = get_menu_choice()
|
|
|
|
>>> if choice == MENU_SETUP:
|
|
|
|
... setup.setup()
|
2025-01-13 11:35:11 -08:00
|
|
|
"""
|
|
|
|
question = [
|
|
|
|
inquirer.List('menu',
|
|
|
|
choices=MENU_CHOICES,
|
|
|
|
carousel=True)
|
|
|
|
]
|
|
|
|
try:
|
2025-01-17 17:04:02 -08:00
|
|
|
answer = inquirer.prompt(question)
|
2025-01-13 11:35:11 -08:00
|
|
|
return answer['menu'] if answer else None
|
|
|
|
except (KeyError, TypeError) as e:
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.error(f"Error getting menu choice: {e}")
|
2025-01-13 11:35:11 -08:00
|
|
|
return None
|
2025-01-14 10:10:30 -08:00
|
|
|
|
2025-01-13 11:35:11 -08:00
|
|
|
def run_menu() -> NoReturn:
|
2025-01-14 10:10:30 -08:00
|
|
|
"""Main menu loop with improved error handling and logger.
|
2025-01-14 09:06:59 -08:00
|
|
|
|
|
|
|
Provides the main application loop that displays the menu and handles user selections.
|
|
|
|
Creates required directories, processes menu choices, and handles errors gracefully.
|
|
|
|
Never returns normally - exits via sys.exit().
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
NoReturn: Function never returns normally
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
SystemExit: When user selects Quit option
|
|
|
|
|
|
|
|
Example:
|
|
|
|
>>> run_menu()
|
|
|
|
What would you like to do?
|
|
|
|
1. Setup
|
|
|
|
2. Build a Deck
|
|
|
|
3. Get Card Info
|
|
|
|
4. Tag CSV Files
|
|
|
|
5. Quit
|
|
|
|
"""
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.info("Starting MTG Python Deckbuilder")
|
2025-01-13 11:35:11 -08:00
|
|
|
Path('csv_files').mkdir(parents=True, exist_ok=True)
|
2024-12-26 09:38:21 -08:00
|
|
|
|
2025-01-13 11:35:11 -08:00
|
|
|
while True:
|
2024-12-26 09:38:21 -08:00
|
|
|
try:
|
2025-01-13 11:35:11 -08:00
|
|
|
print('What would you like to do?')
|
|
|
|
choice = get_menu_choice()
|
|
|
|
|
|
|
|
if choice is None:
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.info("Menu operation cancelled")
|
2024-12-26 09:38:21 -08:00
|
|
|
continue
|
|
|
|
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.info(f"User selected: {choice}")
|
2025-01-13 11:35:11 -08:00
|
|
|
|
|
|
|
match choice:
|
|
|
|
case 'Setup':
|
|
|
|
setup.setup()
|
|
|
|
case 'Tag CSV Files':
|
|
|
|
tagger.run_tagging()
|
2025-01-17 17:04:02 -08:00
|
|
|
case 'Build a Deck':
|
|
|
|
deck_builder.main()
|
2025-01-13 11:35:11 -08:00
|
|
|
case 'Quit':
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.info("Exiting application")
|
2025-01-13 11:35:11 -08:00
|
|
|
sys.exit(0)
|
|
|
|
case _:
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.warning(f"Invalid menu choice: {choice}")
|
2025-01-13 11:35:11 -08:00
|
|
|
|
|
|
|
except Exception as e:
|
2025-01-14 10:10:30 -08:00
|
|
|
logger.error(f"Unexpected error in main menu: {e}")
|
|
|
|
|
2025-01-13 11:35:11 -08:00
|
|
|
if __name__ == "__main__":
|
|
|
|
run_menu()
|