Skip to content

Commit

Permalink
Remove self keywords in additional API responses (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
allenporter authored Nov 23, 2023
1 parent 7d8b0d0 commit 5ef41e2
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 19 deletions.
37 changes: 19 additions & 18 deletions gcal_sync/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,30 @@ class CalendarBaseModel(BaseModel):
"""Base class for calendar models."""

def __init__(self, **data: Any) -> None:
"""Initialize the model."""
try:
super().__init__(**data)
except ValidationError as err:
raise CalendarParseException(f"Failed to parse component: {err}") from err

@root_validator(pre=True)
def _remove_self(cls, values: dict[str, Any]) -> dict[str, Any]:
"""Rename any 'self' fields from all child values of the dictionary."""
if "self" in values:
values["self_"] = values["self"]
del values["self"]

# Mutate any children with "self" fields
updates = {}
for k, v in values.items():
if isinstance(v, dict):
updates[k] = cls._remove_self(v)
elif isinstance(v, list) and len(v) > 0 and isinstance(v[0], dict):
updates[k] = [cls._remove_self(item) for item in v]
values.update(updates)

return values


class Calendar(CalendarBaseModel):
"""Metadata associated with a calendar from the CalendarList API."""
Expand Down Expand Up @@ -573,24 +592,6 @@ def rrule(self) -> Iterable[Union[datetime.date, datetime.datetime]]:
return []
return self.recur.as_rrule(self.start.value)

@root_validator(pre=True)
def _remove_self(cls, values: dict[str, Any]) -> dict[str, Any]:
"""Rename any 'self' fields from all child values of the dictionary."""

if "self" in values:
values["self_"] = values["self"]
del values["self"]

# Mutate any children with "self" fields
for v in values.values():
if isinstance(v, dict):
cls._remove_self(v)
elif isinstance(v, list) and len(v) > 1 and isinstance(v[0], dict):
for item in v:
cls._remove_self(item)

return values

@root_validator(pre=True)
def _allow_cancelled_events(cls, values: dict[str, Any]) -> dict[str, Any]:
"""Special case for canceled event tombstones missing required fields."""
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = gcal-sync
version = 6.0.2
version = 6.0.3
description = A python library for syncing Google Calendar to local storage
long_description = file: README.md
long_description_content_type = text/markdown
Expand Down
38 changes: 38 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -875,3 +875,41 @@ async def test_create_event_with_reminder(
"reminders": {"overrides": [{"method": "popup", "minutes": 7}]},
}
]


async def test_api_self_response(
event_sync_manager_cb: Callable[[], Awaitable[CalendarEventSyncManager]],
json_response: ApiResult,
url_request: Callable[[], str],
json_request: Callable[[], str],
) -> None:
"""Test api responses with reserved keywords."""
json_response(
{
"items": [
{
"id": "some-event-id-1",
"iCalUID": "some-event-id-1@google.com",
"summary": "Event 1",
"start": {
"date": "2022-04-13",
},
"end": {
"date": "2022-04-14",
},
"status": "confirmed",
"attendees": [
{
"email": "example@example.com",
"self": True,
"responseStatus": "tentative",
}
],
}
],
"nextSyncToken": "sync-token-1",
}
)
json_response({})
sync = await event_sync_manager_cb()
await sync.run()

0 comments on commit 5ef41e2

Please sign in to comment.