allenporter / gcal_sync

A python library for syncing Google Calendar to local storage.
https://allenporter.github.io/gcal_sync/
Apache License 2.0
6 stars 4 forks source link

[Bug] Fields using alias always return default value #545

Open sfdye opened 2 months ago

sfdye commented 2 months ago

From my local testing with github.com/home-assistant/core/, the returned attendees data seem to be corrupted where display_name and response_status always returns the default value, regardless of the actual value.

I would think this applies to other fields using alias e.g. Field(alias="xxx", default=xxx).

Example (real data with redacted email)

attendees=[Attendee(id=None, email='redacted', display_name=None, optional=False, comment=None, response_status=<ResponseStatus.NEEDS_ACTION: 'needsAction'>), Attendee(id=None, email='redacted', display_name=None, optional=False, comment=None, response_status=<ResponseStatus.NEEDS_ACTION: 'needsAction'>)]

Digging around, I think the issue might be due to the slight nuance of the alias feature in pydantic v1 and v2. (apparently home assistant is using v1 whereas gcal_sync supports both v1 and v2)

I have no idea why this is case since the unit tests cover both versions.

allenporter commented 2 months ago

I'm not able to reproduce this for response_status. When I look at what is stored locally in storage I do see valid values of response_status persisted on disk:

$ grep response_status config/.storage/google.xxxxxxx | sort | uniq
                  "response_status": "accepted"
                  "response_status": "declined"
                  "response_status": "needsAction"

Check out the tests in tests/test_model.py which pass in data in the form from the API which should be exercising the alias. You should be able to use that to reproduce the issue you're seeing, but those tests seem to cover this.

FWIW i noticed "self" is passed in as "self_" and so you probably need to add a new field is_self with an alias of self_.

I don't have any events that are returning displayName from the API. When testing using the API Explorer at https://developers.google.com/calendar/api/v3/reference/events/get I don't see any. So, my assumption is its not returned from the API.

One way you can "sniff" the response values is adding a root validator on the Attendees values to see the raw values passed in from json before any parsing happens to make sure they are coming through:

    @root_validator(pre=True)
    def _parse_attendee_values(cls, values: dict[str, Any]) -> dict[str, Any]:
        """Parse attendee values."""
        _LOGGER.debug("Attendee values: %s", values)

Which will log something like this (this example is from the tests but you can use it from the real API too):

DEBUG    gcal_sync.model:model.py:332 Attendee values: {'id': 'attendee-id-1', 'email': 'example1@example.com', 'displayName': 'Example 1', 'comment': 'comment 1', 'self_': True}
DEBUG    gcal_sync.model:model.py:332 Attendee values: {'id': 'attendee-id-2', 'email': 'example2@example.com', 'displayName': 'Example 2', 'responseStatus': 'accepted'}
DEBUG    gcal_sync.model:model.py:332 Attendee values: {'id': 'attendee-id-3', 'email': 'example3@example.com', 'displayName': 'Example 3', 'responseStatus': 'declined'}