From 76277f876c6de71b7994086e19740a091ceac437 Mon Sep 17 00:00:00 2001 From: matt Date: Fri, 17 Jan 2025 18:04:29 -0800 Subject: [PATCH] Adjusted logging across the files --- .gitignore | 11 ++++++++--- builder_utils.py | 32 ++++++++++++++++++++++++++++---- card_info.py | 44 -------------------------------------------- deck_builder.py | 40 +++++++++++++++++++++++++++++++--------- input_handler.py | 33 ++++++++++++++++++++++++++++----- main.py | 47 ++++++++++++++++++++++++++++++++--------------- main.spec | 44 -------------------------------------------- price_check.py | 43 +++++++++++++++++++++++++++++++------------ settings.py | 1 + setup.py | 31 +++++++++++++++++++++++-------- setup_utils.py | 31 +++++++++++++++++++++++-------- tagger.py | 31 +++++++++++++++++++++++-------- 12 files changed, 228 insertions(+), 160 deletions(-) delete mode 100644 card_info.py delete mode 100644 main.spec diff --git a/.gitignore b/.gitignore index 48bb90f..5dd3421 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,12 @@ *.json *.log *.txt -!requirements.txt -test.py .mypy_cache/ -__pycache__/ \ No newline at end of file +test.py +main.spec +!requirements.txt +__pycache__/ +build/ +csv_files/ +dist/ +logs/ \ No newline at end of file diff --git a/builder_utils.py b/builder_utils.py index 6d0151f..951c7fd 100644 --- a/builder_utils.py +++ b/builder_utils.py @@ -29,6 +29,7 @@ Typical usage example: # Standard library imports import functools import logging +import os import time from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast @@ -72,12 +73,35 @@ from settings import ( ) from type_definitions import CardLibraryDF, CommanderDF, LandDF -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s' -) +# Create logs directory if it doesn't exist +if not os.path.exists('logs'): + os.makedirs('logs') +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/builder_utils.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) + # Type variables for generic functions T = TypeVar('T') DataFrame = TypeVar('DataFrame', bound=pd.DataFrame) diff --git a/card_info.py b/card_info.py deleted file mode 100644 index 48ef7e9..0000000 --- a/card_info.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import annotations - -import inquirer.prompt # type: ignore -import pandas as pd # type: ignore -import pprint - -from fuzzywuzzy import fuzz, process # type: ignore -from IPython.display import display - -pd.set_option('display.max_colwidth', None) -pd.set_option('display.expand_frame_repr', True) -pd.options.mode.chained_assignment = None - -def get_card_info(): - question = [ - inquirer.Text( - 'card_prompt', - message='Enter a card name:' - ) - ] - answer = inquirer.prompt(question) - card_choice = answer['card_prompt'] - - df = pd.read_csv('csv_files/cards.csv', low_memory=False) - fuzzy_card_choice = process.extractOne(card_choice, df['name'], scorer=fuzz.ratio) - fuzzy_card_choice = fuzzy_card_choice[0] - filtered_df = df[df['name'] == fuzzy_card_choice] - columns_to_keep = ['name', 'colorIdentity', 'colors', 'manaCost', 'manaValue', 'type', 'keywords', 'power', 'toughness', 'text'] - filtered_df = filtered_df[filtered_df['layout'].str.contains('reversible_card') == False] - filtered_df = filtered_df[filtered_df['availability'].str.contains('arena') == False] - filtered_df.drop_duplicates(subset='name', keep='first', inplace=True) - filtered_df = filtered_df[columns_to_keep].astype('string') - columns_to_keep = ['name', 'colorIdentity', 'colors', 'manaCost', 'manaValue', 'type', 'keywords', 'power', 'toughness'] - filtered_df_no_text = filtered_df[columns_to_keep] - filtered_df_no_text.dropna(how='all', axis=1, inplace=True) - df_dict = filtered_df.to_dict('list') - - pprint.pprint(df_dict, sort_dicts=False) - - - pprint.pprint(filtered_df_no_text) - pprint.pprint(filtered_df['text']) - -#get_card_info() \ No newline at end of file diff --git a/deck_builder.py b/deck_builder.py index 9c44d86..10cd5c7 100644 --- a/deck_builder.py +++ b/deck_builder.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging import math import numpy as np +import os import random import time from functools import lru_cache @@ -20,7 +21,7 @@ from settings import ( COMMANDER_CSV_PATH, FUZZY_MATCH_THRESHOLD, MAX_FUZZY_CHOICES, FETCH_LAND_DEFAULT_COUNT, COMMANDER_POWER_DEFAULT, COMMANDER_TOUGHNESS_DEFAULT, COMMANDER_MANA_COST_DEFAULT, COMMANDER_MANA_VALUE_DEFAULT, COMMANDER_TYPE_DEFAULT, COMMANDER_TEXT_DEFAULT, - THEME_PRIORITY_BONUS, THEME_POOL_SIZE_MULTIPLIER, + THEME_PRIORITY_BONUS, THEME_POOL_SIZE_MULTIPLIER, DECK_DIRECTORY, COMMANDER_COLOR_IDENTITY_DEFAULT, COMMANDER_COLORS_DEFAULT, COMMANDER_TAGS_DEFAULT, COMMANDER_THEMES_DEFAULT, COMMANDER_CREATURE_TYPES_DEFAULT, DUAL_LAND_TYPE_MAP, CSV_READ_TIMEOUT, CSV_PROCESSING_BATCH_SIZE, CSV_VALIDATION_RULES, CSV_REQUIRED_COLUMNS, @@ -89,12 +90,34 @@ except ImportError: logging.warning("Scrython is not installed. Price checking features will be unavailable." ) -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s' -) +# Create logs directory if it doesn't exist +if not os.path.exists('logs'): + os.makedirs('logs') +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/deck_builder.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) pd.set_option('display.max_columns', None) pd.set_option('display.max_rows', None) @@ -480,9 +503,7 @@ class DeckBuilder: self.fill_out_deck() # Process and organize deck - self.card_library.to_csv(f'{CSV_DIRECTORY}/test_deck_presort.csv', index=False) self.organize_library() - self.card_library.to_csv(f'{CSV_DIRECTORY}/test_deck_preconcat.csv', index=False) # Log deck composition self._log_deck_composition() @@ -496,8 +517,9 @@ class DeckBuilder: self.commander_to_top() # Save final deck - self.card_library.to_csv(f'{CSV_DIRECTORY}/test_deck_done.csv', index=False) - self.full_df.to_csv(f'{CSV_DIRECTORY}/test_all_after_done.csv', index=False) + FILE_TIME = time.strftime("%Y%m%d-%H%M%S") + DECK_FILE = f'{self.commander}_{FILE_TIME}.csv' + self.card_library.to_csv(f'{DECK_DIRECTORY}/{DECK_FILE}', index=False) except Exception as e: raise DeckBuilderError(f"Failed to initialize deck building: {str(e)}") diff --git a/input_handler.py b/input_handler.py index 8e96934..db473dc 100644 --- a/input_handler.py +++ b/input_handler.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +import os from typing import Any, List, Optional, Tuple, Union import inquirer.prompt @@ -28,13 +29,35 @@ from exceptions import ( PriceValidationError ) -# Configure logging -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s' -) +# Create logs directory if it doesn't exist +if not os.path.exists('logs'): + os.makedirs('logs') +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/input_handler.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) + class InputHandler: """Handles user input operations with validation and error handling. diff --git a/main.py b/main.py index c2ad686..f33571c 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,10 @@ +"""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. +""" from __future__ import annotations # Standard library imports @@ -15,26 +22,34 @@ import deck_builder import setup import tagger -"""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. -""" # Create logs directory if it doesn't exist if not os.path.exists('logs'): os.makedirs('logs') -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.StreamHandler(), - logging.FileHandler('logs/main.log', mode='a', encoding='utf-8') - ] -) +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = os.path.join(LOG_DIR, 'main.log') +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) # Menu constants MENU_SETUP = 'Setup' @@ -93,6 +108,8 @@ def run_menu() -> NoReturn: """ logger.info("Starting MTG Python Deckbuilder") Path('csv_files').mkdir(parents=True, exist_ok=True) + Path('deck_files').mkdir(parents=True, exist_ok=True) + Path('logs').mkdir(parents=True, exist_ok=True) while True: try: diff --git a/main.spec b/main.spec deleted file mode 100644 index f46a5cd..0000000 --- a/main.spec +++ /dev/null @@ -1,44 +0,0 @@ -# -*- mode: python ; coding: utf-8 -*- - - -a = Analysis( - ['C:\\Users\\Matt\\mtg_python\\mtg_python_deckbuilder\\main.py'], - pathex=[], - binaries=[], - datas=[], - hiddenimports=[], - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - noarchive=False, - optimize=0, -) -pyz = PYZ(a.pure) - -exe = EXE( - pyz, - a.scripts, - [], - exclude_binaries=True, - name='main', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, -) -coll = COLLECT( - exe, - a.binaries, - a.datas, - strip=False, - upx=True, - upx_exclude=[], - name='main', -) diff --git a/price_check.py b/price_check.py index 82acfb7..2c3cbfd 100644 --- a/price_check.py +++ b/price_check.py @@ -36,6 +36,31 @@ from settings import ( ) from type_definitions import PriceCache +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/price_check.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module +logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) + class PriceChecker: """Class for handling MTG card price checking and validation. @@ -64,12 +89,6 @@ class PriceChecker: self.max_card_price: float = max_card_price self.max_deck_price: float = max_deck_price self.current_deck_price: float = 0.0 - - # Configure logging - logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s' - ) @lru_cache(maxsize=PRICE_CACHE_SIZE) def get_card_price(self, card_name: str, attempts: int = 0) -> float: @@ -116,7 +135,7 @@ class PriceChecker: except scrython.foundation.ScryfallError as e: if attempts < MAX_PRICE_CHECK_ATTEMPTS: - logging.warning(f"Retrying price check for {card_name} (attempt {attempts + 1})") + logger.warning(f"Retrying price check for {card_name} (attempt {attempts + 1})") return self.get_card_price(card_name, attempts + 1) raise PriceAPIError(card_name, {"error": str(e)}) @@ -125,7 +144,7 @@ class PriceChecker: except Exception as e: if attempts < MAX_PRICE_CHECK_ATTEMPTS: - logging.warning(f"Unexpected error checking price for {card_name}, retrying") + logger.warning(f"Unexpected error checking price for {card_name}, retrying") return self.get_card_price(card_name, attempts + 1) raise PriceAPIError(card_name, {"error": str(e)}) @@ -184,10 +203,10 @@ class PriceChecker: results[card_name] = price except Exception as e: errors.append((card_name, e)) - logging.error(f"Error checking price for {card_name}: {e}") + logger.error(f"Error checking price for {card_name}: {e}") if errors: - logging.warning(f"Failed to get prices for {len(errors)} cards") + logger.warning(f"Failed to get prices for {len(errors)} cards") return results @@ -198,10 +217,10 @@ class PriceChecker: price: Price to add to current deck total """ self.current_deck_price += price - logging.debug(f"Updated deck price to ${self.current_deck_price:.2f}") + logger.debug(f"Updated deck price to ${self.current_deck_price:.2f}") def clear_cache(self) -> None: """Clear the price cache.""" self.price_cache.clear() self.get_card_price.cache_clear() - logging.info("Price cache cleared") \ No newline at end of file + logger.info("Price cache cleared") \ No newline at end of file diff --git a/settings.py b/settings.py index e3f9084..3a7be80 100644 --- a/settings.py +++ b/settings.py @@ -788,6 +788,7 @@ TYPE_TAG_MAPPING = { } CSV_DIRECTORY = 'csv_files' +DECK_DIRECTORY = 'deck_files' # Color identity constants and mappings diff --git a/setup.py b/setup.py index c3d3265..51b0fb4 100644 --- a/setup.py +++ b/setup.py @@ -54,15 +54,30 @@ from exceptions import ( if not os.path.exists('logs'): os.makedirs('logs') -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.StreamHandler(), - logging.FileHandler('logs/setup.log', mode='w', encoding='utf-8') - ] -) +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/setup.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) def check_csv_exists(file_path: Union[str, Path]) -> bool: """Check if a CSV file exists at the specified path. diff --git a/setup_utils.py b/setup_utils.py index 125233c..cf91b82 100644 --- a/setup_utils.py +++ b/setup_utils.py @@ -53,15 +53,30 @@ from type_definitions import CardLibraryDF if not os.path.exists('logs'): os.makedirs('logs') -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.StreamHandler(), - logging.FileHandler('logs/setup_utils.log', mode='a', encoding='utf-8') - ] -) +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/setup_utils.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) # Type definitions class FilterRule(TypedDict): diff --git a/tagger.py b/tagger.py index 2aa745e..877e518 100644 --- a/tagger.py +++ b/tagger.py @@ -44,15 +44,30 @@ PATTERN_GROUPS = { if not os.path.exists('logs'): os.makedirs('logs') -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.StreamHandler(), - logging.FileHandler('logs/tagger.log', mode='w', encoding='utf-8') - ] -) +# Logging configuration +LOG_DIR = 'logs' +LOG_FILE = f'{LOG_DIR}/tagger.log' +LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +LOG_LEVEL = logging.INFO + +# Create formatters and handlers +formatter = logging.Formatter(LOG_FORMAT) + +# File handler +file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8') +file_handler.setFormatter(formatter) + +# Stream handler +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) + +# Create logger for this module logger = logging.getLogger(__name__) +logger.setLevel(LOG_LEVEL) + +# Add handlers to logger +logger.addHandler(file_handler) +logger.addHandler(stream_handler) ### Setup ## Load the dataframe