vobject

Parse and generate iCalendar and vCard files with a full-featured Python library.

Library
PyPI
v0.9.9
54stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
71/100Good
Development Activity92
Maintenance72
Community52
Maturity48
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
79/100Good
Architecture78
Code Quality78
Innovation70
Learning Curve90

VObject is a Python library for parsing and generating iCalendar (.ics) and vCard (.vcf) files. It converts RFC 5545 calendar data and RFC 6350 contact data into native Python objects — dates become datetime instances, recurrence rules become dateutil.rrule rruleset objects — and serializes them back to spec-compliant text.

Originally built for the Open Source Applications Foundation’s Chandler project, VObject was later maintained by Eventable before being revived under the py-vobject organization after a period of inactivity. It ships two CLI utilities, ics_diff for comparing calendar files and change_tz for shifting event timezones, alongside the core parsing API.

What You Get

  • Component tree parsing - readComponents/readOne turn raw .ics/.vcf text into a tree of Component and ContentLine objects.
  • Native Python types - dates, datetimes, and recurrence rules are converted to datetime and dateutil.rrule.rruleset instances automatically.
  • Behavior-based validation - Behavior subclasses per component type (VEVENT, VTODO, VCARD, etc.) drive encoding, decoding, and spec validation.
  • Round-trip serialization - modified or newly built objects serialize back to valid RFC 5545/6350 text.
  • Bundled CLI tools - ics_diff and change_tz scripts for calendar diffing and timezone correction.

Common Use Cases

  • Calendar sync tools - reading and writing .ics files exchanged between calendaring systems (CalDAV clients, scheduling apps).
  • Contact import/export - parsing vCard files from address books or CRM exports into structured Python data.
  • Timezone correction scripts - using change_tz to move events between timezones when source data is mislabeled.
  • Calendar diffing - using ics_diff to find meaningful differences between two .ics files ignoring irrelevant ordering.

Under The Hood

Architecture VObject organizes calendar and vCard data as a tree of VBase-derived objects (Component and ContentLine, defined in vobject/base.py) that is assembled by readComponents/readOne, converted to native Python types via transformChildrenToNative(), and reconstituted by serialize(); domain-specific logic — validation rules, knownChildren tables, encoding/decoding, and factory behavior — lives outside this generic tree in per-format Behavior subclasses (behavior.py’s abstract Behavior class, extended by icalendar.py for VCALENDAR/VEVENT/VTODO/etc. and vcard.py for VCARD), which base.py’s registerBehavior/getBehavior registry looks up by component name and version string so the same parser core drives two unrelated formats; a DEFAULT_MAX_NESTING guard in base.py caps recursive descent to prevent stack overflow on malformed input, and the ics_diff/change_tz CLI scripts sit as thin consumers on top of this same object model rather than a separate code path.

Tech Stack VObject is pure-Python (99.97% by bytes per GitHub’s language breakdown) targeting Python 3.9+ (pyproject.toml, dynamic-versioned via flit_core >=3.4 as the PEP 517 build backend), with a minimal runtime dependency footprint — python-dateutil (>=2.5 or >=2.7 depending on interpreter version) for RFC 5545 recurrence-rule parsing into rruleset objects, and pytz (>=2019.1) for timezone data, with an internal fallback Pytz shim in icalendar.py so pytz stays optional at runtime; console-script entry points (ics_diff, change_tz) are registered via [project.scripts]; the dev extra pulls in pytest for testing, flake8/pylint/black/isort for linting and formatting, pre-commit for git hooks, sphinx for documentation, and flit for packaging — no web framework, database, or ORM is involved since this is a pure data-transformation library.

Code Quality Testing uses pytest across 9 files in tests/ (test_vobject.py, test_icalendar.py, test_vcards.py, test_behaviors.py, test_calendar_serialization.py, test_change_tz.py, test_cli.py, test_compatibility.py, test_vtodo.py) totaling 77 test functions plus doctests embedded in vobject/init.py’s module docstring, run across a CI matrix of Python 3.9 through 3.14 (.github/workflows/test.yml); error handling is explicit and typed via custom exception classes (VObjectError, ParseError, ValidateError, NativeError defined in base.py) rather than bare excepts, though most of the codebase (base.py, behavior.py, vcard.py) predates PEP 484 type hints — only icalendar.py and ics_diff.py carry function-level type annotations; naming largely follows a legacy camelCase convention (readComponents, transformChildrenToNative) rather than PEP 8 snake_case, a holdover from the project’s pre-2010 Chandler-project origins; black, flake8, isort, and pylint are configured in pyproject.toml and enforced via a separate pre-commit.yml CI workflow.

API Design VObject’s public surface is deliberately small: readComponents/readOne to parse, iCalendar()/vCard() factory functions plus newFromBehavior to build objects from scratch, and .serialize() to emit spec text, with attribute-style access (cal.vevent.summary.value) replacing verbose tree-traversal calls; its most distinctive design choice is transforming parsed data into native Python types automatically — RRULE lines become dateutil.rrule.rruleset instances you can iterate directly, dates become datetime.date/datetime objects — so callers work with real Python semantics instead of re-parsing ICAL grammar themselves, and the same generic Component/ContentLine/Behavior machinery drives both iCalendar and vCard with no format-specific parser duplication; getting started requires minimal boilerplate, though the doctest-style docs and camelCase API show the project’s age relative to more modern, fully type-hinted Python libraries in this space.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search