Skip to content

Commit

Permalink
Add from_file and to_file method
Browse files Browse the repository at this point in the history
  • Loading branch information
abe-101 committed Dec 9, 2024
1 parent 4725c1b commit 804ab52
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 2 deletions.
3 changes: 1 addition & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ Breaking changes:
- The ``relative`` attribute of ``vWeekday`` components has the correct sign now. See `Issue 749 <https://github.com/collective/icalendar/issues/749>`_.

New features:

- ...
- Add ``from_file()`` and ``to_file()`` methods to ``Component`` class for easier file handling of iCalendar data. See `Issue 756 <https://github.com/collective/icalendar/issues/756>`_.

Bug fixes:

Expand Down
69 changes: 69 additions & 0 deletions src/icalendar/cal.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from datetime import date, datetime, timedelta, tzinfo
from typing import List, Optional, Tuple
from datetime import date, datetime, timedelta
from pathlib import Path
from typing import TYPE_CHECKING, List, NamedTuple, Optional, Tuple, Union

import dateutil.rrule
Expand Down Expand Up @@ -587,6 +588,74 @@ def is_thunderbird(self) -> bool:
return any(attr.startswith("X-MOZ-") for attr in self.keys())


@classmethod
def from_file(cls, file: Union[str, Path], multiple: bool = False):
"""Create a Component from a file.
This class method can be used by any Component subclass (Calendar, Event, etc.)
to read their data from a file.
Args:
file: The file to read from. Can be:
- A string path to a file
- A Path object
multiple: If True, allows parsing multiple components from the file.
Returns:
If multiple=False (default):
A single Component instance of the appropriate type
If multiple=True:
A list of Component instances
Raises:
FileNotFoundError: If the file path doesn't exist
ValueError: If the file contents are not valid iCalendar format
Example:
>>> from icalendar import Calendar
>>> # Read a calendar file
>>> cal = Calendar.from_file("src/icalendar/tests/calendars/example.ics")
>>> # Read multiple calendars
>>> cals = Calendar.from_file("src/icalendar/tests/calendars/multiple_calendar_components.ics", multiple=True)
"""
# Handle string path by converting to Path
if isinstance(file, str):
file = Path(file)

return cls.from_ical(file.read_bytes(), multiple=multiple)

def to_file(self, file: Union[str, Path], sorted: bool = True) -> None:
"""Write the component to a file.
This method can be used by any Component subclass (Calendar, Event, etc.)
to write their data to a file.
Args:
file: Where to write the component. Can be:
- A string path to a file
- A Path object
sorted: Whether parameters and properties should be lexicographically sorted.
Example:
>>> from icalendar import Calendar
>>> from pathlib import Path
>>> # Read a calendar file
>>> cal = Calendar.from_file("src/icalendar/tests/calendars/example.ics")
>>> # or pass a Path object
>>> path = Path("src/icalendar/tests/calendars/example.ics")
>>> cal = Calendar.from_file(path)
>>> # Read multiple calendars
>>> cals = Calendar.from_file("src/icalendar/tests/calendars/multiple_calendar_components.ics", multiple=True)
"""

# Handle string path
if isinstance(file, str):
file = Path(file)

file.write_bytes(self.to_ical(sorted=sorted))



#######################################
# components defined in RFC 5545
Expand Down

0 comments on commit 804ab52

Please sign in to comment.