1
0
Fork 0
mirror of https://github.com/Kozea/Radicale.git synced 2025-08-04 18:22:26 +00:00

(#1812) Work on expand events time-range filter processing

This commit is contained in:
Georgiy 2025-07-01 23:00:25 +03:00 committed by David Greaves
parent 18710d9a27
commit 9d591bd514

View file

@ -224,9 +224,17 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
root.findall(xmlutils.make_clark("C:filter")) +
root.findall(xmlutils.make_clark("CR:filter")))
# extract time-range filter for processing after main filters
time_range_element = None
non_time_range_filters = []
for filter_ in filters:
time_range_element = filter_.find(".//" + xmlutils.make_clark("C:time-range"))
if time_range_element is None:
non_time_range_filters.append(filter_)
# Retrieve everything required for finishing the request.
retrieved_items = list(retrieve_items(
base_prefix, path, collection, hreferences, filters, multistatus))
base_prefix, path, collection, hreferences, non_time_range_filters, multistatus))
collection_tag = collection.tag
# !!! Don't access storage after this !!!
unlock_storage_fn()
@ -239,7 +247,7 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
if filters and not filters_matched:
try:
if not all(test_filter(collection_tag, item, filter_)
for filter_ in filters):
for filter_ in non_time_range_filters):
continue
except ValueError as e:
raise ValueError("Failed to filter item %r from %r: %s" %
@ -248,6 +256,13 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
raise RuntimeError("Failed to filter item %r from %r: %s" %
(item.href, collection.path, e)) from e
# Filtering non-recurring events by time-range
if (time_range_element is not None) and not hasattr(item, 'rrule'):
start, end = radicale_filter.time_range_timestamps(time_range_element)
istart, iend = item.time_range
if istart >= end or iend <= start:
continue
found_props = []
not_found_props = []
@ -280,8 +295,18 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
end, '%Y%m%dT%H%M%SZ'
).replace(tzinfo=datetime.timezone.utc)
time_range_start = None
time_range_end = None
if time_range_element is not None:
time_range_start, time_range_end = radicale_filter.parse_time_range(time_range_element)
expanded_element = _expand(
element, copy.copy(item), start, end)
element=element, item=copy.copy(item),
start=start, end=end,
time_range_start=time_range_start, time_range_end=time_range_end,
)
found_props.append(expanded_element)
else:
found_props.append(element)
@ -303,6 +328,8 @@ def _expand(
item: radicale_item.Item,
start: datetime.datetime,
end: datetime.datetime,
time_range_start: Optional[datetime.datetime] = None,
time_range_end: Optional[datetime.datetime] = None,
) -> ET.Element:
vevent_component: vobject.base.Component = copy.copy(item.vobject_item)
@ -347,6 +374,13 @@ def _expand(
for recurrence_dt in recurrences:
recurrence_utc = recurrence_dt.astimezone(datetime.timezone.utc)
if time_range_start is not None and time_range_end is not None:
dtstart = recurrence_dt if all_day_event else recurrence_utc
dtend = dtstart + duration if duration else dtstart
if not (dtstart < time_range_end and dtend > time_range_start):
continue
i_overridden, vevent = _find_overridden(i_overridden, vevents_overridden, recurrence_utc, dt_format)
if not vevent:
@ -377,6 +411,47 @@ def _expand(
else:
vevent_component.add(vevent)
# Filter overridden events and vevent_recurrence if recurrences is empty
# Todo: optimize that code
if time_range_start is not None and time_range_end is not None:
filtered_vevents = []
for vevent in vevents_overridden:
dtstart = vevent.dtstart.value
dtend = vevent.dtend.value if hasattr(vevent, 'dtend') else dtstart
dtstart = datetime.datetime.strptime(
dtstart, "%Y%m%dT%H%M%SZ").replace(
tzinfo=datetime.timezone.utc)
dtend = datetime.datetime.strptime(
dtend, "%Y%m%dT%H%M%SZ").replace(
tzinfo=datetime.timezone.utc)
if dtstart < time_range_end and dtend > time_range_start:
filtered_vevents.append(vevent)
dtstart = vevent_recurrence.dtstart.value
dtend = vevent_recurrence.dtend.value if hasattr(vevent_recurrence, 'dtend') else dtstart
dtstart = datetime.datetime.strptime(
dtstart, "%Y%m%dT%H%M%SZ").replace(
tzinfo=datetime.timezone.utc)
dtend = datetime.datetime.strptime(
dtend, "%Y%m%dT%H%M%SZ").replace(
tzinfo=datetime.timezone.utc)
if filtered_vevents or (dtstart < time_range_end and dtend > time_range_start):
if filtered_vevents:
vevent_component.vevent = filtered_vevents[0]
for vevent in filtered_vevents[1:]:
vevent_component.add(vevent)
if dtstart < time_range_end and dtend > time_range_start:
if not filtered_vevents:
vevent_component.vevent = vevent_recurrence
else:
vevent_component.add(vevent_recurrence)
else:
element.text = ""
return element
element.text = vevent_component.serialize()
return element