Skip to content

Commit 507b080

Browse files
authored
compatibility hints - refactoring efforts
In 1.5.0, I moved the compability matrix from the tests directory and into the project itself - now I'm doing a major overhaul of it. This change is not much visible for end users yet - but already now it's possible to configure "compatibility hints" when setting up the davclient, and the idea is that different kind of workarounds may be applied depending on the compatibility-matrix. Search without comp-type is wonky on many servers, now the `search`-method will automatically deliver a union of a search of the three different comp-types if a comp-type is not set in the parameters *and* it's declared that the compatibility matrix does not work. In parallel I'm developing a stand-alone tool caldav-server-tester to check the compatibility of a caldav server. This is "work in progress", the rewriting of old compatibility hints is incomplete. It's a lot of work, so it will take some time to fully complete it.
1 parent 2f33b55 commit 507b080

9 files changed

Lines changed: 655 additions & 317 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## IMPORTANT - "flapping" changeset!
44

5-
In 2.0.0 I dropped the dependency on the requests library as the project is stagnant and adopted niquests, a fork of the requests library. It's a small change, and three github issues could be closed just by doing this switch. In addition niquests supports HTTP/2 and is one possible way forward for implementing async support. However, the change has proven controversial, shortly after releasing 2.0 I had to revert back to requests and release 2.0.1. Right after releasing 2.0.1, I reverted again so that the master branch is using niquests.
5+
The requests library is stagnant, so in 2.0.0 I replaced it with a fork niquests. It's a very tiny changeset, and three github issues could be closed just by doing this switch. In addition niquests supports HTTP/2 and is one possible way forward for implementing async support. However, the change has proven controversial, shortly after releasing 2.0 I had to revert back to requests and release 2.0.1. Right after releasing 2.0.1, I reverted again so that the master branch is using niquests.
66

77
My plan now is to keep doing dual releases while maintaining the 2.x-series - one with niquests and one with requests. You are encouraged to make an informed decision on weather you are most comfortable with the stable but stagnant requests, or the niquests fork and choose your version accordingly. When I'm starting to work on 3.0 (which will support async requests), I will think deeply about this and either choose niquests, httpx, or (it's always possible to hope!) requests 3.0. **Your opinion is valuable for me**. Feel free to comment on https://github.com/python-caldav/caldav/issues/457, https://github.com/python-caldav/caldav/issues/530 or https://github.com/jawah/niquests/issues/267 if you have a github account, and if not you can reach out at python-http@plann.no
88

@@ -16,6 +16,10 @@ This project should adhere to [Semantic Versioning](https://semver.org/spec/v2.0
1616

1717
## [Unreleased]
1818

19+
### Changed
20+
21+
* In 1.5.0, I moved the compability matrix from the tests directory and into the project itself - now I'm doing a major overhaul of it. This change is not much visible for end users yet - but already now it's possible to configure "compatibility hints" when setting up the davclient, and the idea is that different kind of workarounds may be applied depending on the compatibility-matrix. Search without comptype is wonky on many servers, now the `search`-method will automatically deliver a union of a search of the three different comptypes if a comptype is not set in the parameters *and* it's declared that the compatibility matrix does not work. In parallell I'm developing a stand-alone tool caldav-server-tester to check the compatibility of a caldav server.
22+
1923
### Fixes
2024

2125
* A search without filtering on comp-type on a calendar containing a mix of events, journals and tasks should return a mix of such. (All the examples in the RFC includes the comp-type filter, so many servers does not support this). There were a bug in the auto-detection of comp-type, so tasks would typically be wrapped as events or vice-versa. https://github.com/python-caldav/caldav/pull/540

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,9 @@ Features:
99
* search events by dates
1010
* etc.
1111

12-
See the file [examples/basic_usage_examples.py](examples/basic_usage_examples.py) to get started.
12+
The documentation was freshed up a bit as of version 2.0, and is available at https://caldav.readthedocs.io/
1313

14-
Links:
15-
16-
* [Pypi](https://pypi.org/project/caldav)
17-
* [Documentation](docs/source/index.rst) - should be automatically mirrored on https://caldav.readthedocs.io/en/latest/
14+
The package is published at [Pypi](https://pypi.org/project/caldav)
1815

1916
Licences:
2017

caldav/collection.py

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ def search(
763763
xml=None,
764764
comp_class: Optional[_CC] = None,
765765
todo: Optional[bool] = None,
766-
include_completed: bool = False,
766+
include_completed: bool = None,
767767
sort_keys: Sequence[str] = (),
768768
sort_reverse: bool = False,
769769
expand: bool = False,
@@ -860,21 +860,18 @@ def search(
860860
if todo and not include_completed:
861861
matches1 = self.search(
862862
todo=True,
863-
comp_class=comp_class,
864863
ignore_completed1=True,
865864
include_completed=True,
866865
**kwargs,
867866
)
868867
matches2 = self.search(
869868
todo=True,
870-
comp_class=comp_class,
871869
ignore_completed2=True,
872870
include_completed=True,
873871
**kwargs,
874872
)
875873
matches3 = self.search(
876874
todo=True,
877-
comp_class=comp_class,
878875
ignore_completed3=True,
879876
include_completed=True,
880877
**kwargs,
@@ -903,30 +900,48 @@ def search(
903900
raise error.ConsistencyError(
904901
"Inconsistent usage parameters: xml together with other search options"
905902
)
903+
904+
## For some of the workarounds below, we will do a recursive search, with all
905+
## those arguments:
906+
kwargs2 = {
907+
"include_completed": include_completed,
908+
"sort_reverse": sort_reverse,
909+
"expand": expand,
910+
"server_expand": server_expand,
911+
"split_expanded": split_expanded,
912+
"props": props,
913+
}
914+
915+
if not comp_class and not self.client.features.check_support(
916+
"search.comp-type-optional"
917+
):
918+
if kwargs2["include_completed"] is None:
919+
kwargs2["include_completed"] = True
920+
objects = (
921+
self.search(event=True, **kwargs2, **kwargs)
922+
+ self.search(todo=True, **kwargs2, **kwargs)
923+
+ self.search(journal=True, **kwargs2, **kwargs)
924+
)
925+
self.sort_objects(objects, sort_keys, sort_reverse)
926+
return objects
927+
906928
try:
907929
(response, objects) = self._request_report_build_resultlist(
908930
xml, comp_class, props=props
909931
)
932+
910933
except error.ReportError as err:
911-
## Hack for some calendar servers
912-
## yielding 400 if the search does not include compclass.
913-
## Partial fix for https://github.com/python-caldav/caldav/issues/401
914-
## This assumes the client actually wants events and not tasks
915-
## The calendar server in question did not support tasks
916-
## However the most correct would probably be to join
917-
## events, tasks and journals.
918-
## TODO: we need server compatibility hints!
919-
## https://github.com/python-caldav/caldav/issues/402
920-
if not comp_class and not "400" in err.reason:
934+
## This is only for backward compatibility. The logic is even flawed.
935+
## But it does partially fix https://github.com/python-caldav/caldav/issues/401
936+
if (
937+
self.client.features.backward_compatibility_mode
938+
and not comp_class
939+
and not "400" in err.reason
940+
):
921941
return self.search(
922-
event=True,
923-
include_completed=include_completed,
924942
sort_keys=sort_keys,
925943
sort_reverse=sort_reverse,
926-
expand=expand,
927-
server_expand=server_expand,
928-
split_expanded=split_expanded,
929-
props=props,
944+
*kwargs2,
930945
**kwargs,
931946
)
932947
raise
@@ -976,6 +991,17 @@ def search(
976991
for o in objects_:
977992
objects.extend(o.split_expanded())
978993

994+
## partial workaround for https://github.com/python-caldav/caldav/issues/201
995+
for obj in objects:
996+
try:
997+
obj.load(only_if_unloaded=True)
998+
except:
999+
pass
1000+
1001+
self.sort_objects(objects, sort_keys, sort_reverse)
1002+
return objects
1003+
1004+
def sort_objects(self, objects, sort_keys, sort_reverse):
9791005
def sort_key_func(x):
9801006
ret = []
9811007
comp = x.icalendar_component
@@ -1003,7 +1029,6 @@ def sort_key_func(x):
10031029
> datetime.now().strftime("%F%H%M%S")
10041030
),
10051031
}
1006-
## ref https://github.com/python-caldav/caldav/issues/448 - allow strings instead of a sequence here
10071032
for sort_key in sort_keys:
10081033
val = comp.get(sort_key, None)
10091034
if val is None:
@@ -1020,19 +1045,11 @@ def sort_key_func(x):
10201045
return ret
10211046

10221047
if sort_keys:
1048+
## ref https://github.com/python-caldav/caldav/issues/448 - allow strings instead of a sequence here
10231049
if isinstance(sort_keys, str):
10241050
sort_keys = (sort_keys,)
10251051
objects.sort(key=sort_key_func, reverse=sort_reverse)
10261052

1027-
## partial workaround for https://github.com/python-caldav/caldav/issues/201
1028-
for obj in objects:
1029-
try:
1030-
obj.load(only_if_unloaded=True)
1031-
except:
1032-
pass
1033-
1034-
return objects
1035-
10361053
def build_search_xml_query(
10371054
self,
10381055
comp_class=None,

0 commit comments

Comments
 (0)