Support param-filter
This commit is contained in:
parent
da1363f026
commit
fef9f0abc6
@ -173,10 +173,11 @@ def _prop_match(item, filter_):
|
|||||||
# Point #1 of rfc4791-9.7.2
|
# Point #1 of rfc4791-9.7.2
|
||||||
return filter_.get("name").lower() in vobject_item.contents
|
return filter_.get("name").lower() in vobject_item.contents
|
||||||
else:
|
else:
|
||||||
|
name = filter_.get("name").lower()
|
||||||
if filter_length == 1:
|
if filter_length == 1:
|
||||||
if filter_[0].tag == _tag("C", "is-not-defined"):
|
if filter_[0].tag == _tag("C", "is-not-defined"):
|
||||||
# Point #2 of rfc4791-9.7.2
|
# Point #2 of rfc4791-9.7.2
|
||||||
return filter_.get("name").lower() not in vobject_item.contents
|
return name not in vobject_item.contents
|
||||||
if filter_[0].tag == _tag("C", "time-range"):
|
if filter_[0].tag == _tag("C", "time-range"):
|
||||||
# Point #3 of rfc4791-9.7.2
|
# Point #3 of rfc4791-9.7.2
|
||||||
if not _time_range_match(item, filter_[0]):
|
if not _time_range_match(item, filter_[0]):
|
||||||
@ -184,22 +185,11 @@ def _prop_match(item, filter_):
|
|||||||
filter_.remove(filter_[0])
|
filter_.remove(filter_[0])
|
||||||
elif filter_[0].tag == _tag("C", "text-match"):
|
elif filter_[0].tag == _tag("C", "text-match"):
|
||||||
# Point #4 of rfc4791-9.7.2
|
# Point #4 of rfc4791-9.7.2
|
||||||
# TODO: collations are not supported, but the default ones needed
|
if not _text_match(vobject_item, filter_[0], name):
|
||||||
# for DAV servers are actually pretty useless. Texts are lowered to
|
|
||||||
# be case-insensitive, almost as the "i;ascii-casemap" value.
|
|
||||||
match = next(filter_[0].itertext()).lower()
|
|
||||||
value = vobject_item.getChildValue(filter_.get("name").lower())
|
|
||||||
if value is None:
|
|
||||||
return False
|
|
||||||
value = value.lower()
|
|
||||||
if filter_[0].get("negate-condition") == "yes":
|
|
||||||
if match in value:
|
|
||||||
return False
|
|
||||||
elif match not in value:
|
|
||||||
return False
|
return False
|
||||||
filter_.remove(filter_[0])
|
filter_.remove(filter_[0])
|
||||||
return all(
|
return all(
|
||||||
_param_filter_match(item, param_filter)
|
_param_filter_match(vobject_item, param_filter, name)
|
||||||
for param_filter in filter_)
|
for param_filter in filter_)
|
||||||
|
|
||||||
|
|
||||||
@ -213,14 +203,46 @@ def _time_range_match(item, filter_):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _param_filter_match(item, filter_):
|
def _text_match(vobject_item, filter_, child_name, attrib_name=None):
|
||||||
|
"""Check whether the ``item`` matches the text-match ``filter_``.
|
||||||
|
|
||||||
|
See rfc4791-9.7.5.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# TODO: collations are not supported, but the default ones needed
|
||||||
|
# for DAV servers are actually pretty useless. Texts are lowered to
|
||||||
|
# be case-insensitive, almost as the "i;ascii-casemap" value.
|
||||||
|
match = next(filter_.itertext()).lower()
|
||||||
|
children = getattr(vobject_item, "%s_list" % child_name, [])
|
||||||
|
if attrib_name:
|
||||||
|
condition = any(
|
||||||
|
match in attrib.lower() for child in children
|
||||||
|
for attrib in child.params.get(attrib_name, []))
|
||||||
|
else:
|
||||||
|
condition = any(match in child.value.lower() for child in children)
|
||||||
|
if filter_.get("negate-condition") == "yes":
|
||||||
|
return not condition
|
||||||
|
else:
|
||||||
|
return condition
|
||||||
|
|
||||||
|
|
||||||
|
def _param_filter_match(vobject_item, filter_, parent_name):
|
||||||
"""Check whether the ``item`` matches the param-filter ``filter_``.
|
"""Check whether the ``item`` matches the param-filter ``filter_``.
|
||||||
|
|
||||||
See rfc4791-9.7.3.
|
See rfc4791-9.7.3.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# TODO: implement this
|
name = filter_.get("name")
|
||||||
return True
|
children = getattr(vobject_item, "%s_list" % parent_name, [])
|
||||||
|
condition = any(name in child.params for child in children)
|
||||||
|
if len(filter_):
|
||||||
|
if filter_[0].tag == _tag("C", "text-match"):
|
||||||
|
return condition and _text_match(
|
||||||
|
vobject_item, filter_[0], parent_name, name)
|
||||||
|
elif filter_[0].tag == _tag("C", "is-not-defined"):
|
||||||
|
return not condition
|
||||||
|
else:
|
||||||
|
return condition
|
||||||
|
|
||||||
|
|
||||||
def name_from_path(path, collection):
|
def name_from_path(path, collection):
|
||||||
|
@ -25,6 +25,9 @@ LAST-MODIFIED:20130902T150158Z
|
|||||||
DTSTAMP:20130902T150158Z
|
DTSTAMP:20130902T150158Z
|
||||||
UID:event
|
UID:event
|
||||||
SUMMARY:Event
|
SUMMARY:Event
|
||||||
|
ORGANIZER:mailto:unclesam@example.com
|
||||||
|
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=TENTATIVE;CN=Jane Doe:MAILTO:janedoe@example.com
|
||||||
|
ATTENDEE;ROLE=REQ-PARTICIPANT;DELEGATED-FROM="MAILTO:bob@host.com";PARTSTAT=ACCEPTED;CN=John Doe:MAILTO:johndoe@example.com
|
||||||
DTSTART;TZID=Europe/Paris:20130902T180000
|
DTSTART;TZID=Europe/Paris:20130902T180000
|
||||||
DTEND;TZID=Europe/Paris:20130902T190000
|
DTEND;TZID=Europe/Paris:20130902T190000
|
||||||
END:VEVENT
|
END:VEVENT
|
||||||
|
@ -217,7 +217,7 @@ class BaseRequests:
|
|||||||
</C:comp-filter>"""])
|
</C:comp-filter>"""])
|
||||||
|
|
||||||
def test_text_match_filter(self):
|
def test_text_match_filter(self):
|
||||||
"""Report request with tag-based filter on calendar."""
|
"""Report request with text-match filter on calendar."""
|
||||||
assert "href>/calendar.ics/event.ics</" in self._test_filter(["""
|
assert "href>/calendar.ics/event.ics</" in self._test_filter(["""
|
||||||
<C:comp-filter name="VCALENDAR">
|
<C:comp-filter name="VCALENDAR">
|
||||||
<C:comp-filter name="VEVENT">
|
<C:comp-filter name="VEVENT">
|
||||||
@ -251,6 +251,51 @@ class BaseRequests:
|
|||||||
</C:comp-filter>
|
</C:comp-filter>
|
||||||
</C:comp-filter>"""])
|
</C:comp-filter>"""])
|
||||||
|
|
||||||
|
def test_param_filter(self):
|
||||||
|
"""Report request with param-filter on calendar."""
|
||||||
|
assert "href>/calendar.ics/event.ics</" in self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:prop-filter name="ATTENDEE">
|
||||||
|
<C:param-filter name="PARTSTAT">
|
||||||
|
<C:text-match collation="i;ascii-casemap"
|
||||||
|
>ACCEPTED</C:text-match>
|
||||||
|
</C:param-filter>
|
||||||
|
</C:prop-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""])
|
||||||
|
assert "href>/calendar.ics/event.ics</" not in self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:prop-filter name="ATTENDEE">
|
||||||
|
<C:param-filter name="PARTSTAT">
|
||||||
|
<C:text-match collation="i;ascii-casemap"
|
||||||
|
>UNKNOWN</C:text-match>
|
||||||
|
</C:param-filter>
|
||||||
|
</C:prop-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""])
|
||||||
|
assert "href>/calendar.ics/event.ics</" not in self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:prop-filter name="ATTENDEE">
|
||||||
|
<C:param-filter name="PARTSTAT">
|
||||||
|
<C:is-not-defined />
|
||||||
|
</C:param-filter>
|
||||||
|
</C:prop-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""])
|
||||||
|
assert "href>/calendar.ics/event.ics</" in self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:prop-filter name="ATTENDEE">
|
||||||
|
<C:param-filter name="UNKNOWN">
|
||||||
|
<C:is-not-defined />
|
||||||
|
</C:param-filter>
|
||||||
|
</C:prop-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""])
|
||||||
|
|
||||||
|
|
||||||
class TestMultiFileSystem(BaseRequests, BaseTest):
|
class TestMultiFileSystem(BaseRequests, BaseTest):
|
||||||
"""Base class for filesystem tests."""
|
"""Base class for filesystem tests."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user