Skip to main content

A Python package for semester-related utilities.

Project description

hm-semester

A Python package for generating ICS calendar files for Hochschule München (HM) semesters. Create calendars with semester dates, breaks, holidays, and weekly/biweekly lecture schedules.

Features

  • Semester Calendar: Generate calendars with semester start/end dates and breaks (Christmas, Easter, Pentecost)
  • Lecture Agenda: Create individual lecture events with holiday-aware scheduling
  • Biweekly Support: Handle biweekly lectures that maintain alternating patterns even when holidays interrupt
  • Update Tracking: Deterministic UIDs and SEQUENCE numbers for calendar updates
  • Multi-language: Support for German and English labels

Usage

Semester Calendar (Holidays & Breaks)

Generate a calendar with semester dates and break periods.

CLI

python -m hm_semester --year 2025 --semester winter --lang en

This creates winter_semester_2025_en.ics with:

  • Semester start and end dates
  • Christmas break (Winter semester)
  • Easter and Pentecost breaks (Summer semester)

Python API

from hm_semester.semester import generate_calendar

cal = generate_calendar(2025, "winter", "en")
with open("semester.ics", "wb") as f:
    f.write(cal.to_ical())

Lecture Agenda

Generate individual lecture events with holiday-aware scheduling.

Basic Example

from datetime import time
from hm_semester.agenda import WeeklyEvent, create_agenda

events = [
    WeeklyEvent(
        summary="Algorithms",
        course_id="CS101",
        weekday=0,  # Monday
        start_time=time(9, 0),
        end_time=time(11, 0),
        location="Room 101",
    ),
    WeeklyEvent(
        summary="Database Systems",
        course_id="CS202",
        weekday=2,  # Wednesday
        start_time=time(14, 0),
        end_time=time(16, 0),
        location="Lab 305",
        biweekly=True,  # Every 2 weeks
        start_week=1,
    ),
]

cal = create_agenda(events, 2026, "en", "summer")
with open("lectures.ics", "wb") as f:
    f.write(cal.to_ical())

WeeklyEvent Parameters

  • summary (str): Event title
  • course_id (str): Course identifier for deterministic UID generation
  • weekday (int): Day of week (0=Monday, 6=Sunday)
  • start_time (time): Lecture start time
  • end_time (time): Lecture end time
  • location (str, optional): Room or building
  • biweekly (bool, optional): If True, event occurs every 2 weeks
  • start_week (int, optional): For biweekly, which week to start (1, 2, 3, ...)
  • timezone (str, optional): Timezone name (default: "Europe/Berlin")
  • sequence (int, optional): Version number for updates (default: 0)

Holiday-Aware Scheduling

Lectures automatically skip semester breaks:

  • Individual events are generated (no RRULE)
  • Holidays are excluded from the schedule
  • Biweekly lectures maintain alternating pattern even when holidays interrupt
    • Example: If a biweekly lecture would be in week 7 (holiday), it shifts to week 8

Biweekly Patterns

Use start_week to stagger multiple biweekly groups:

# Four groups meeting every 2 weeks, staggered by 1 week
groups = [
    WeeklyEvent("Group A", "grpA", 0, time(10, 0), time(12, 0), 
                biweekly=True, start_week=1),
    WeeklyEvent("Group B", "grpB", 0, time(10, 0), time(12, 0), 
                biweekly=True, start_week=2),
    WeeklyEvent("Group C", "grpC", 0, time(10, 0), time(12, 0), 
                biweekly=True, start_week=3),
    WeeklyEvent("Group D", "grpD", 0, time(10, 0), time(12, 0), 
                biweekly=True, start_week=4),
]

Updating Calendars

When room locations or times change, increment the sequence parameter:

# Initial calendar
events = [
    WeeklyEvent("Algorithms", "CS101", 0, time(9, 0), time(11, 0), 
                location="Room 101", sequence=0),
]
cal = create_agenda(events, 2026, "en", "summer")

# Later: room changed
events[0].location = "Room 999"
events[0].sequence = 1
updated_cal = create_agenda(events, 2026, "en", "summer")

For Thunderbird/local calendar apps: Delete the old calendar and import the new one.

For CalDAV/subscribed calendars: Events with the same UID and higher SEQUENCE are automatically updated.

Examples

See examples/create_agenda_example.py for a complete example.

Output Format

  • Each lecture gets a unique event with format: "Course Name (1)", "Course Name (2)", etc.
  • UIDs are deterministic: {course_id}-{year}-{semester}-lesson-{number}@hm.edu
  • VTIMEZONE components are included for proper timezone handling
  • SEQUENCE field tracks version numbers for updates

Installation

From PyPI

pip install hm-semester

From source

git clone https://github.com/DavidMStraub/hm-semester.git
cd hm-semester
pip install .

Development

Run tests:

pytest tests/

Release Process

This package uses GitHub Actions for automated PyPI releases:

  1. Update version in pyproject.toml
  2. Commit and push changes
  3. Create a new release on GitHub
  4. The workflow automatically builds and publishes to PyPI and TestPyPI

The workflow uses Trusted Publishing (no API tokens needed). Configure trusted publishers:

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

hm_semester-26.1.0.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.

hm_semester-26.1.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file hm_semester-26.1.0.tar.gz.

File metadata

  • Download URL: hm_semester-26.1.0.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for hm_semester-26.1.0.tar.gz
Algorithm Hash digest
SHA256 5132e6c99dd7d8d1e09fcbd964c131dfef54b167f6aaa4c60b3020be4e3cfc01
MD5 425aed1268126f996eef9bc674de5c0a
BLAKE2b-256 193abdc859d6de5a2b877f4ed15d3944d378352647d44d5cfe623bb939381cec

See more details on using hashes here.

Provenance

The following attestation bundles were made for hm_semester-26.1.0.tar.gz:

Publisher: pypi-release.yml on DavidMStraub/hm-semester

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hm_semester-26.1.0-py3-none-any.whl.

File metadata

  • Download URL: hm_semester-26.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for hm_semester-26.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0e989ec0f96231af8eaf41bd985d8e38f72b1418dd8fdea63c4dcf6e057ecb17
MD5 5f5c93c5aa427f4f22bb510ef8f71411
BLAKE2b-256 e90b06d117ffecf0a10bbbf4754f892e7a46c9cce9a90193087e20a83f778f7b

See more details on using hashes here.

Provenance

The following attestation bundles were made for hm_semester-26.1.0-py3-none-any.whl:

Publisher: pypi-release.yml on DavidMStraub/hm-semester

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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