stapel-calendar
Calendar and scheduling: events with participants and RSVP, RFC 5545 recurring series (virtual expansion, on-demand materialization, per-instant cancellation and reschedule), availability windows with free/busy and bookable slot computation, ICS export, and event-driven reminders.
Part of the Stapel framework — composable Django apps that deploy as a monolith or as microservices without changing module code.
Install
pip install stapel-calendar
At a glance
| Fact | Value |
|---|---|
| Version | 0.4.2 |
| Python | >=3.11 (3.11, 3.12, 3.13, 3.14) |
| HTTP operations | 10 |
| Config axes | 1 |
| Usage surface | 31 |
| Extension points | 5 |
| Error codes | 48 |
| Fleet dependencies | stapel-auth (optional) · stapel-core · stapel-notifications (optional) |
Documentation
OpenAPI · capabilities.json · llms.txt (for agents)
What this is
A generic calendar core — Event / Participant / RSVP, an RFC 5545
recurrence engine (RRULE via python-dateutil, virtual expansion +
on-demand materialization), availability (working windows, free/busy,
slots) and ICS export. Two flavors of one domain — meetings and
bookings — share this core; everything app-specific lives behind seams.
Quick start
INSTALLED_APPS = [
# ...
"stapel_calendar",
]
# urls.py
path("calendar/", include("stapel_calendar.urls"))
Concepts
- Event — a scheduled thing (meeting/booking/appointment) with tz-aware
start/end, anownerand an opaquescope_key. No FK to any host concept (org, room) — scoping and resources are seams. - Recurrence — the series master stores a canonical RRULE. Occurrences are virtual until they gain their own state (an RSVP or a resource), at which point they are materialized (persisted) on demand.
- Availability — recurring working windows minus busy events give open booking slots.
from stapel_calendar import services
series = services.create_event(
owner=user, title="Standup",
start=start, end=end,
recurrence_type="weekdays", # -> FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR
)
occurrences = services.expand_event(series, range_start, range_end) # virtual
services.materialize(series, occurrence_start) # persist one + emit hook
busy = services.free_busy(user, range_start, range_end)
slots = services.compute_slots(user, range_start, range_end, slot_minutes=30)
Settings
All configuration lives in the STAPEL_CALENDAR namespace (dict setting,
flat setting, or env var — resolved lazily):
| Key | Default | Meaning |
|---|---|---|
SCOPE_PROVIDER |
…scope.DefaultScopeProvider |
Resolve/filter the opaque scope_key |
REMINDER_POLICY |
…reminders.DefaultReminderPolicy |
When/what to remind |
PRESETS |
{} |
Custom recurrence presets (merged over built-ins) |
REMINDER_OFFSETS |
[10] |
Minutes before start to remind |
REMINDER_SCAN_WINDOW_SECONDS |
60 |
Reminder cron granularity |
DEFAULT_EXPANSION_HORIZON_DAYS |
90 |
Default range end |
MAX_EXPANSION_OCCURRENCES |
1000 |
Expansion safety cap |
DEFAULT_SLOT_MINUTES |
30 |
Default slot length |
comm surface
| Kind | Name | Contract |
|---|---|---|
| Emit | calendar.occurrence.materialized |
An occurrence was persisted — subscribe to attach a resource |
| Emit | calendar.event.reminder_due |
A reminder is due — deliver it |
| Function | calendar.free_busy |
{user_id, start, end, scope_key?} -> {busy: [...]} |
Extension points
See MODULE.md — the agent-facing map of every fork-free seam (the resource hook, reminder policy, scope provider, recurrence presets, serializer seams, settings).
Development
pip install -e . && pip install pytest pytest-django ruff
./setup-hooks.sh
pytest tests/
License
MIT — see LICENSE.
This page is assembled by stapel-readme from docs/readme.md plus the contract artifacts in docs/. Edit the prose in docs/readme.md; the badges, facts and links above and below it are generated — do not hand-edit README.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stapel_calendar-0.4.2.tar.gz.
File metadata
- Download URL: stapel_calendar-0.4.2.tar.gz
- Upload date:
- Size: 85.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e24597eb2bb25e3c4d0c7f22b05348f1e94caee778447bb399b20ed4a6dbeec5
|
|
| MD5 |
27f1829f837655fa82c0dbbf017fcaa0
|
|
| BLAKE2b-256 |
a722eb8a2ad07a4fa2a23771ae9fbf5b022e18b39ffaf9283e46cc935df35260
|
Provenance
The following attestation bundles were made for stapel_calendar-0.4.2.tar.gz:
Publisher:
publish.yml on usestapel/stapel-calendar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stapel_calendar-0.4.2.tar.gz -
Subject digest:
e24597eb2bb25e3c4d0c7f22b05348f1e94caee778447bb399b20ed4a6dbeec5 - Sigstore transparency entry: 2477686952
- Sigstore integration time:
-
Permalink:
usestapel/stapel-calendar@3740693bba2917f15de0b5956dd66763d48f0afe -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/usestapel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3740693bba2917f15de0b5956dd66763d48f0afe -
Trigger Event:
push
-
Statement type:
File details
Details for the file stapel_calendar-0.4.2-py3-none-any.whl.
File metadata
- Download URL: stapel_calendar-0.4.2-py3-none-any.whl
- Upload date:
- Size: 74.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6678d0bcf2f7d86f12560928f5d9c1267ca2021b4652a870e909e9a09f04c949
|
|
| MD5 |
9bbe2e9578befd8af168c573cc8f1402
|
|
| BLAKE2b-256 |
e333ce533432893f567e6236ded8d3bacf5d060c8ae5ed0a57b797f7f25e2fb6
|
Provenance
The following attestation bundles were made for stapel_calendar-0.4.2-py3-none-any.whl:
Publisher:
publish.yml on usestapel/stapel-calendar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stapel_calendar-0.4.2-py3-none-any.whl -
Subject digest:
6678d0bcf2f7d86f12560928f5d9c1267ca2021b4652a870e909e9a09f04c949 - Sigstore transparency entry: 2477686974
- Sigstore integration time:
-
Permalink:
usestapel/stapel-calendar@3740693bba2917f15de0b5956dd66763d48f0afe -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/usestapel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3740693bba2917f15de0b5956dd66763d48f0afe -
Trigger Event:
push
-
Statement type: