Add Handbook.md benchmark tasks

This commit is contained in:
DerekSurge
2026-06-24 12:44:34 -07:00
commit 72f9a65917
1800 changed files with 323589 additions and 0 deletions
@@ -0,0 +1,369 @@
"""Event schema enforces the supported Google Calendar mock shape."""
from datetime import UTC, datetime
import pytest
from pydantic import ValidationError
from google_calendar.models import (
Calendar,
CalendarPerson,
CalendarState,
Event,
EventAttendee,
EventDateTime,
)
from google_calendar.tools.search import _parse_event_end, _parse_event_start
def _minimal_event(**overrides: object) -> dict[str, object]:
base: dict[str, object] = {
"id": "evt-1",
"summary": "s",
"start": {"dateTime": "2025-06-01T10:00:00Z"},
"end": {"dateTime": "2025-06-01T11:00:00Z"},
}
base.update(overrides)
return base
def test_event_accepts_payload_without_created_and_updated():
event = Event.model_validate(_minimal_event())
assert event.created is None
assert event.updated is None
def test_event_rejects_unmodeled_extra_fields():
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(conferenceData={"entryPoints": []}))
def test_event_coerces_single_recurrence_string_to_list():
event = Event.model_validate(_minimal_event(recurrence="RRULE:FREQ=WEEKLY"))
assert event.recurrence == ["RRULE:FREQ=WEEKLY"]
def test_event_recurrence_requires_supported_prefix():
for recurrence in ["RRULE:FREQ=WEEKLY", "EXRULE:FREQ=WEEKLY", "RDATE:20250601", "EXDATE:20250601"]:
assert Event.model_validate(_minimal_event(recurrence=[recurrence]))
for recurrence in ["FREQ=WEEKLY", "BAD:FREQ=WEEKLY"]:
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(recurrence=[recurrence]))
def test_calendar_state_round_trips_legacy_event():
state = CalendarState.model_validate({"events": {"evt-1": _minimal_event(recurrence="RRULE:FREQ=DAILY")}})
dumped = state.model_dump(mode="json", exclude_none=True)
reloaded = CalendarState.model_validate(dumped)
assert reloaded == state
def test_calendar_state_round_trips_multi_calendar_state():
state = CalendarState.model_validate(
{
"timeZone": "America/New_York",
"events": {},
"calendars": {
"work": {
"summary": "Work",
"timeZone": "Europe/London",
"events": {"evt-1": _minimal_event()},
}
},
}
)
dumped = state.model_dump(mode="json", exclude_none=True)
assert dumped["timeZone"] == "America/New_York"
assert dumped["calendars"]["work"]["timeZone"] == "Europe/London"
assert dumped["calendars"]["work"]["events"]["evt-1"]["id"] == "evt-1"
assert CalendarState.model_validate(dumped) == state
def test_calendar_state_rejects_explicit_primary_calendar():
with pytest.raises(ValidationError):
CalendarState.model_validate(
{
"events": {"evt-1": _minimal_event()},
"calendars": {
"primary": {
"summary": "Primary",
"events": {"evt-2": _minimal_event(id="evt-2")},
}
},
}
)
def test_calendar_events_must_be_keyed_by_event_id():
with pytest.raises(ValidationError):
Calendar.model_validate(
{
"summary": "Work",
"events": {"wrong-key": _minimal_event(id="evt-1")},
}
)
with pytest.raises(ValidationError):
CalendarState.model_validate({"events": {"wrong-key": _minimal_event(id="evt-1")}})
def test_calendar_time_zone_is_validated():
assert Calendar.model_validate({"summary": "Work", "timeZone": "America/Los_Angeles"})
with pytest.raises(ValidationError):
Calendar.model_validate({"summary": "Work", "timeZone": "Not/AZone"})
with pytest.raises(ValidationError):
CalendarState.model_validate({"timeZone": "Not/AZone"})
@pytest.mark.parametrize(
"payload",
[
{"dateTime": "2025-06-01T10:00:00Z"},
{"dateTime": "2025-06-01T10:00:00-04:00"},
{"dateTime": "2025-06-01T10:00:00.123Z"},
{"dateTime": "2025-06-01T10:00:00", "timeZone": "America/New_York"},
{"dateTime": "2025-06-01T10:00:00-04:00", "timeZone": "America/New_York"},
{"date": "2025-06-01"},
],
)
def test_event_datetime_accepts_google_calendar_shapes(payload):
assert EventDateTime.model_validate(payload)
@pytest.mark.parametrize(
"payload",
[
{},
{"dateTime": "2025-06-01T10:00:00Z", "date": "2025-06-01"},
{"dateTime": "2025-06-01 10:00:00Z"},
{"dateTime": "2025-06-01T10:00:00"},
{"date": "2025-6-1"},
{"date": "2025-02-31"},
{"dateTime": "2025-06-01T10:00:00", "timeZone": "Not/AZone"},
{"dateTime": "2025-06-01T10:00:00Z", "timeZone": "America/New_York"},
],
)
def test_event_datetime_rejects_invalid_shapes(payload):
with pytest.raises(ValidationError):
EventDateTime.model_validate(payload)
def test_offsetless_datetime_uses_event_timezone():
event = _minimal_event(
start={"dateTime": "2025-06-01T10:00:00", "timeZone": "America/New_York"},
end={"dateTime": "2025-06-01T11:00:00", "timeZone": "America/New_York"},
)
parsed_start = _parse_event_start(event)
assert parsed_start is not None
assert parsed_start.isoformat() == "2025-06-01T10:00:00-04:00"
def test_legacy_all_day_same_day_end_is_normalized():
event = _minimal_event(
start={"date": "2025-06-01"},
end={"date": "2025-06-01"},
)
assert _parse_event_end(event) == datetime(2025, 6, 2, tzinfo=UTC)
def test_event_rejects_mixed_start_end_shapes():
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(start={"dateTime": "2025-06-01T10:00:00Z"}, end={"date": "2025-06-02"}))
def test_event_rejects_end_before_start():
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(
start={"dateTime": "2025-06-01T10:00:00Z"},
end={"dateTime": "2025-06-01T10:00:00Z"},
)
)
def test_event_rejects_empty_id():
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(id=""))
def test_event_rejects_invalid_audit_timestamp():
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(created="2025-06-01T10:00:00"))
def test_event_transparency_is_typed():
event = Event.model_validate(_minimal_event(transparency="transparent"))
assert event.transparency == "transparent"
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(transparency="busy-ish"))
def test_from_gmail_events_default_to_transparent():
event = Event.model_validate(_minimal_event(eventType="fromGmail"))
assert event.transparency == "transparent"
def test_attendee_email_and_guest_count_are_validated():
assert EventAttendee.model_validate({"email": "alice@example.com", "additionalGuests": 1})
with pytest.raises(ValidationError):
EventAttendee.model_validate({"email": "not-an-email"})
with pytest.raises(ValidationError):
EventAttendee.model_validate({"email": "alice@example.com", "additionalGuests": -1})
def test_event_rejects_duplicate_attendees_case_insensitively():
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(
attendees=[
{"email": "alice@example.com"},
{"email": "ALICE@example.com"},
]
)
)
def test_creator_and_organizer_are_typed_person_objects():
event = Event.model_validate(
_minimal_event(
creator={"email": "creator@example.com", "displayName": "Creator"},
organizer={"email": "organizer@example.com", "displayName": "Organizer", "self": True},
)
)
assert event.creator is not None
assert event.creator.email == "creator@example.com"
assert event.organizer is not None
assert event.organizer.self is True
with pytest.raises(ValidationError):
CalendarPerson.model_validate({"email": "not-an-email"})
def test_extended_properties_and_source_are_typed():
event = Event.model_validate(
_minimal_event(
extendedProperties={
"private": {"task_id": "task-123"},
"shared": {"project": "Migration"},
},
source={"title": "Sprint planning notes"},
)
)
assert event.extendedProperties is not None
assert event.extendedProperties.private == {"task_id": "task-123"}
assert event.source is not None
assert event.source.title == "Sprint planning notes"
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(extendedProperties={"private": {"task_id": {"nested": "no"}}}))
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(source={"title": ""}))
def test_extended_properties_reject_unmodeled_top_level_keys():
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(
extendedProperties={
"private": {"task_id": "task-123"},
"unexpected": {"not": "modeled"},
}
)
)
def test_event_type_defaults_to_default():
event = Event.model_validate(_minimal_event())
assert event.eventType == "default"
def test_focus_time_event_accepts_matching_properties():
event = Event.model_validate(
_minimal_event(
eventType="focusTime",
focusTimeProperties={
"autoDeclineMode": "declineOnlyNewConflictingInvitations",
"chatStatus": "doNotDisturb",
"declineMessage": "Focusing right now",
},
)
)
assert event.focusTimeProperties is not None
assert event.focusTimeProperties.chatStatus == "doNotDisturb"
def test_event_type_rejects_missing_or_mismatched_properties():
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(eventType="focusTime"))
with pytest.raises(ValidationError):
Event.model_validate(_minimal_event(eventType="default", focusTimeProperties={"chatStatus": "available"}))
def test_working_location_properties_match_location_type():
event = Event.model_validate(
_minimal_event(
eventType="workingLocation",
workingLocationProperties={"type": "customLocation", "customLocation": {"label": "Client office"}},
)
)
assert event.workingLocationProperties is not None
assert event.workingLocationProperties.type == "customLocation"
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(eventType="workingLocation", workingLocationProperties={"type": "customLocation"})
)
def test_working_location_home_office_is_empty_marker():
event = Event.model_validate(
_minimal_event(
eventType="workingLocation",
workingLocationProperties={"type": "homeOffice", "homeOffice": {}},
)
)
assert event.workingLocationProperties is not None
assert event.workingLocationProperties.type == "homeOffice"
assert event.workingLocationProperties.homeOffice is not None
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(
eventType="workingLocation",
workingLocationProperties={"type": "homeOffice", "homeOffice": {"label": "Home"}},
)
)
def test_birthday_properties_validate_special_date_shape():
Event.model_validate(_minimal_event(eventType="birthday", birthdayProperties={"type": "birthday"}))
Event.model_validate(
_minimal_event(eventType="birthday", birthdayProperties={"type": "anniversary", "contact": "people/c12345"})
)
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(eventType="birthday", birthdayProperties={"type": "self", "contact": "people/c12345"})
)
with pytest.raises(ValidationError):
Event.model_validate(
_minimal_event(eventType="birthday", birthdayProperties={"type": "anniversary", "contact": "people/a"})
)