Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
with:
Expand All @@ -34,6 +29,16 @@ jobs:
- name: Install dependencies
run: uv sync --all-extras

# `.python-version` sets the version everywhere; a Dockerfile `FROM` line
# cannot read it, so check that the two agree.
- name: Check the Dockerfile uses the pinned Python
run: |
want="FROM python:$(cat .python-version)-slim"
if ! grep -qxF "$want" Dockerfile; then
echo "::error file=Dockerfile::Expected '$want' to match .python-version"
exit 1
fi

- name: Check code formatting with Ruff
run: uv run ruff format --check .

Expand All @@ -52,11 +57,6 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
with:
Expand Down Expand Up @@ -93,11 +93,6 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
with:
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/live.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ jobs:
- uses: actions/checkout@v7

# The runner is an AL2023 host, which setup-python has no builds for, so
# uv installs Python instead.
# uv installs the Python pinned in .python-version instead.
- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
with:
python-version: '3.11'
enable-cache: true
cache-dependency-glob: uv.lock

Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ source .venv/bin/activate # Windows: .venv\Scripts\activate
cp .env.example .env # Add API keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)
```

**Python >= 3.11 required**
**Python 3.14 required.** `.python-version` is the one place the version is set: `uv`, CI, and the Dockerfile's `FROM` line all follow it.

## Code Style

Expand Down
2 changes: 1 addition & 1 deletion docs/ARCHITECTURE-SPINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ No edge runs `generate/` ↔ `judge/` ↔ `score/`, and none runs from `workers/

| Name | Version |
| --- | --- |
| Python | `>=3.11` (per `pyproject.toml` `requires-python`; ruff `target-version = "py311"`) |
| Python | `3.14`, set in `.python-version`; `requires-python` and ruff `target-version` match it |
| Package/dependency manager | uv (`uv.lock` present; CLI usage documented as `uv run python vera.py ...`) |
| langchain / langchain-anthropic / langchain-openai / langchain-ollama | `>=0.1.0` direct floor per `pyproject.toml`, but effectively constrained to the post-1.0 langchain rewrite by `[tool.uv] constraint-dependencies`' `langchain-core>=1.2.5` pin — pre-1.0 langchain is not actually installable under this lockfile despite the loose direct floor |
| langchain-google-genai / langchain-azure-ai | `>=1.0.0` |
Expand Down
2 changes: 1 addition & 1 deletion judge/question_navigator.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def _get_next_row_question(self, current_question_id: str) -> Optional[str]:
current_index = self.question_order.index(current_question_id)
if current_index + 1 < len(self.question_order):
return self.question_order[current_index + 1]
except (ValueError, AttributeError):
except ValueError, AttributeError:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird flex but ok

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, agreed, it reads oddly. It is PEP 758: from 3.14 the parentheses are optional when an except lists several exceptions without as. Ruff 3.14 formatting drops them, so they stay gone as long as Ruff formats the code. If the team would rather keep them, the only way is to set Ruff's target back below 3.14, which brings back the second version number this PR removes.

pass
return None

Expand Down
10 changes: 5 additions & 5 deletions judge/score_comparison_from_export_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,14 @@ def load_model_data_from_export_summary_csv(

try:
vera_score = float(row["Total score"])
except (TypeError, ValueError, KeyError):
except TypeError, ValueError, KeyError:
print(f"⚠️ Warning: Bad Total score for row Provider={model_name!r}, skip")
continue

try:
overall_bp_pct = float(row["Total % BP (scored ratings)"])
overall_hph_pct = float(row["Total % HPH (scored ratings)"])
except (TypeError, ValueError, KeyError):
except TypeError, ValueError, KeyError:
overall_bp_pct = 0.0
overall_hph_pct = 0.0

Expand All @@ -217,20 +217,20 @@ def load_model_data_from_export_summary_csv(
else:
try:
vera_dim = float(raw_v)
except (TypeError, ValueError):
except TypeError, ValueError:
vera_dim = 50.0
col_hph = f"{d} — % HPH (scored)"
col_bp = f"{d} — % BP (scored)"
hph_d = bp_d = 0.0
if col_hph in row.index and pd.notna(row[col_hph]):
try:
hph_d = float(row[col_hph])
except (TypeError, ValueError):
except TypeError, ValueError:
pass
if col_bp in row.index and pd.notna(row[col_bp]):
try:
bp_d = float(row[col_bp])
except (TypeError, ValueError):
except TypeError, ValueError:
pass
dimensions[d] = {
"vera_score": vera_dim,
Expand Down
4 changes: 2 additions & 2 deletions judge/score_viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def _safe_pie_value(value: Any) -> float:
"""Coerce aggregate percentage to a finite non-negative float for pie charts."""
try:
v = float(value)
except (TypeError, ValueError):
except TypeError, ValueError:
return 0.0
if v != v or v < 0: # NaN or negative
return 0.0
Expand All @@ -66,7 +66,7 @@ def _create_pie_chart(ax, results: Dict[str, Any]):
score_display = float(overall_vera_score)
if score_display != score_display:
score_display = 0.0
except (TypeError, ValueError):
except TypeError, ValueError:
score_display = 0.0
pie_title = (
f"Overall VERA-MH v1.2 Score: {score_display:.1f}\n\nRating Distribution"
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "vera-mh"
version = "0.1.0"
description = "Validation of Ethical and Responsible AI in Mental Health"
requires-python = ">=3.11"
requires-python = ">=3.14"
dependencies = [
"langchain>=0.1.0",
"langchain-anthropic>=1.5.6",
Expand Down Expand Up @@ -63,7 +63,8 @@ typeCheckingMode = "basic"

[tool.ruff]
line-length = 88
target-version = "py311"
# No `target-version`: ruff reads it from `requires-python`, which follows
# `.python-version`.
# Ruff 0.16's default `include` carries `*.md`, so it reformats Python code
# blocks inside Markdown. Our docs use snippets as illustrations -- pseudo-code,
# partial excerpts, and deliberately aligned trailing comments -- which the
Expand Down
2 changes: 1 addition & 1 deletion run_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def _display_path(path: str | os.PathLike[str]) -> str:
resolved = Path(path).resolve()
cwd = Path.cwd().resolve()
return str(resolved.relative_to(cwd))
except (ValueError, OSError):
except ValueError, OSError:
return str(Path(path).resolve())


Expand Down
2 changes: 1 addition & 1 deletion tests/mocks/mock_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ async def generate_structured_response(

response_data = json.loads(response_text)
return response_model(**response_data)
except (json.JSONDecodeError, ValueError, TypeError):
except json.JSONDecodeError, ValueError, TypeError:
# Create instance with mock default values
# Check if the model has example data in json_schema_extra
if hasattr(response_model, "model_config") and isinstance(
Expand Down
4 changes: 2 additions & 2 deletions utils/conversation_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def format_conversation_summary(
try:
turn_role = Role(speaker_value)
prefix = "user:" if turn_role == Role.PERSONA else "chatbot:"
except (ValueError, TypeError):
except ValueError, TypeError:
raise ValueError(f"Invalid role value '{speaker_value}' for turn {i}")

# Add the response with proper formatting
Expand Down Expand Up @@ -222,7 +222,7 @@ def build_langchain_messages(
message = AIMessage(content=text)
else:
message = HumanMessage(content=text)
except (ValueError, TypeError):
except ValueError, TypeError:
raise ValueError(
f"Invalid role value '{turn_speaker}' for turn {turn_number}"
)
Expand Down
2 changes: 1 addition & 1 deletion utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def parse_key_value_list(arg):
# https://docs.python.org/3/library/ast.html#ast.literal_eval
try:
value = ast.literal_eval(value)
except (ValueError, SyntaxError):
except ValueError, SyntaxError:
# Note: not logging the error here as we are leaving the value as a string
pass
d[key] = value
Expand Down
Loading
Loading