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
7 changes: 3 additions & 4 deletions app/community_prs.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
fetch_pr_info,
get_all_github_prs,
)
from app.utils.streamlit_date_input import normalize_date_range

st.set_page_config(
page_title="Community PRs",
Expand Down Expand Up @@ -205,10 +206,8 @@ def get_change_types(labels: list) -> list[str]:
max_value=max_date,
)

# Filter data based on selected date range
# date_input can return () or (start,) or (start, end) depending on user input
start_date = date_range[0] if len(date_range) > 0 else None
end_date = date_range[1] if len(date_range) > 1 else None
# Streamlit can temporarily return partial tuples while a range is being edited.
start_date, end_date = normalize_date_range(date_range)
if start_date and end_date:
df_filtered = all_prs_df[
(all_prs_df["created_at"].dt.date >= start_date) & (all_prs_df["created_at"].dt.date <= end_date)
Expand Down
6 changes: 5 additions & 1 deletion app/flaky_tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import math
from collections import Counter
from datetime import date, datetime
from typing import Any
Expand Down Expand Up @@ -144,7 +145,10 @@ def extract_browser(test_name: str) -> str | None:
else:
flaky_tests_df["Workflow Failure Probability"] = float("nan")

overall_failure_prob: float = 1 - (1 - flaky_tests_df["Workflow Failure Probability"].fillna(0).astype(float)).prod() # type: ignore[operator,assignment]
workflow_failure_probabilities = [
float(probability) for probability in flaky_tests_df["Workflow Failure Probability"].fillna(0).tolist()
]
overall_failure_prob = 1.0 - math.prod(1.0 - probability for probability in workflow_failure_probabilities)


total_flaky_failures = int(flaky_tests_df["Failures"].sum())
Expand Down
13 changes: 8 additions & 5 deletions app/github_issue_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,15 @@ def _format_issue_record(
if "issues_state" not in st.session_state:
st.session_state["issues_state"] = "all"

issue_state_options: tuple[IssueState, IssueState, IssueState] = ("open", "closed", "all")
saved_issue_state = st.session_state["issues_state"]
default_issue_state: IssueState = saved_issue_state if saved_issue_state in issue_state_options else "all"

with st.form("issue_download_form"):
issue_state = st.selectbox(
issue_state: IssueState = st.selectbox(
"Issue state",
options=["open", "closed", "all"],
index=["open", "closed", "all"].index(st.session_state["issues_state"]),
options=issue_state_options,
index=issue_state_options.index(default_issue_state),
help="GitHub issues state to fetch.",
)
include_prs = st.checkbox(
Expand All @@ -101,8 +105,7 @@ def _format_issue_record(

if submit:
with st.spinner("Fetching issues from GitHub…"):
# Cast is safe because selectbox options are limited to these values
raw_issues = _fetch_issue_data(issue_state) # type: ignore[arg-type]
raw_issues = _fetch_issue_data(issue_state)

records: list[dict[str, object]] = []
for issue in raw_issues:
Expand Down
7 changes: 3 additions & 4 deletions app/issue_reactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from app.utils.github_utils import get_all_github_issues
from app.utils.issue_formatting import get_issue_type, reactions_to_str
from app.utils.streamlit_date_input import normalize_date_range

DEFAULT_ISSUES_FOLDER = "issues"
PATH_OF_SCRIPT = pathlib.Path(__file__).parent.resolve()
Expand Down Expand Up @@ -56,10 +57,8 @@
# Filter who closed the issue:
closed_by_filter = st.text_input("Closed by", value=st.query_params.get("closed_by", ""))

# Filter data based on selected date range
# date_input can return () or (start,) or (start, end) depending on user input
start_date = date_range[0] if len(date_range) > 0 else None
end_date = date_range[1] if len(date_range) > 1 else None
# Streamlit can temporarily return partial tuples while a range is being edited.
start_date, end_date = normalize_date_range(date_range)
if start_date and end_date:
df_filtered = all_issues_df[
(all_issues_df["closed_at"].dt.date >= start_date) & (all_issues_df["closed_at"].dt.date <= end_date)
Expand Down
11 changes: 6 additions & 5 deletions app/perf/utils/test_diff_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ def _extract_react_profile_metrics(
stable_test_name (str): Stable test name.
"""
phase_data = all_phases[index][react_profile_key][phase]
metrics = phase_data.keys()
for metric in metrics:
key = f"{react_profile_key}__{phase}__{metric}"
phase_metrics = (
("duration_ms", phase_data["duration_ms"]),
("count", phase_data["count"]),
)
for metric_name, metric_value in phase_metrics:
key = f"{react_profile_key}__{phase}__{metric_name}"
if key not in results_per_test[stable_test_name]:
results_per_test[stable_test_name][key] = []
# Access by variable key - cast to handle TypedDict limitations
metric_value: float | int = phase_data[metric] # type: ignore[literal-required]
results_per_test[stable_test_name][key].append(metric_value)


Expand Down
4 changes: 2 additions & 2 deletions app/utils/github_graphql_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ def _extract_pr_metrics(
for review in all_reviews:
author_info = review.get("author") or {}
login = author_info.get("login")
if _is_human_reviewer(author_info.get("__typename", ""), login, ignore_bots):
reviewer_logins.add(login) # type: ignore[arg-type]
if login and _is_human_reviewer(author_info.get("__typename", ""), login, ignore_bots):
reviewer_logins.add(login)

reviewers = sorted(reviewer_logins)

Expand Down
15 changes: 11 additions & 4 deletions app/utils/github_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import json
import urllib.parse
from io import BytesIO
from typing import TYPE_CHECKING, Any, Final, Literal, cast
from typing import TYPE_CHECKING, Any, Final, Literal, Protocol, cast
from zipfile import ZipFile

import requests
import streamlit as st

if TYPE_CHECKING:
from collections.abc import Iterator
from collections.abc import Callable, Iterator
from datetime import date

# Streamlit team members:
Expand Down Expand Up @@ -165,6 +165,12 @@ def __init__(self, message: str, partial_data: Any) -> None:
self.partial_data = partial_data


class _PullRequestFilesPayloadFetcher(Protocol):
def __call__(self, repo: str, pr_number: int) -> tuple[list[dict[str, Any]], str | None]: ...

clear: Callable[..., None]


@st.cache_data(ttl=60 * 10, max_entries=256, show_spinner=False)
def fetch_issue_payload(repo: str, issue_number: int | str) -> tuple[dict[str, Any] | None, str | None]:
"""Fetch issue payload and return (data, error_message)."""
Expand Down Expand Up @@ -351,15 +357,16 @@ def _fetch_pull_request_files_payload_cached(repo: str, pr_number: int) -> list[
return files


def fetch_pull_request_files_payload(repo: str, pr_number: int) -> tuple[list[dict[str, Any]], str | None]:
def _fetch_pull_request_files_payload(repo: str, pr_number: int) -> tuple[list[dict[str, Any]], str | None]:
"""Fetch all changed files for a pull request."""
try:
return _fetch_pull_request_files_payload_cached(repo, pr_number), None
except _PartialDataError as exc:
return cast("list[dict[str, Any]]", exc.partial_data), str(exc)


fetch_pull_request_files_payload.clear = _fetch_pull_request_files_payload_cached.clear # type: ignore[attr-defined]
fetch_pull_request_files_payload = cast("_PullRequestFilesPayloadFetcher", _fetch_pull_request_files_payload)
fetch_pull_request_files_payload.clear = _fetch_pull_request_files_payload_cached.clear


@st.cache_data(ttl=300, max_entries=256, show_spinner=False)
Expand Down
18 changes: 18 additions & 0 deletions app/utils/streamlit_date_input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import annotations

from datetime import date

type DateInputValue = date | tuple[()] | tuple[date] | tuple[date, date]


def normalize_date_range(date_input_value: DateInputValue) -> tuple[date | None, date | None]:
"""Normalize a Streamlit date_input value into a start/end tuple."""
match date_input_value:
case (start_date, end_date):
return start_date, end_date
case (start_date,):
return start_date, None
case _ if isinstance(date_input_value, date):
return date_input_value, date_input_value
case _:
return None, None
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ default-groups = ["dev"]
dev = [
"pytest>=9.0.2",
"ruff==0.15.12",
"ty==0.0.12",
"ty==0.0.34",
"mypy==1.20.2",
"watchdog",
"pandas-stubs",
Expand Down
43 changes: 21 additions & 22 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.