Skip to main content

Python library to access macOS calendars via EventKit

Project description

macCal

A Python library to access local macOS calendars via EventKit and PyObjC. Works with macOS 26 Tahoe.

Overview

  • Written in 100% python, easy to audit and extend
  • Can search events, find free time, add/edit/delete events
  • Fully typed
  • Apache 2.0

Written by Guido Appenzeller, guido@appenzeller.net. Feedback and PR's welcome.

Requirements

  • macOS 14+ (Sonoma or later)
  • Python 3.13, but probably works with earlier versions
  • Calendar access permission

Installation

With pip:

pip install maccal

For development:

git clone https://github.com/appenz/maccal
cd maccal
make install

Quick Start

from datetime import datetime, timedelta, timezone
from maccal import CalendarStore

store = CalendarStore()

# List calendars
for cal in store.list_calendars():
    print(f"{cal.title} ({cal.type.name})")

# Get events for the next 7 days
now = datetime.now(tz=timezone.utc)
events = store.get_events(now, now + timedelta(days=7))
for event in events:
    print(f"{event.start:%H:%M} {event.title}")

# Search events
results = store.find_events("standup", start=now, end=now + timedelta(days=30))

# Search specific fields
results = store.find_events(
    "@acme.com",
    start=now, end=now + timedelta(days=30),
    fields=["attendee_email"],
)

# Create an event
event = store.add_event(
    title="Team Lunch",
    start=datetime(2026, 3, 15, 12, 0, tzinfo=timezone.utc),
    end=datetime(2026, 3, 15, 13, 0, tzinfo=timezone.utc),
    calendar="Personal",
    location="Cafe",
)

# Find free time
slots = store.find_free_time(
    start=datetime(2026, 3, 15, 9, 0, tzinfo=timezone.utc),
    end=datetime(2026, 3, 15, 17, 0, tzinfo=timezone.utc),
    duration=timedelta(minutes=30),
)

Searchable Fields

When using find_events, you can restrict search to specific fields:

  • title, location, notes, url, calendar
  • organizer_name, organizer_email
  • attendee_name, attendee_email

Pass fields=None (default) to search all fields.

Recurring Events

When querying events, recurring events are automatically expanded into individual occurrences. When editing or deleting a recurring event, you must specify which occurrences to affect:

store.update_event(
    event.event_id,
    title="New Title",
    span="this",        # "this" or "future"
    occurrence_date=event.occurrence_date,
)

Omitting occurrence_date for a recurring event raises ValueError.

Development

make install    # Install with dev dependencies
make test       # Run tests
make lint       # Check code style
make format     # Auto-format code
make build      # Build package
make benchmark  # Run performance benchmarks

License

Apache 2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

maccal-1.0.2.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

maccal-1.0.2-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

File details

Details for the file maccal-1.0.2.tar.gz.

File metadata

  • Download URL: maccal-1.0.2.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.8

File hashes

Hashes for maccal-1.0.2.tar.gz
Algorithm Hash digest
SHA256 c378d5962e6f1f27f88d712d28ae434ace0de17f1eb84e3be5cc3ebf8dd85f32
MD5 00fc95eea636cb9ca4d042b3557b9917
BLAKE2b-256 35750dcaa1ba5c2c70514b5a27f8e7831c55c01b86c168cb42a005a937c937a6

See more details on using hashes here.

File details

Details for the file maccal-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: maccal-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 15.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.8

File hashes

Hashes for maccal-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 310451296d8bb2ea629058271fb9f0e8bd66c915ab57bf8d1f1ef29c32581fa0
MD5 b56e32fcadccf227b26c77754d339029
BLAKE2b-256 0649f04b7e6fd65455993b05accbc755824851bb34864a757dd36cca004e6c27

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page