iCalendar Searcher
icalendar-searcher is a Python library designed for powerful searching, filtering, and sorting of iCalendar components using a SQL-like Domain Specific Language (DSL). It simplifies interaction with `.ics` data, offering functionalities like expanding recurring events and complex property queries. The current stable version is 1.0.5, with an active development pace characterized by frequent patch and minor releases.
Common errors
-
TypeError: IcalendarSearcher.__init__() got an unexpected keyword argument 'ignore_exceptions'
cause Using the `ignore_exceptions` parameter in the `IcalendarSearcher` constructor, which was removed in version 1.0.0.fixRemove `ignore_exceptions` from your `IcalendarSearcher` instantiation. If you need custom exception handling, implement it outside the searcher. -
AttributeError: 'IcalendarSearcher' object has no attribute 'get_calendars'
cause Attempting to call the `get_calendars()` method, which was removed in version 1.0.0.fixUse the `search()` method directly, which now returns an iterator of `icalendar.cal.Component` objects. The concept of `get_calendars()` is no longer directly exposed. -
TypeError: IcalendarSearcher.__init__() got an unexpected keyword argument 'expand_recurring_events'
cause Passing `expand_recurring_events` to the `IcalendarSearcher` constructor, but it was moved to the `search()` method in version 1.0.0.fixPass `expand_recurring_events=True` (or `False`) directly to the `search()` method, e.g., `searcher.search(query, expand_recurring_events=True)`. -
AttributeError: 'generator' object has no attribute 'get_events'
cause Attempting to call `get_events()` or similar methods on the object returned by `search()`, which is now an iterator of components, not a `QueryResult` object.fixIterate directly over the result of `search()`. Each item in the iteration is an `icalendar.cal.Component` object. Access component properties directly, e.g., `for component in searcher.search(): print(component.get('SUMMARY'))`.
Warnings
- breaking The `ignore_exceptions` parameter was removed from the `IcalendarSearcher` constructor. It is no longer supported.
- breaking The method `IcalendarSearcher.get_calendars()` was removed. `IcalendarSearcher.search()` now directly returns an iterator of `icalendar.cal.Component` objects.
- breaking The `expand_recurring_events` parameter was moved from the `IcalendarSearcher` constructor to the `IcalendarSearcher.search()` method.
- breaking The `search()` method now returns an iterator of `icalendar.cal.Component` objects directly, and the `QueryResult` object was removed.
Install
-
pip install icalendar-searcher
Imports
- IcalendarSearcher
from icalendar_searcher import IcalendarSearcher
- QueryBuilder
from icalendar_searcher import QueryBuilder
Quickstart
from icalendar_searcher import IcalendarSearcher, QueryBuilder
ics_data = """
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp//NONSGML Event Generator//EN
BEGIN:VEVENT
UID:19970610T172345Z-AF23B2@example.com
DTSTAMP:19970610T172345Z
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
DESCRIPTION:Party to celebrate Bastille Day.
LOCATION:Paris, France
END:VEVENT
BEGIN:VEVENT
UID:19980610T172345Z-AF23C3@example.com
DTSTAMP:19980610T172345Z
DTSTART:19980720T100000Z
DTEND:19980720T110000Z
SUMMARY:Meeting with client
END:VEVENT
END:VCALENDAR
"""
searcher = IcalendarSearcher(ics_data)
# Example 1: Find events starting after a specific date
query_future = QueryBuilder().filter("DTSTART >= 1997-07-15T00:00:00Z").build()
results_future = searcher.search(query_future)
print("\nEvents starting after July 15, 1997:")
for component in results_future:
print(f"- {component.get('SUMMARY')}")
# Example 2: Filter by property value (case-insensitive summary containing 'party')
query_party = QueryBuilder().filter("SUMMARY ~ 'party'").build()
results_party = searcher.search(query_party)
print("\nEvents with 'party' in summary:")
for component in results_party:
print(f"- {component.get('SUMMARY')}")
# Example 3: Get all components
all_results = searcher.search()
print("\nAll events:")
for component in all_results:
print(f"- {component.get('SUMMARY')}")