Skip to content

Commit

Permalink
Add exception catching for pyparsing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
allenporter committed Nov 6, 2023
1 parent 5ec50bc commit 24c4426
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 5 deletions.
18 changes: 13 additions & 5 deletions ical/calendar_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,18 @@
from __future__ import annotations

import logging
import pyparsing

try:
from pydantic.v1 import Field
from pydantic.v1 import Field, ValidationError
except ImportError:
from pydantic import Field
from pydantic import Field, ValidationError

from .calendar import Calendar
from .component import ComponentModel
from .parsing.component import encode_content, parse_content
from .types.data_types import DATA_TYPE
from .exceptions import CalendarParseError

_LOGGER = logging.getLogger(__name__)

Expand All @@ -55,13 +57,19 @@ class CalendarStream(ComponentModel):
@classmethod
def from_ics(cls, content: str) -> "CalendarStream":
"""Factory method to create a new instance from an rfc5545 iCalendar content."""
components = parse_content(content)
try:
components = parse_content(content)
except pyparsing.ParseException as err:
raise CalendarParseError(f"Failed to parse calendar stream: {err}") from err
result: dict[str, list] = {"vcalendar": []}
for component in components:
result.setdefault(component.name, [])
result[component.name].append(component.as_dict())
_LOGGER.debug("Parsing object %s", result)
return cls.parse_obj(result)
try:
return cls.parse_obj(result)
except ValidationError as err:
raise CalendarParseError(f"Failed to parse calendar stream: {err}") from err

Check warning on line 72 in ical/calendar_stream.py

View check run for this annotation

Codecov / codecov/patch

ical/calendar_stream.py#L71-L72

Added lines #L71 - L72 were not covered by tests

def ics(self) -> str:
"""Encode the calendar stream as an rfc5545 iCalendar Stream content."""
Expand All @@ -79,7 +87,7 @@ def calendar_from_ics(cls, content: str) -> Calendar:
return stream.calendars[0]
if len(stream.calendars) == 0:
return Calendar()
raise ValueError("Calendar Stream had more than one calendar")
raise CalendarParseError("Calendar Stream had more than one calendar")

Check warning on line 90 in ical/calendar_stream.py

View check run for this annotation

Codecov / codecov/patch

ical/calendar_stream.py#L90

Added line #L90 was not covered by tests

@classmethod
def calendar_to_ics(cls, calendar: Calendar) -> str:
Expand Down
7 changes: 7 additions & 0 deletions tests/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from ical.calendar import Calendar
from ical.calendar_stream import IcsCalendarStream
from ical.exceptions import CalendarParseError
from ical.event import Event
from ical.types.recur import Recur

Expand Down Expand Up @@ -458,3 +459,9 @@ def test_floating_time_with_timezone_propagation() -> None:
it = iter(cal.timeline_tz(zoneinfo.ZoneInfo("Europe/Brussels")))
for i in range(0, 30):
next(it)


def test_invalid_ics() -> None:
"""Test a parse failure for ics content."""
with pytest.raises(CalendarParseError, match="Failed to parse calendar stream"):
IcsCalendarStream.calendar_from_ics("invalid")
8 changes: 8 additions & 0 deletions tests/test_calendar_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
from pytest_golden.plugin import GoldenTestFixture

from ical.exceptions import CalendarParseError
from ical.calendar_stream import CalendarStream, IcsCalendarStream


Expand Down Expand Up @@ -58,3 +59,10 @@ def test_serialize(golden: GoldenTestFixture) -> None:
"""Fixture to read golden file and compare to golden output."""
cal = IcsCalendarStream.from_ics(golden["input"])
assert cal.ics() == golden.get("encoded", golden["input"])



def test_invalid_ics(mock_prodid: Generator[None, None, None]) -> None:
"""Test parsing failures for ics content."""
with pytest.raises(CalendarParseError, match="Failed to parse calendar stream"):
IcsCalendarStream.calendar_from_ics("invalid")

0 comments on commit 24c4426

Please sign in to comment.