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.1.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.1-py3-none-any.whl (15.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: maccal-1.0.1.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.1.tar.gz
Algorithm Hash digest
SHA256 0a13e4bedcb8b5533b20d5d10dde503bfddcf0953104efc4374b3ef5fccbd049
MD5 08b2ff526190da425fc718d52107e663
BLAKE2b-256 826af763e7d2d1809f26f89f7737023bb451f9e2ead1e1a4509ef47b215c4442

See more details on using hashes here.

File details

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

File metadata

  • Download URL: maccal-1.0.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f34889d7b40670ac3dfb92ecec8729f5a59bf9269543985365e97ec5a070ae6e
MD5 0a75d4f5eb26a54d89f1479f57108c60
BLAKE2b-256 7bc460b26736519364bd370d6fd6aa69d2a417c378eab0584b18506637d80558

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