Skip to content

Expose calendar source on calendars and events - #6

Open
fmasi wants to merge 1 commit into
harriscarl:mainfrom
fmasi:feat/expose-calendar-source
Open

Expose calendar source on calendars and events#6
fmasi wants to merge 1 commit into
harriscarl:mainfrom
fmasi:feat/expose-calendar-source

Conversation

@fmasi

@fmasi fmasi commented May 19, 2026

Copy link
Copy Markdown

Summary

Surfaces EKCalendar.source() data in two places:

  • _calendar_to_dict — adds source: {title, type} on every calendar dict returned by calendar_list_calendars.
  • _event_to_dict — adds calendar_source: str alongside the existing calendar: str on every event dict returned by calendar_list_events, calendar_get_event, calendar_search_events.

Why

EventKit calendars are not uniquely identified by title alone — same-named calendars can exist across accounts. Smoke-testing the patch on a real machine I hit two calendars with identical titles served by different source accounts; without source, they were indistinguishable. With it, callers can disambiguate, filter by account ("only iCloud"), and route events sensibly.

Example shapes of source returned by EventKit:

source.title source.type
iCloud 2 (CalDAV)
Google 2 (CalDAV)
<account-email> (per-account CalDAV) 2 (CalDAV)
Other 5 (Birthdays)
On My Mac 0 (Local)

Design notes

  • Backward-compatible. The existing calendar: "Title" field on events is unchanged — only a new sibling calendar_source is added. Existing keys on calendar dicts (id, title, type, allows_modifications) are also unchanged; source is purely additive.
  • None-safe. Both code paths check that calendar.source() (and event.calendar()) is non-null before dereferencing.
  • Raw enum for source.type matches the existing type: str(calendar.type()) pattern. Pretty-printing can come downstream.

Test plan

  • Existing fields on calendar/event dicts unchanged
  • source present on every calendar dict, with non-null title/type when EventKit provides a source
  • calendar_source present on every event dict
  • Local/Birthdays calendars surface their pseudo-source ("Other", "On My Mac") without raising
  • No regressions for callers that ignore the new fields

Smoke-tested locally against a real macOS calendar tree with mixed iCloud, Google, subscribed, and Birthdays sources. All output sane.

Independent of #5

This is a separate PR; not stacked on #5 (exclude_calendars). Either can land first.

🤖 Generated with Claude Code

EKCalendar.source() carries the account identity ("iCloud", "Google",
account email, "Other") and a sourceType enum. Surfacing this lets
callers disambiguate same-named calendars across accounts (e.g. two
"Holidays in United Kingdom" calendars, one Google, one iCloud) and
route by account ("everything from my iCloud").

Changes:
- _calendar_to_dict gains source: {title, type} on every calendar
- _event_to_dict gains calendar_source: str alongside the existing
  calendar title (backward-compatible; existing callers see no change)

Both fields are None-safe; if EventKit returns no source they stay
null rather than raising.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant