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 uv

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.0.tar.gz (11.5 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.0-py3-none-any.whl (15.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for maccal-1.0.0.tar.gz
Algorithm Hash digest
SHA256 516b52c7382723ad1bbe63082f8ef043ae1f0c6a54e7f8d05def19c50a1602c1
MD5 6ff7a6a426ff2341e95ce0b75bac516c
BLAKE2b-256 a5713093339aff688666ea2c10b809ffa0061f0bb44ae01fc1d9d7e0d44f14bf

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for maccal-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f9fcc87ddb6a81a93ef1df9aa1fd8d8e07ed8ec77810d54d54fbbd58a3f00bdc
MD5 b510cd9b1fe800053553c6fde4ead7cf
BLAKE2b-256 a9e1b8b64db7f168496732dcaaf2f157661f1ccc0f1f2efd15d86dae15c890f0

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