Refactor imports and improve logging in multiple modules; streamline type hints and remove redundant code

This commit is contained in:
William Valentin
2025-07-28 12:37:43 -07:00
parent 8e03f105b0
commit 8a0b4fcdf2
7 changed files with 71 additions and 78 deletions

View File

@@ -1,4 +1,5 @@
import os
from dotenv import load_dotenv
load_dotenv(override=True)

View File

@@ -1,7 +1,6 @@
import os
import csv
import logging
from typing import List, Union
import os
import pandas as pd
@@ -36,13 +35,8 @@ class DataManager:
def load_data(self) -> pd.DataFrame:
"""Load data from CSV file."""
if (
not os.path.exists(self.filename)
or os.path.getsize(self.filename) == 0
):
self.logger.warning(
"CSV file is empty or doesn't exist. No data to load."
)
if not os.path.exists(self.filename) or os.path.getsize(self.filename) == 0:
self.logger.warning("CSV file is empty or doesn't exist. No data to load.")
return pd.DataFrame()
try:
@@ -69,7 +63,7 @@ class DataManager:
self.logger.error(f"Error loading data: {str(e)}")
return pd.DataFrame()
def add_entry(self, entry_data: List[Union[str, int]]) -> bool:
def add_entry(self, entry_data: list[str | int]) -> bool:
"""Add a new entry to the CSV file."""
try:
with open(self.filename, mode="a", newline="") as file:
@@ -80,7 +74,7 @@ class DataManager:
self.logger.error(f"Error adding entry: {str(e)}")
return False
def update_entry(self, date: str, values: List[Union[str, int]]) -> bool:
def update_entry(self, date: str, values: list[str | int]) -> bool:
"""Update an existing entry identified by date."""
try:
df: pd.DataFrame = self.load_data()

View File

@@ -1,11 +1,11 @@
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.axes import Axes
from tkinter import ttk
import tkinter as tk
from typing import Dict
from tkinter import ttk
import matplotlib.figure
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.axes import Axes
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class GraphManager:
@@ -19,7 +19,7 @@ class GraphManager:
self.parent_frame.grid_columnconfigure(0, weight=1)
# Initialize toggle variables for chart elements
self.toggle_vars: Dict[str, tk.BooleanVar] = {
self.toggle_vars: dict[str, tk.BooleanVar] = {
"depression": tk.BooleanVar(value=True),
"anxiety": tk.BooleanVar(value=True),
"sleep": tk.BooleanVar(value=True),

View File

@@ -1,6 +1,7 @@
import os
from constants import LOG_CLEAR, LOG_LEVEL, LOG_PATH
from logger import init_logger
from constants import LOG_PATH, LOG_CLEAR, LOG_LEVEL
if not os.path.exists(LOG_PATH):
try:

View File

@@ -1,20 +1,16 @@
import logging
import colorlog
from constants import LOG_PATH
def init_logger(dunder_name, testing_mode) -> logging.Logger:
log_format = (
"%(asctime)s - "
"%(name)s - "
"%(funcName)s - "
"%(levelname)s - "
"%(message)s"
)
log_format = "%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s"
""" Initialize logging """
bold_seq = "\033[1m"
colorlog_format = f"{bold_seq} " "%(log_color)s " f"{log_format}"
colorlog_format = f"{bold_seq} %(log_color)s {log_format}"
colorlog.basicConfig(format=colorlog_format)
logger = logging.getLogger(dunder_name)

View File

@@ -1,15 +1,16 @@
import os
import sys
import tkinter as tk
from collections.abc import Callable
from tkinter import messagebox
from typing import Dict, List, Tuple, Any, Callable, Union
from typing import Any
import pandas as pd
from init import logger
from constants import LOG_LEVEL, LOG_PATH
from data_manager import DataManager
from graph_manager import GraphManager
from init import logger
from ui_manager import UIManager
@@ -31,7 +32,8 @@ class MedTrackerApp:
logger.info(f"Using data file: {first_argument}")
else:
logger.warning(
f"Data file {first_argument} does not exist. Using default file: {self.filename}"
f"Data file {first_argument} doesn't exist. \
Using default file: {self.filename}"
)
if LOG_LEVEL == "DEBUG":
@@ -75,10 +77,10 @@ class MedTrackerApp:
self.graph_manager: GraphManager = GraphManager(graph_frame)
# --- Create Input Frame ---
input_ui: Dict[str, Any] = self.ui_manager.create_input_frame(main_frame)
input_ui: dict[str, Any] = self.ui_manager.create_input_frame(main_frame)
self.input_frame: ttk.Frame = input_ui["frame"]
self.symptom_vars: Dict[str, tk.IntVar] = input_ui["symptom_vars"]
self.medicine_vars: Dict[str, List[Union[tk.IntVar, ttk.Spinbox]]] = input_ui[
self.symptom_vars: dict[str, tk.IntVar] = input_ui["symptom_vars"]
self.medicine_vars: dict[str, list[tk.IntVar | ttk.Spinbox]] = input_ui[
"medicine_vars"
]
self.note_var: tk.StringVar = input_ui["note_var"]
@@ -99,7 +101,7 @@ class MedTrackerApp:
)
# --- Create Table Frame ---
table_ui: Dict[str, Any] = self.ui_manager.create_table_frame(main_frame)
table_ui: dict[str, Any] = self.ui_manager.create_table_frame(main_frame)
self.tree: ttk.Treeview = table_ui["tree"]
self.tree.bind("<Double-1>", self.on_double_click)
@@ -115,10 +117,10 @@ class MedTrackerApp:
logger.debug(f"Editing item_id={item_id}, values={item_values}")
self._create_edit_window(item_id, item_values)
def _create_edit_window(self, item_id: str, values: Tuple[str, ...]) -> None:
def _create_edit_window(self, item_id: str, values: tuple[str, ...]) -> None:
"""Create a new Toplevel window for editing an entry."""
# Define callbacks for edit window buttons
callbacks: Dict[str, Callable] = {
callbacks: dict[str, Callable] = {
"save": self._save_edit,
"delete": lambda win: self._delete_entry(win, item_id),
}
@@ -141,7 +143,7 @@ class MedTrackerApp:
note: str,
) -> None:
"""Save the edited data to the CSV file."""
values: List[Union[str, int]] = [
values: list[str | int] = [
date,
dep,
anx,
@@ -173,7 +175,7 @@ class MedTrackerApp:
def add_entry(self) -> None:
"""Add a new entry to the CSV file."""
entry: List[Union[str, int]] = [
entry: list[str | int] = [
self.date_var.get(),
self.symptom_vars["depression"].get(),
self.symptom_vars["anxiety"].get(),
@@ -240,7 +242,7 @@ class MedTrackerApp:
# Update the treeview with the data
if not df.empty:
for index, row in df.iterrows():
for _index, row in df.iterrows():
self.tree.insert(parent="", index="end", values=list(row))
logger.debug(f"Loaded {len(df)} entries into treeview.")

View File

@@ -1,10 +1,12 @@
from datetime import datetime
import os
import logging
import os
import sys
import tkinter as tk
from collections.abc import Callable
from datetime import datetime
from tkinter import ttk
from typing import Dict, List, Tuple, Any, Callable, Union
from typing import Any
from PIL import Image, ImageTk
@@ -20,22 +22,19 @@ class UIManager:
try:
self.logger.info(f"Trying to load icon from: {img_path}")
# Try to find the icon in various locations
if not os.path.exists(img_path):
# Check if we're in PyInstaller bundle
if hasattr(sys, "_MEIPASS"):
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path: str = sys._MEIPASS
potential_paths: List[str] = [
os.path.join(base_path, os.path.basename(img_path)),
os.path.join(base_path, "chart-671.png"),
]
for path in potential_paths:
if os.path.exists(path):
self.logger.info(
f"Found icon in PyInstaller bundle: {path}"
)
img_path = path
break
# Check if we're in PyInstaller bundle
if not os.path.exists(img_path) and hasattr(sys, "_MEIPASS"):
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path: str = sys._MEIPASS
potential_paths: list[str] = [
os.path.join(base_path, os.path.basename(img_path)),
os.path.join(base_path, "chart-671.png"),
]
for path in potential_paths:
if os.path.exists(path):
self.logger.info(f"Found icon in PyInstaller bundle: {path}")
img_path = path
break
icon_image: Image.Image = Image.open(img_path)
icon_image = icon_image.resize(
@@ -52,14 +51,14 @@ class UIManager:
self.logger.error(f"Error setting icon: {str(e)}")
return False
def create_input_frame(self, parent_frame: ttk.Frame) -> Dict[str, Any]:
def create_input_frame(self, parent_frame: ttk.Frame) -> dict[str, Any]:
"""Create and configure the input frame with all widgets."""
input_frame: ttk.LabelFrame = ttk.LabelFrame(parent_frame, text="New Entry")
input_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")
input_frame.grid_columnconfigure(1, weight=1)
# Create variables for symptoms
symptom_vars: Dict[str, tk.IntVar] = {
symptom_vars: dict[str, tk.IntVar] = {
"depression": tk.IntVar(value=0),
"anxiety": tk.IntVar(value=0),
"sleep": tk.IntVar(value=0),
@@ -67,7 +66,7 @@ class UIManager:
}
# Create scales for symptoms
symptom_labels: List[Tuple[str, str]] = [
symptom_labels: list[tuple[str, str]] = [
("Depression (0-10):", "depression"),
("Anxiety (0-10):", "anxiety"),
("Sleep Quality (0-10):", "sleep"),
@@ -93,14 +92,14 @@ class UIManager:
medicine_frame = ttk.LabelFrame(input_frame, text="Medicine")
medicine_frame.grid(row=4, column=1, padx=0, pady=10, sticky="nsew")
medicine_vars: Dict[str, Tuple[tk.IntVar, str]] = {
medicine_vars: dict[str, tuple[tk.IntVar, str]] = {
"bupropion": (tk.IntVar(value=0), "Bupropion 150/300 mg"),
"hydroxyzine": (tk.IntVar(value=0), "Hydroxyzine 25mg"),
"gabapentin": (tk.IntVar(value=0), "Gabapentin 100mg"),
"propranolol": (tk.IntVar(value=0), "Propranolol 10mg"),
}
for idx, (name, (var, text)) in enumerate(medicine_vars.items()):
for idx, (_name, (var, text)) in enumerate(medicine_vars.items()):
ttk.Checkbutton(medicine_frame, text=text, variable=var).grid(
row=idx, column=0, sticky="w", padx=5, pady=2
)
@@ -135,7 +134,7 @@ class UIManager:
"date_var": date_var,
}
def create_table_frame(self, parent_frame: ttk.Frame) -> Dict[str, Any]:
def create_table_frame(self, parent_frame: ttk.Frame) -> dict[str, Any]:
"""Create and configure the table frame with a treeview."""
table_frame: ttk.LabelFrame = ttk.LabelFrame(
parent_frame, text="Log (Double-click to edit)"
@@ -146,7 +145,7 @@ class UIManager:
table_frame.grid_rowconfigure(0, weight=1)
table_frame.grid_columnconfigure(0, weight=1)
columns: List[str] = [
columns: list[str] = [
"Date",
"Depression",
"Anxiety",
@@ -161,7 +160,7 @@ class UIManager:
tree: ttk.Treeview = ttk.Treeview(table_frame, columns=columns, show="headings")
col_labels: List[str] = [
col_labels: list[str] = [
"Date",
"Depression",
"Anxiety",
@@ -174,10 +173,10 @@ class UIManager:
"Note",
]
for col, label in zip(columns, col_labels):
for col, label in zip(columns, col_labels, strict=False):
tree.heading(col, text=label)
col_settings: List[Tuple[str, int, str]] = [
col_settings: list[tuple[str, int, str]] = [
("Date", 80, "center"),
("Depression", 80, "center"),
("Anxiety", 80, "center"),
@@ -209,7 +208,7 @@ class UIManager:
return graph_frame
def add_buttons(
self, frame: ttk.Frame, buttons_config: List[Dict[str, Any]]
self, frame: ttk.Frame, buttons_config: list[dict[str, Any]]
) -> ttk.Frame:
"""Add buttons to a frame based on configuration."""
button_frame: ttk.Frame = ttk.Frame(frame)
@@ -230,7 +229,7 @@ class UIManager:
return button_frame
def create_edit_window(
self, values: Tuple[str, ...], callbacks: Dict[str, Callable]
self, values: tuple[str, ...], callbacks: dict[str, Callable]
) -> tk.Toplevel:
"""Create a new window for editing an entry."""
edit_win: tk.Toplevel = tk.Toplevel(master=self.root)
@@ -283,9 +282,9 @@ class UIManager:
anx: int,
slp: int,
app: int,
) -> Dict[str, Union[tk.StringVar, tk.IntVar]]:
) -> dict[str, tk.StringVar | tk.IntVar]:
"""Create fields for editing entry values."""
vars_dict: Dict[str, Union[tk.StringVar, tk.IntVar]] = {}
vars_dict: dict[str, tk.StringVar | tk.IntVar] = {}
# Ensure values are converted to appropriate types
try:
@@ -377,7 +376,7 @@ class UIManager:
hydro: int,
gaba: int,
prop: int,
) -> Dict[str, tk.IntVar]:
) -> dict[str, tk.IntVar]:
"""Create medicine checkboxes in the edit window."""
ttk.Label(parent, text="Treatment:").grid(
row=row, column=0, sticky="w", padx=5, pady=2
@@ -385,14 +384,14 @@ class UIManager:
medicine_frame: ttk.LabelFrame = ttk.LabelFrame(parent, text="Medicine")
medicine_frame.grid(row=row, column=1, padx=0, pady=10, sticky="nsew")
medicine_vars: Dict[str, Tuple[int, str]] = {
medicine_vars: dict[str, tuple[int, str]] = {
"bupropion": (bup, "Bupropion 150/300 mg"),
"hydroxyzine": (hydro, "Hydroxyzine 25mg"),
"gabapentin": (gaba, "Gabapentin 100mg"),
"propranolol": (prop, "Propranolol 10mg"),
}
vars_dict: Dict[str, tk.IntVar] = {}
vars_dict: dict[str, tk.IntVar] = {}
for idx, (key, (value, label)) in enumerate(medicine_vars.items()):
vars_dict[key] = tk.IntVar(value=int(value))
ttk.Checkbutton(medicine_frame, text=label, variable=vars_dict[key]).grid(
@@ -405,8 +404,8 @@ class UIManager:
self,
parent: tk.Toplevel,
row: int,
vars_dict: Dict[str, Any],
callbacks: Dict[str, Callable],
vars_dict: dict[str, Any],
callbacks: dict[str, Callable],
) -> None:
"""Add buttons to the edit window."""
button_frame: ttk.Frame = ttk.Frame(parent)