Skip to content

Commit

Permalink
Search method: fixed inconsistencies and optimized a bit
Browse files Browse the repository at this point in the history
Some logic was only run when the expand-flag was set to True:

1) The logic automatically loading objects that aren't loaded

2) The logic removing "empty" responses from Google,

This logic ensures a consistent return from the search-method also for servers
not conforming to the RFC (by returning unloaded data or empty responses)

The second was fixed in the previous commit, but it feels wrong converting the
data to an icalendar object unless it's needed.
  • Loading branch information
tobixen committed Dec 26, 2023
1 parent 28979a6 commit 4daf65f
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ This project should more or less adhere to [Semantic Versioning](https://semver.
* Georges Toth (@sim0nx) did a lot of efforts lifting up the project to more modern standards.
* A hook for collecting debug information has been in the pull request for ages. I've decided to include it in 1.4.0.
* Code formatting / style fixes.
* Search method did some logic handling non-conformant servers (loading data from the server if the search response didn't include the icalendar data, ignoring trash from the Google server when it returns data without a VTODO/VEVENT/VJOURNAL component.

### Fixed

* Revisited a problem that Google sometimes delivers junk when doing searches - credits to github user @zhwei in https://github.com/python-caldav/caldav/pull/366
* There were some compatibility-logic loading objects if the server does not deliver icalendar data (as it's suppsoed to do according to the RFC), but only if passing the `expand`-flag to the `search`-method. Fixed that it loads regardless of weather `expand` is set or not. Also in https://github.com/python-caldav/caldav/pull/366

### Changed

* In https://github.com/python-caldav/caldav/pull/366, I optimized the logic in `search` a bit, now all data from the server not containing a VEVENT, VTODO or VJOURNAL will be thrown away. I believe this won't cause any problems for anyone, as the server should only deliver such components, but I may be wrong.

### Added

Expand Down
30 changes: 20 additions & 10 deletions caldav/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,13 @@ def search(
xml, comp_class, props=props
)

for o in objects:
## This would not be needed if the servers would follow the standard ...
o.load(only_if_unloaded=True)

## Google sometimes returns empty objects
objects = [o for o in objects if o.has_component()]

if kwargs.get("expand", False):
## expand can only be used together with start and end.
## Error checking is done in build_search_xml_query. If
Expand All @@ -1229,13 +1236,6 @@ def search(
start = kwargs["start"]
end = kwargs["end"]

for o in objects:
## This would not be needed if the servers would follow the standard ...
o.load(only_if_unloaded=True)

## Google sometimes returns empty objects
objects = [o for o in objects if o.icalendar_component]

for o in objects:
component = o.icalendar_component
if component is None:
Expand All @@ -1248,9 +1248,6 @@ def search(
objects = []
for o in objects_:
objects.extend(o.split_expanded())
else:
## Google sometimes returns empty objects
objects = [o for o in objects if o.icalendar_component]

def sort_key_func(x):
ret = []
Expand Down Expand Up @@ -2122,6 +2119,8 @@ def _get_icalendar_component(self, assert_one=False):
See also https://github.com/python-caldav/caldav/issues/232
"""
self.load(only_if_unloaded=True)
if not self.icalendar_instance:
return None
ret = [
x
for x in self.icalendar_instance.subcomponents
Expand Down Expand Up @@ -2530,6 +2529,17 @@ def is_loaded(self):
self._data or self._vobject_instance or self._icalendar_instance
) and self.data.count("BEGIN:") > 1

def has_component(self):
return (
self._data
or self._vobject_instance
or (self._icalendar_instance and self.icalendar_component)
) and self.data.count("BEGIN:VEVENT") + self.data.count(
"BEGIN:VTODO"
) + self.data.count(
"BEGIN:VJOURNAL"
) > 0

def __str__(self) -> str:
return "%s: %s" % (self.__class__.__name__, self.url)

Expand Down
8 changes: 5 additions & 3 deletions tests/test_caldav_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,14 @@ def testAbsoluteURL(self):
"http://cal.example.com/home/bernard/calendars/"
)

@mock.patch("caldav.objects.CalendarObjectResource.is_loaded")
def testDateSearch(self, mocked):
def _load(self, only_if_unloaded=True):
self.data = todo6

@mock.patch("caldav.objects.CalendarObjectResource.load", new=_load)
def testDateSearch(self):
"""
## ref https://github.com/python-caldav/caldav/issues/133
"""
mocked.__bool__ = lambda self: True
xml = """<xml><multistatus xmlns="DAV:">
<response>
<href>/principals/calendar/home@petroski.example.com/963/43B060B3-A023-48ED-B9E7-6FFD38D5073E.ics</href>
Expand Down

0 comments on commit 4daf65f

Please sign in to comment.