Skip to content

Commit ce1ee41

Browse files
Merge pull request #26 from tmaier-kettering/claude/project-review-improvements-nryvsh
Refactor API client initialization and fix Pydantic validation
2 parents b8bdfa1 + 42a2cb8 commit ce1ee41

6 files changed

Lines changed: 37 additions & 47 deletions

File tree

batch_processing/batch_creation.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from enum import Enum
1212
from io import BytesIO
1313
from typing import Optional, List
14-
import tkinter as tk
1514
from pydantic import BaseModel, ConfigDict, Field
1615

1716
from file_handling.data_conversion import make_str_enum
@@ -108,7 +107,7 @@ def generate_multi_label_batch(labels, quotes) -> BytesIO | None:
108107
labels_enum = make_str_enum("Label", labels)
109108

110109
class LabeledQuoteMulti(BaseModel):
111-
label: List[labels_enum] = Field(..., min_items=1)
110+
label: List[labels_enum] = Field(..., min_length=1)
112111
model_config = ConfigDict(use_enum_values=True, extra='forbid')
113112

114113
SCHEMA = LabeledQuoteMulti.model_json_schema()
@@ -156,7 +155,7 @@ def generate_keyword_extraction_batch(texts) -> BytesIO | None:
156155
Returns a BytesIO whose .name is set to 'batchinput.jsonl'.
157156
"""
158157
class KeywordExtraction(BaseModel):
159-
keywords: list[str] = Field(..., min_items=1)
158+
keywords: list[str] = Field(..., min_length=1)
160159
model_config = ConfigDict(extra='forbid')
161160

162161
SCHEMA = KeywordExtraction.model_json_schema()

file_handling/data_import.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -360,17 +360,6 @@ def _initial_blank_preview():
360360
_fill_preview_rows([[""] * 5 for _ in range(5)])
361361
_update_dataset_name_preview()
362362

363-
def _current_header_labels() -> list[str]:
364-
# Return the labels currently shown atop the preview
365-
return [tree.heading(cid)["text"] for cid in tree["columns"]]
366-
367-
def _selected_header_label() -> str:
368-
labels = _current_header_labels()
369-
idx = selected_col.get()
370-
if 0 <= idx < len(labels):
371-
return str(labels[idx])
372-
return ""
373-
374363
def _update_dataset_name_controls_enabled():
375364
# Enable/disable "selected column header" radio based on has_headers + data present
376365
has_data = bool(_loaded_rows)

live_processing/keyword_extraction_live.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,28 @@
88

99
from typing import Optional
1010
import tkinter as tk
11+
from tkinter import messagebox
1112
from pydantic import BaseModel, ValidationError, Field, ConfigDict
12-
from openai import OpenAI
1313
from file_handling.data_import import import_data
1414
from file_handling.data_conversion import save_as_csv, to_long_df
15-
from settings import secrets_store, config
15+
from settings import config
16+
from batch_processing.batch_method import get_client
1617

1718
# Progress UI lives in a separate module
1819
from ui.progress_ui import ProgressController
1920

20-
# Initialize OpenAI client with stored API key
21-
try:
22-
OPENAI_API_KEY = secrets_store.load_api_key()
23-
client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None
24-
except Exception:
25-
OPENAI_API_KEY = None
26-
client = None
27-
2821

2922
def keyword_extraction_pipeline(parent: Optional[tk.Misc] = None):
3023
"""
3124
Prompt for quotes CSVs, extract keywords from each quote,
3225
show progress, then save results to CSV.
3326
"""
27+
try:
28+
client = get_client()
29+
except Exception as e:
30+
messagebox.showerror("API Key Required", str(e))
31+
return
32+
3433
# Get quotes data
3534
from_import = import_data(parent, "Select the quotes data")
3635
if from_import is None:
@@ -40,7 +39,7 @@ def keyword_extraction_pipeline(parent: Optional[tk.Misc] = None):
4039
class KeywordExtraction(BaseModel):
4140
id: int | None = None
4241
quote: str
43-
keywords: list[str] = Field(..., min_items=1)
42+
keywords: list[str] = Field(..., min_length=1)
4443
model_config = ConfigDict()
4544

4645
total = len(quotes)

live_processing/multi_label_live.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,28 @@
88

99
from typing import Optional, List
1010
import tkinter as tk
11+
from tkinter import messagebox
1112
from pydantic import BaseModel, ValidationError, Field, ConfigDict
12-
from openai import OpenAI
1313
from file_handling.data_import import import_data
1414
from file_handling.data_conversion import make_str_enum, save_as_csv, to_long_df
15-
from settings import secrets_store, config
15+
from settings import config
16+
from batch_processing.batch_method import get_client
1617

1718
# Progress UI lives in a separate module
1819
from ui.progress_ui import ProgressController
1920

20-
# Initialize OpenAI client with stored API key
21-
try:
22-
OPENAI_API_KEY = secrets_store.load_api_key()
23-
client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None
24-
except Exception:
25-
OPENAI_API_KEY = None
26-
client = None
27-
2821

2922
def multi_label_pipeline(parent: Optional[tk.Misc] = None):
3023
"""
3124
Prompt for labels/quotes CSVs, classify each quote with 1+ labels,
3225
show progress, then save results to CSV.
3326
"""
27+
try:
28+
client = get_client()
29+
except Exception as e:
30+
messagebox.showerror("API Key Required", str(e))
31+
return
32+
3433
# Get labels data
3534
from_import = import_data(parent, "Select the labels data")
3635
if from_import is None:
@@ -47,7 +46,7 @@ def multi_label_pipeline(parent: Optional[tk.Misc] = None):
4746
class LabeledQuoteMulti(BaseModel):
4847
id: int | None = None
4948
quote: str
50-
label: List[labels] = Field(..., min_items=1)
49+
label: List[labels] = Field(..., min_length=1)
5150
model_config = ConfigDict(use_enum_values=True, extra='forbid')
5251

5352
total = len(quotes)

live_processing/single_label_live.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,28 @@
88

99
from typing import Optional
1010
import tkinter as tk
11+
from tkinter import messagebox
1112
from pydantic import BaseModel, ValidationError, Field, ConfigDict
12-
from openai import OpenAI
1313
from file_handling.data_import import import_data
1414
from file_handling.data_conversion import make_str_enum, save_as_csv, to_long_df
15-
from settings import secrets_store, config
15+
from settings import config
16+
from batch_processing.batch_method import get_client
1617

1718
# Progress UI lives in a separate module
1819
from ui.progress_ui import ProgressController
1920

20-
# Initialize OpenAI client with stored API key
21-
try:
22-
OPENAI_API_KEY = secrets_store.load_api_key()
23-
client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None
24-
except Exception:
25-
OPENAI_API_KEY = None
26-
client = None
27-
2821

2922
def single_label_pipeline(parent: Optional[tk.Misc] = None):
3023
"""
3124
Prompt for labels/quotes CSVs, classify each quote with exactly one label,
3225
show progress, then save results to CSV.
3326
"""
27+
try:
28+
client = get_client()
29+
except Exception as e:
30+
messagebox.showerror("API Key Required", str(e))
31+
return
32+
3433
# Get labels data
3534
from_import = import_data(parent, "Select the labels data")
3635
if from_import is None:

ui/main_window.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,12 @@ def build_ui(root: tk.Tk) -> None:
9292
root: The main Tkinter window to build the UI in
9393
"""
9494
root.title(APP_TITLE)
95-
root.iconbitmap(asset_path("app.ico"))
95+
try:
96+
# .ico files are only natively supported by iconbitmap on Windows;
97+
# this raises TclError on Linux/macOS Tk builds.
98+
root.iconbitmap(asset_path("app.ico"))
99+
except tk.TclError:
100+
pass
96101

97102
# ===== Top-level grid: header, spacer, table area =====
98103
root.columnconfigure(0, weight=1)

0 commit comments

Comments
 (0)