Explorar el Código

honor TRIGGER of VALARM for timerange filtering

Peter Bieringer hace 9 meses
padre
commit
f56416b2fb
Se han modificado 1 ficheros con 28 adiciones y 4 borrados
  1. 28 4
      radicale/item/filter.py

+ 28 - 4
radicale/item/filter.py

@@ -121,6 +121,7 @@ def comp_match(item: "item.Item", filter_: ET.Element, level: int = 0) -> bool:
         logger.warning("Filtering %s is not supported", name)
         return True
     # Point #3 and #4 of rfc4791-9.7.1
+    trigger = None
     if level == 0:
         components = [item.vobject_item]
     elif level == 1:
@@ -128,15 +129,18 @@ def comp_match(item: "item.Item", filter_: ET.Element, level: int = 0) -> bool:
     elif level == 2:
         components = list(getattr(item.vobject_item, "%s_list" % tag.lower()))
         for comp in components:
-            if not hasattr(comp, name.lower()):
+            subcomp = getattr(comp, name.lower(), None)
+            if not subcomp:
                 return False
+            if hasattr(subcomp, "trigger"):
+                trigger = subcomp.trigger.value
     for child in filter_:
         if child.tag == xmlutils.make_clark("C:prop-filter"):
             if not any(prop_match(comp, child, "C")
                        for comp in components):
                 return False
         elif child.tag == xmlutils.make_clark("C:time-range"):
-            if not time_range_match(item.vobject_item, filter_[0], tag):
+            if not time_range_match(item.vobject_item, filter_[0], tag, trigger):
                 return False
         elif child.tag == xmlutils.make_clark("C:comp-filter"):
             if not comp_match(item, child, level=level + 1):
@@ -166,7 +170,7 @@ def prop_match(vobject_item: vobject.base.Component,
     # Point #3 and #4 of rfc4791-9.7.2
     for child in filter_:
         if ns == "C" and child.tag == xmlutils.make_clark("C:time-range"):
-            if not time_range_match(vobject_item, child, name):
+            if not time_range_match(vobject_item, child, name, None):
                 return False
         elif child.tag == xmlutils.make_clark("%s:text-match" % ns):
             if not text_match(vobject_item, child, name, ns):
@@ -180,9 +184,10 @@ def prop_match(vobject_item: vobject.base.Component,
 
 
 def time_range_match(vobject_item: vobject.base.Component,
-                     filter_: ET.Element, child_name: str) -> bool:
+                     filter_: ET.Element, child_name: str, trigger: datetime | None) -> bool:
     """Check whether the component/property ``child_name`` of
        ``vobject_item`` matches the time-range ``filter_``."""
+    # supporting since 3.5.4 now optional trigger (either absolute or relative offset)
 
     if not filter_.get("start") and not filter_.get("end"):
         return False
@@ -193,6 +198,25 @@ def time_range_match(vobject_item: vobject.base.Component,
     def range_fn(range_start: datetime, range_end: datetime,
                  is_recurrence: bool) -> bool:
         nonlocal matched
+        if trigger:
+            # if trigger is given, only check range_start
+            if isinstance(trigger, timedelta):
+                # trigger is a offset, apply to range_start
+                if start < range_start + trigger and range_start + trigger < end:
+                    matched = True
+                    return True
+                else:
+                    return False
+            elif isinstance(trigger, datetime):
+                # trigger is absolute, use instead of range_start
+                if start < trigger and trigger < end:
+                    matched = True
+                    return True
+                else:
+                    return False
+            else:
+                logger.warning("item/filter/time_range_match/range_fn: unsupported data format of provided trigger=%r", trigger)
+                return True
         if start < range_end and range_start < end:
             matched = True
             return True