Refactor imports and improve logging in multiple modules; streamline type hints and remove redundant code
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(override=True)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
26
src/main.py
26
src/main.py
@@ -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.")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user