Skip to content

Commit 30f7eab

Browse files
committed
bugfixing
1 parent 108a10f commit 30f7eab

2 files changed

Lines changed: 55 additions & 37 deletions

File tree

caldav/compatibility_hints.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
encountered while working on the caldav library, and descriptions on
55
how the well-known servers behave.
66
"""
7-
87
## NEW STYLE
9-
108
## (we're gradually moving stuff from the good old
119
## "incompatibility_description" below over to
1210
## "compatibility_features")
@@ -51,8 +49,8 @@ class FeatureSet:
5149
"save_load": {
5250
"description": "Calendar server should accept ojects with RRULE given, as well as objects with recurrence sets, and should be able to deliver back the same data",
5351
"features": {
52+
"event": {"description": "works with events"},
5453
"todo": {"description": "works with tasks"},
55-
"todo": {"description": "works with events"},
5654
}
5755
},
5856
"search_includes_implicit_recurrences": {
@@ -61,7 +59,9 @@ class FeatureSet:
6159
"features": {
6260
"infinite-scope": {
6361
"description": "Needless to say, search on any future date range, no matter how far out in the future, should yield the recurring object"
64-
}
62+
},
63+
"event": {"description": "works with events"},
64+
"todo": {"description": "works with tasks"},
6565
}
6666
},
6767
"expanded_search": {
@@ -146,21 +146,32 @@ def check_support(self, feature, return_type=bool):
146146
TODO: write a better docstring
147147
"""
148148
feature_info = self.find_feature(feature)
149-
support = self._server_features.get(feature, {'support': 'full'})
149+
node = self._server_features
150+
feature_path = feature.split('.')
151+
support = None
152+
for x in feature_path:
153+
if x in node:
154+
support = node[x]
155+
node = support.get('features', {})
156+
else:
157+
if support is None:
158+
## default is that the server supports everything
159+
## TODO: consider feature_info['type'], be smarter about this
160+
support = {'support': 'full'}
161+
break
150162
if return_type == str:
151163
## TODO: consider type, be smarter about it
152164
return support.get('support', support.get('enable', support.get('behaviour')))
153165
elif return_type == dict:
154166
return support
155167
elif return_type == bool:
156-
## TODO: consider type, be smarter about it
168+
## TODO: consider feature_info['type'], be smarter about this
157169
return support.get('support', 'full') == 'full' and not support.get('enable') and not support.get('behaviour')
158170

159-
160171
def find_feature(self, feature: str) -> dict:
161172
"""
162173
Feature should be a string like feature.subfeature.subsubfeature.
163-
174+
164175
Looks through the FEATURES list and returns the relevant section.
165176
166177
Will raise an AssertionError if feature is not found

tests/test_caldav.py

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
from .conf import xandikos_host
4242
from .conf import xandikos_port
4343
from caldav.compatibility_hints import FeatureSet
44-
from caldav.compatibility_hints import incompatibility_description ## TEMP - should be removed in the future
44+
from caldav.compatibility_hints import (
45+
incompatibility_description,
46+
) ## TEMP - should be removed in the future
4547
from caldav.davclient import DAVClient
4648
from caldav.davclient import DAVResponse
4749
from caldav.davclient import get_davclient
@@ -660,6 +662,7 @@ class RepeatedFunctionalTestsBaseClass:
660662
"""
661663

662664
_default_calendar = None
665+
663666
## TODO: move to davclient or compatibility_hints
664667
def check_support(self, feature, return_type=bool):
665668
"""
@@ -680,8 +683,8 @@ def skip_on_compatibility_flag(self, flag):
680683
pytest.skip("Test skipped due to server incompatibility issue: " + msg)
681684

682685
def skip_unless_support(self, feature):
683-
if self.check_support(feature):
684-
msg = self.features.find_feature(feature).get('description', feature)
686+
if not self.check_support(feature):
687+
msg = self.features.find_feature(feature).get("description", feature)
685688
pytest.skip("Test skipped due to server incompatibility issue: " + msg)
686689

687690
def setup_method(self):
@@ -692,7 +695,7 @@ def setup_method(self):
692695
features = self.server_params.get("features", {})
693696

694697
## Temp thing
695-
self.old_features = features.get('old_flags', [])
698+
self.old_features = features.get("old_flags", [])
696699

697700
self.features = FeatureSet(self.server_params.get("features", {}))
698701

@@ -711,13 +714,13 @@ def setup_method(self):
711714
self.caldav.__enter__()
712715

713716
foo = self.check_support("rate-limit", dict)
714-
if foo.get('enable'):
715-
rate_delay = foo['interval']/foo['count']
717+
if foo.get("enable"):
718+
rate_delay = foo["interval"] / foo["count"]
716719
self.caldav.request = _delay_decorator(self.caldav.request, t=rate_delay)
717720
foo = self.check_support("search-cache", dict)
718-
if foo.get('behaviour') == 'delay':
721+
if foo.get("behaviour") == "delay":
719722
Calendar._search = Calendar.search
720-
Calendar.search = _delay_decorator(Calendar.search, t=foo['delay'])
723+
Calendar.search = _delay_decorator(Calendar.search, t=foo["delay"])
721724

722725
if False and self.check_compatibility_flag("no-current-user-principal"):
723726
self.principal = Principal(
@@ -737,7 +740,10 @@ def setup_method(self):
737740
logging.debug("##############################")
738741

739742
def teardown_method(self):
740-
if self.check_support("search-cache", dict).get('behaviour', 'no-cache') != 'no-cache':
743+
if (
744+
self.check_support("search-cache", dict).get("behaviour", "no-cache")
745+
!= "no-cache"
746+
):
741747
Calendar.search = Calendar._search
742748
logging.debug("############################")
743749
logging.debug("############## test teardown_method")
@@ -781,9 +787,9 @@ def _cleanup(self, mode=None):
781787
def _teardownCalendar(self, name=None, cal_id=None):
782788
try:
783789
cal = self.principal.calendar(name=name, cal_id=cal_id)
784-
if self.check_compatibility_flag(
785-
"sticky_events"
786-
) or not self.check_support("delete-calendar"):
790+
if self.check_compatibility_flag("sticky_events") or not self.check_support(
791+
"delete-calendar"
792+
):
787793
for goo in cal.objects():
788794
try:
789795
goo.delete()
@@ -2420,7 +2426,9 @@ def testTodoDatesearch(self):
24202426
# Hence a compliant server should chuck out all the todos except t5.
24212427
# Not all servers perform according to (my interpretation of) the RFC.
24222428
foo = 5
2423-
if not self.check_support('recurrences.todo'):
2429+
if not self.check_support(
2430+
"recurrences.search_includes_implicit_recurrences.todo"
2431+
):
24242432
foo -= 1 ## t6 will not be returned
24252433
if self.check_compatibility_flag(
24262434
"vtodo_datesearch_nodtstart_task_is_skipped"
@@ -2434,21 +2442,16 @@ def testTodoDatesearch(self):
24342442
assert len(todos2) == foo
24352443

24362444
## verify that "expand" works
2437-
if self.check_support('recurrences.todo'):
2445+
if self.check_support("recurrences.search_includes_implicit_recurrences.todo"):
24382446
## todo1 and todo2 should be the same (todo1 using legacy method)
24392447
## todo1 and todo2 tries doing server side expand, with fallback
24402448
## to client side expand
2441-
assert (
2442-
len([x for x in todos1 if "DTSTART:20020415T1330" in x.data]) == 1
2443-
)
2444-
assert (
2445-
len([x for x in todos2 if "DTSTART:20020415T1330" in x.data]) == 1
2446-
)
2449+
assert len([x for x in todos1 if "DTSTART:20020415T1330" in x.data]) == 1
2450+
assert len([x for x in todos2 if "DTSTART:20020415T1330" in x.data]) == 1
24472451
if self.check_support("recurrences.expanded_search"):
2448-
assert (
2449-
len([x for x in todos4 if "DTSTART:20020415T1330" in x.data])
2450-
== 1
2451-
)
2452+
assert (
2453+
len([x for x in todos4 if "DTSTART:20020415T1330" in x.data]) == 1
2454+
)
24522455
## todo3 is client side expand, should always work
24532456
assert len([x for x in todos3 if "DTSTART:20020415T1330" in x.data]) == 1
24542457
## todo4 is server side expand, may work dependent on server
@@ -2471,9 +2474,9 @@ def testTodoDatesearch(self):
24712474
## * t4 should probably be returned, as it has no dtstart nor due and
24722475
## hence is also considered to span over infinite time
24732476
urls_found = [x.url for x in todos1]
2474-
urls_found2 = [x.url for x in todos1]
2477+
urls_found2 = [x.url for x in todos2]
24752478
assert urls_found == urls_found2
2476-
if self.check_support('recurrences.todo'):
2479+
if self.check_support("recurrences.search_includes_implicit_recurrences"):
24772480
urls_found.remove(t6.url)
24782481
if not self.check_compatibility_flag(
24792482
"vtodo_datesearch_nodtstart_task_is_skipped"
@@ -2684,7 +2687,9 @@ def testSetCalendarProperties(self):
26842687
try:
26852688
cc.delete()
26862689
except error.DeleteError:
2687-
if not self.check_support("delete-calendar") or self.check_compatibility_flag("unique_calendar_ids"):
2690+
if not self.check_support(
2691+
"delete-calendar"
2692+
) or self.check_compatibility_flag("unique_calendar_ids"):
26882693
raise
26892694

26902695
c.set_properties(
@@ -3086,8 +3091,10 @@ def testRecurringDateWithExceptionSearch(self):
30863091
assert "RRULE" not in r[1].data
30873092

30883093
asserts_on_results = [r]
3089-
if self.check_support("recurrences.expanded_search.recurrence_exception_handling"):
3090-
asserts_on_results.append(rs)
3094+
if self.check_support(
3095+
"recurrences.expanded_search.recurrence_exception_handling"
3096+
):
3097+
asserts_on_results.append(rs)
30913098

30923099
for r in asserts_on_results:
30933100
assert isinstance(

0 commit comments

Comments
 (0)