Hello community, here is the log from the commit of package python-caldav for openSUSE:Factory checked in at 2020-01-24 14:12:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-caldav (Old) and /work/SRC/openSUSE:Factory/.python-caldav.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-caldav" Fri Jan 24 14:12:02 2020 rev:6 rq:766864 version:0.6.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-caldav/python-caldav.changes 2019-04-30 13:03:44.958076816 +0200 +++ /work/SRC/openSUSE:Factory/.python-caldav.new.26092/python-caldav.changes 2020-01-24 14:12:14.366431320 +0100 @@ -1,0 +2,16 @@ +Fri Jan 24 09:52:25 UTC 2020 - Marketa Calabkova <[email protected]> + +- update to 0.6.2 + * caldav/lib/error.py - ProppatchError was not defined, ref https://github.com/python-caldav/caldav/issues/54. + Also added a common base class DAVError, and made sure the error + referenced in #54 will never reappear, even if new methods are + added to DAVClient. + * caldav/elements/cdav.py - fixing a retention problem - the + timezone fixes done recently was not compatible with python 2.7 nor 3.5. + * setup.py - reintroducing dependencies pytz and tzlocal - but only for old python versions + * README.md - proper documentation of the dual licensing, ref + https://github.com/python-caldav/caldav/issues/60 + * caldav/objects.py - fixes (or workarounds?) that solves real-world + issues with iCloud and MS Exchange. Ref https://github.com/python-caldav/caldav/pull/56 + +------------------------------------------------------------------- Old: ---- caldav-0.6.1.tar.gz New: ---- caldav-0.6.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-caldav.spec ++++++ --- /var/tmp/diff_new_pack.LPf5pN/_old 2020-01-24 14:12:15.086431564 +0100 +++ /var/tmp/diff_new_pack.LPf5pN/_new 2020-01-24 14:12:15.086431564 +0100 @@ -1,7 +1,7 @@ # -# spec file for package python +# spec file for package python-caldav # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %global modname caldav Name: python-%{modname} -Version: 0.6.1 +Version: 0.6.2 Release: 0 Summary: CalDAV (RFC4791) client library for Python License: GPL-3.0-or-later AND Apache-2.0 @@ -35,12 +35,14 @@ BuildRequires: python-rpm-macros Requires: python-lxml Requires: python-nose -Requires: python-pytz Requires: python-requests Requires: python-six -Requires: python-tzlocal Requires: python-vobject BuildArch: noarch +%ifpython2 +Requires: python-pytz +Requires: python-tzlocal +%endif %python_subpackages %description ++++++ caldav-0.6.1.tar.gz -> caldav-0.6.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/ChangeLog new/caldav-0.6.2/ChangeLog --- old/caldav-0.6.1/ChangeLog 2019-04-09 20:39:03.000000000 +0200 +++ new/caldav-0.6.2/ChangeLog 2019-09-10 18:18:00.000000000 +0200 @@ -1,5 +1,44 @@ +2019-05-29 Tobias Brox <[email protected]> + * .travis.yml - xandikos cannot be installed on python2.7, but we still want to run the available tests + * caldav/lib/error.py - ProppatchError was not defined, ref https://github.com/python-caldav/caldav/issues/54. Also added a common base class DAVError, and made sure the error referenced in #54 will never reappear, even if new methods are added to DAVClient. + * tests/test_caldav.py - testing that the bug referenced in #54 has been properly plugged in caldav/lib/error.py + * caldav/elements/cdav.py - fixing a retention problem - the timezone fixes done recently was not compatible with python 2.7 nor 3.5. + * caldav/objects.py - revisiting https://github.com/python-caldav/caldav/issues/54 - "... is not None" feels more kosher than "... != None", and added TODO-comment that we need to do more research when those variables are None. Bugfix on the error handling for multi-status-return, should return the specific error code and error message found, not the "207 Multi-Status". + * setup.py - reintroducing dependencies pytz and tzlocal - but only for old python versions + * tests/conf.py - test_xandikos should be defaulted to False if xandikos not present (as it can never be present on 2.7) + * tests/test_cdav.py - make the test python2.7-compatible (though some of the testing is a bit moot, as same code path is used in code and in test) + +2019-05-28 Tobias Brox <[email protected]> + * .travis.yml - ref https://github.com/python-caldav/caldav/issues/57, fixing automated test runs after each commit and on each pull request. + * setup.py - new default tests depends on xandikos + * tests/conf.py - new defaults - testing towards external unreliable public test servers are disabled by default, an internal xandikos server is set up and tests are by default run towards that one + * tests/conf_private.py.EXAMPLE - new file, setting an example on how to run tests towards personal servers + * tests/test_caldav.py - added a test class that spawns a xandikos server instance and runs the functional test suite towards it. Unfortunately it only works under python3. Ref https://github.com/python-caldav/caldav/issues/46 + +2019-05-19 Jelmer Vernooij <[email protected]> + * caldav/objects.py - bugfixing + +2019-05-19 Achim Herwig <[email protected]> + * README.md - proper documentation of the dual licensing, ref https://github.com/python-caldav/caldav/issues/60 + +2019-05-17 Achim Herwig <[email protected]> + * caldav/objects.py - bugfixing + * caldav/elements/cdav.py - more work on timezone handling, ref https://github.com/python-caldav/caldav/issues/55 https://github.com/python-caldav/caldav/issues/52 https://github.com/python-caldav/caldav/pull/59 etc + +2019-05-06 Tobias Brox <[email protected]> + * caldav/objects.py - yet another attempt on fixing the timezone handling mess, ref https://github.com/python-caldav/caldav/issues/55 https://github.com/python-caldav/caldav/issues/52 etc + +2019-04-21 Mark Meijer <[email protected]> + * caldav/objects.py - fixes (or workarounds?) that solves real-world issues with iCloud and MS Exchange. Ref https://github.com/python-caldav/caldav/pull/56 + 2019-04-09 Cyril Robert <[email protected]> - * setup.py - Update to 0.6.1 to fix a tagging issue + * setup.py - Update to 0.6.1 to fix a tagging issue + +2019-04-06 Achim Herwig <[email protected]> + * caldav/objects.py - bugfix, ref #52 + +2019-03-11 Tomáš Chvátal <[email protected]> + * MANIFEST.in - Include tests and changelog in pypi sdist tarball, ref https://github.com/python-caldav/caldav/pull/49 2019-03-11 Tobias Brox <[email protected]> * caldav/objects.py - bugfix: accept text/calendar (required for fetching calendar items from the xandikos server, ref https://github.com/python-caldav/caldav/issues/40 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/PKG-INFO new/caldav-0.6.2/PKG-INFO --- old/caldav-0.6.1/PKG-INFO 2019-04-09 20:40:43.000000000 +0200 +++ new/caldav-0.6.2/PKG-INFO 2019-11-22 21:45:19.232302000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: caldav -Version: 0.6.1 +Version: 0.6.2 Summary: CalDAV (RFC4791) client library Home-page: http://bitbucket.org/cyrilrbt/caldav Author: Cyril Robert diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/README.md new/caldav-0.6.2/README.md --- old/caldav-0.6.1/README.md 2019-03-10 18:32:43.000000000 +0100 +++ new/caldav-0.6.2/README.md 2019-09-10 18:18:00.000000000 +0200 @@ -5,3 +5,4 @@ * [Pypi](http://pypi.python.org/pypi/caldav) * [Documentation](http://packages.python.org/caldav) +Caldav is dual-licensed under the [GNU GENERAL PUBLIC LICENSE Version 3](COPYING.GPL) and the [Apache License 2.0](COPYING.APACHE). \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/caldav/elements/cdav.py new/caldav-0.6.2/caldav/elements/cdav.py --- old/caldav-0.6.1/caldav/elements/cdav.py 2019-03-10 18:32:43.000000000 +0100 +++ new/caldav-0.6.2/caldav/elements/cdav.py 2019-09-10 18:18:00.000000000 +0200 @@ -1,21 +1,34 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- +from datetime import datetime +try: + from datetime import timezone + utc_tz = timezone.utc +except: + import pytz + utc_tz = pytz.utc from caldav.lib.namespace import ns from .base import BaseElement, NamedBaseElement, ValuedBaseElement -import pytz -def _date_with_utc_time(ts): - ## If tzinfo is given, convert to UTC - if (hasattr(ts, 'tzname') and - ts.tzname() is not None and - ts.tzname() != 'UTC'): - ts = ts.astimezone(pytz.utc) - ## If not, assume the timestamp is already in UTC - ## (that's very naïve - but in object.py, we explicitly add the - ## local tzinfo if no tzinfo is given) + +def _to_utc_date_string(ts): + # type (Union[date,datetime]]) -> str + """coerce datetimes to UTC (assume localtime if nothing is given)""" + if (isinstance(ts, datetime)): + try: + ## in python 3.6 and higher, ts.astimezone() will assume a + ## naive timestamp is localtime (and so do we) + ts = ts.astimezone(utc_tz) + except: + ## in python 2.7 and 3.5, ts.astimezone() will fail on + ## naive timestamps, but we'd like to assume they are + ## localtime + import tzlocal + ts = tzlocal.get_localzone().localize(ts).astimezone(utc_tz) return ts.strftime("%Y%m%dT%H%M%SZ") + # Operations class CalendarQuery(BaseElement): tag = ns("C", "calendar-query") @@ -65,9 +78,9 @@ ## ref https://tools.ietf.org/html/rfc4791#section-9.9 super(TimeRange, self).__init__() if start is not None: - self.attributes['start'] = _date_with_utc_time(start) + self.attributes['start'] = _to_utc_date_string(start) if end is not None: - self.attributes['end'] = _date_with_utc_time(end) + self.attributes['end'] = _to_utc_date_string(end) class NotDefined(BaseElement): @@ -85,9 +98,9 @@ def __init__(self, start, end=None): super(Expand, self).__init__() if start is not None: - self.attributes['start'] = _date_with_utc_time(start) + self.attributes['start'] = _to_utc_date_string(start) if end is not None: - self.attributes['end'] = _date_with_utc_time(end) + self.attributes['end'] = _to_utc_date_string(end) class Comp(NamedBaseElement): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/caldav/lib/error.py new/caldav-0.6.2/caldav/lib/error.py --- old/caldav-0.6.1/caldav/lib/error.py 2019-03-10 18:32:43.000000000 +0100 +++ new/caldav-0.6.2/caldav/lib/error.py 2019-09-10 18:18:00.000000000 +0200 @@ -1,6 +1,8 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- +from collections import defaultdict + class AuthorizationError(Exception): """ @@ -16,40 +18,46 @@ (self.url, self.reason) -class PropsetError(Exception): +class DAVError(Exception): pass -class PropfindError(Exception): +class PropsetError(DAVError): + pass + +class ProppatchError(DAVError): pass -class ReportError(Exception): +class PropfindError(DAVError): pass -class MkcolError(Exception): +class ReportError(DAVError): pass -class MkcalendarError(Exception): +class MkcolError(DAVError): pass -class PutError(Exception): +class MkcalendarError(DAVError): pass -class DeleteError(Exception): +class PutError(DAVError): pass -class NotFoundError(Exception): +class DeleteError(DAVError): pass -exception_by_method = {} +class NotFoundError(DAVError): + pass + +exception_by_method = defaultdict(lambda: DAVError) for method in ('delete', 'put', 'mkcalendar', 'mkcol', 'report', 'propset', - 'propfind'): + 'propfind', 'proppatch'): exception_by_method[method] = \ locals()[method[0].upper() + method[1:] + 'Error'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/caldav/objects.py new/caldav-0.6.2/caldav/objects.py --- old/caldav-0.6.1/caldav/objects.py 2019-04-09 20:18:55.000000000 +0200 +++ new/caldav-0.6.2/caldav/objects.py 2019-09-10 18:18:00.000000000 +0200 @@ -9,15 +9,21 @@ import vobject import uuid import re -import datetime -import tzlocal +from datetime import datetime, date from lxml import etree try: + # noinspection PyCompatibility from urllib.parse import unquote except ImportError: from urllib import unquote +try: + from typing import Union, Optional + TimeStamp = Optional[Union[date,datetime]] +except: + pass + from caldav.lib import error, vcal from caldav.lib.url import URL from caldav.elements import dav, cdav @@ -28,16 +34,6 @@ """Utility for formatting a response xml tree to an error string""" return "%s %s\n\n%s" % (r.status, r.reason, r.raw) -def _fix_tz(dt): - """ - if the dt object is a date, do nothing. if the dt object is a - datetime and it has no tzinfo, assume it's localtime and set the - tzinfo explicitly. - """ - if hasattr(dt, 'tzname') and dt.tzname() is None: - import pytz - return dt.replace(tzinfo=pytz.utc) - return dt.replace(tzinfo=tzlocal.get_localzone()) class DAVObject(object): @@ -114,7 +110,7 @@ return c - def _query_properties(self, props=[], depth=0): + def _query_properties(self, props=None, depth=0): """ This is an internal method for doing a propfind query. It's a result of code-refactoring work, attempting to consolidate @@ -122,7 +118,7 @@ """ root = None # build the propfind request - if len(props) > 0: + if props is not None and len(props) > 0: prop = dav.Prop() + props root = dav.Propfind() + prop @@ -178,11 +174,15 @@ # All items should be in a <D:response> element for r in response.tree.findall('.//' + dav.Response.tag): status = r.find('.//' + dav.Status.tag) - if (' 200 ' not in status.text and - ' 207 ' not in status.text and - ' 404 ' not in status.text): - raise error.ReportError(errmsg(response)) - # TODO: may be wrong error class + ## TODO: status should never be None, this needs more research. + ## added here as it solves real-world issues, ref + ## https://github.com/python-caldav/caldav/pull/56 + if status is not None: + if (' 200 ' not in status.text and + ' 207 ' not in status.text and + ' 404 ' not in status.text): + raise error.ReportError(errmsg(response)) + # TODO: may be wrong error class href = unquote(r.find('.//' + dav.Href.tag).text) properties[href] = {} for p in props: @@ -204,7 +204,7 @@ return properties - def get_properties(self, props=[], depth=0): + def get_properties(self, props=None, depth=0): """ Get properties (PROPFIND) for this object. Works only for properties, that don't have complex types. @@ -234,7 +234,7 @@ return rc - def set_properties(self, props=[]): + def set_properties(self, props=None): """ Set properties (PROPPATCH) for this object. @@ -243,6 +243,7 @@ Returns: * self """ + props = [] if props is None else props prop = dav.Prop() + props set = dav.Set() + prop root = dav.PropertyUpdate() + set @@ -252,7 +253,7 @@ statuses = r.tree.findall(".//" + dav.Status.tag) for s in statuses: if ' 200 ' not in s.text: - raise error.PropsetError(errmsg(r)) + raise error.PropsetError(s.text) return self @@ -402,11 +403,15 @@ self._calendar_home_set = url return sanitized_url = URL.objectify(url) - if (sanitized_url.hostname and - sanitized_url.hostname != self.client.url.hostname): - # icloud (and others?) having a load balanced system, - # where each principal resides on one named host - self.client.url = sanitized_url + ## TODO: sanitized_url should never be None, this needs more + ## research. added here as it solves real-world issues, ref + ## https://github.com/python-caldav/caldav/pull/56 + if sanitized_url is not None: + if (sanitized_url.hostname and + sanitized_url.hostname != self.client.url.hostname): + # icloud (and others?) having a load balanced system, + # where each principal resides on one named host + self.client.url = sanitized_url self._calendar_home_set = CalendarSet( self.client, self.client.url.join(sanitized_url)) @@ -540,6 +545,7 @@ return self def date_search(self, start, end=None, compfilter="VEVENT", expand="maybe"): + # type (TimeStamp, TimeStamp, str, str) -> CalendarObjectResource """ Search events by date in the calendar. Recurring events are expanded if they are occuring during the specified time frame @@ -562,10 +568,6 @@ # build the request - # fix missing tzinfo in the start and end datetimes - start = _fix_tz(start) - end = _fix_tz(end) - ## for backward compatibility - expand should be false ## in an open-ended date search, otherwise true if expand == 'maybe': @@ -613,9 +615,6 @@ * [FreeBusy(), ...] """ - # fix missing tzinfo in the start and end datetimes - start = _fix_tz(start) - end = _fix_tz(end) root = cdav.FreeBusyQuery() + [cdav.TimeRange(start, end)] response = self._query(root, 1, 'report') @@ -717,11 +716,11 @@ 'isnt_overdue': not (hasattr(vtodo, 'due') and vtodo.due.value.strftime('%F%H%M%S') < - datetime.datetime.now().strftime('%F%H%M%S')), + datetime.now().strftime('%F%H%M%S')), 'hasnt_started': (hasattr(vtodo, 'dtstart') and vtodo.dtstart.value.strftime('%F%H%M%S') > - datetime.datetime.now().strftime('%F%H%M%S')) + datetime.now().strftime('%F%H%M%S')) } for sort_key in sort_keys: val = getattr(vtodo, sort_key, None) @@ -1041,10 +1040,10 @@ Parameters: * completion_timestamp - datetime object. Defaults to - datetime.datetime.now(). + datetime.now(). """ if not completion_timestamp: - completion_timestamp = datetime.datetime.now() + completion_timestamp = datetime.now() if not hasattr(self.vobject_instance.vtodo, 'status'): self.vobject_instance.vtodo.add('status') self.vobject_instance.vtodo.status.value = 'COMPLETED' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/caldav.egg-info/PKG-INFO new/caldav-0.6.2/caldav.egg-info/PKG-INFO --- old/caldav-0.6.1/caldav.egg-info/PKG-INFO 2019-04-09 20:40:43.000000000 +0200 +++ new/caldav-0.6.2/caldav.egg-info/PKG-INFO 2019-11-22 21:45:19.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: caldav -Version: 0.6.1 +Version: 0.6.2 Summary: CalDAV (RFC4791) client library Home-page: http://bitbucket.org/cyrilrbt/caldav Author: Cyril Robert diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/caldav.egg-info/SOURCES.txt new/caldav-0.6.2/caldav.egg-info/SOURCES.txt --- old/caldav-0.6.1/caldav.egg-info/SOURCES.txt 2019-04-09 20:40:43.000000000 +0200 +++ new/caldav-0.6.2/caldav.egg-info/SOURCES.txt 2019-11-22 21:45:19.000000000 +0100 @@ -26,11 +26,9 @@ caldav/lib/url.py caldav/lib/vcal.py tests/__init__.py -tests/__init__.pyc tests/_test_absolute.py tests/conf.py -tests/conf.pyc +tests/conf_private.py.EXAMPLE tests/proxy.py -tests/proxy.pyc tests/test_caldav.py -tests/test_caldav.pyc \ No newline at end of file +tests/test_cdav.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/caldav.egg-info/requires.txt new/caldav-0.6.2/caldav.egg-info/requires.txt --- old/caldav-0.6.1/caldav.egg-info/requires.txt 2019-04-09 20:40:43.000000000 +0200 +++ new/caldav-0.6.2/caldav.egg-info/requires.txt 2019-11-22 21:45:19.000000000 +0100 @@ -2,5 +2,3 @@ lxml requests six -tzlocal -pytz diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/setup.py new/caldav-0.6.2/setup.py --- old/caldav-0.6.1/setup.py 2019-04-09 20:40:17.000000000 +0200 +++ new/caldav-0.6.2/setup.py 2019-09-10 18:18:00.000000000 +0200 @@ -1,10 +1,18 @@ -#!/usr/bin/python2 +#!/usr/bin/python # -*- encoding: utf-8 -*- from setuptools import setup, find_packages -version = '0.6.1' +version = '0.6.2' if __name__ == '__main__': + ## For python 2.7 and 3.5 we depend on pytz and tzlocal. For 3.6 and up, batteries are included. + try: + import datetime + from datetime import timezone + datetime.datetime.now().astimezone() + extra_packages = [] + except: + extra_packages = ['pytz', 'tzlocal'] setup( name='caldav', version=version, @@ -27,6 +35,6 @@ packages=find_packages(exclude=['tests']), include_package_data=True, zip_safe=False, - install_requires=['vobject', 'lxml', 'requests', 'six', 'tzlocal', 'pytz'], - tests_requires=['nose', 'coverage'] + install_requires=['vobject', 'lxml', 'requests', 'six'] + extra_packages, + tests_require=['nose', 'coverage', 'tzlocal', 'pytz', 'xandikos'] ) Binary files old/caldav-0.6.1/tests/__init__.pyc and new/caldav-0.6.2/tests/__init__.pyc differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/tests/conf.py new/caldav-0.6.2/tests/conf.py --- old/caldav-0.6.1/tests/conf.py 2019-04-09 20:18:55.000000000 +0200 +++ new/caldav-0.6.2/tests/conf.py 2019-09-11 07:23:21.000000000 +0200 @@ -1,23 +1,54 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -############################ -# Private test server config -############################ +## YOU SHOULD MOST LIKELY NOT EDIT THIS FILE! +## Make a conf_private.py for personal configuration. +## Check conf_private.py.EXAMPLE + +#################################### +# Import personal test server config +#################################### +try: + from .conf_private import only_private ## legacy compatibility + test_public_test_servers = only_private +except ImportError: + try: + from .conf_private import public_test_servers + test_public_test_servers = only_private + except ImportError: + test_public_test_servers = False + try: from .conf_private import caldav_servers except ImportError: caldav_servers = [] try: - from .conf_private import only_private + from .conf_private import test_private_test_servers + if not test_private_test_servers: + caldav_servers = [] except ImportError: - only_private = False + pass + + +try: + from .conf_private import test_xandikos, xandikos_host, xandikos_port +except ImportError: + try: + import xandikos + test_xandikos = True + except: + test_xandikos = False + xandikos_host = 'localhost' + xandikos_port = 8993 ## random port above 8000 + ##################### # Public test servers ##################### -if not only_private: +## As of 2019-09, all of those are down. Will try to fix Real Soon. +if False: +#if test_public_test_servers: ## TODO: this one is set up on emphemeral storage on OpenShift and ## then configured manually through the webui installer, it will Binary files old/caldav-0.6.1/tests/conf.pyc and new/caldav-0.6.2/tests/conf.pyc differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/tests/conf_private.py.EXAMPLE new/caldav-0.6.2/tests/conf_private.py.EXAMPLE --- old/caldav-0.6.1/tests/conf_private.py.EXAMPLE 1970-01-01 01:00:00.000000000 +0100 +++ new/caldav-0.6.2/tests/conf_private.py.EXAMPLE 2019-09-10 18:18:00.000000000 +0200 @@ -0,0 +1,57 @@ +## PRIVATE CALDAV SERVER(S) TO RUN TESTS TOWARDS +## Make a list of your own servers/accounts that you'd like to run the +## test towards. Running the test suite towards a personal account +## should generally be safe, it should not mess up with content there +## and it should clean up after itself, but don't sue me if anything +## goes wrong ... + +caldav_servers = [ + { + ## This is all that is really needed - url, username and + ## password. The username and password may also be passed in + ## the URL itself (like + ## https://sam_i_am:[email protected]/) + 'url': 'https://some.server.example.com', + 'username': 'testuser', + 'password': 'hunter2', + + ## There are some boolean options that may be passed i.e. to + ## skip tests (many CalDAV server features are marked as + ## optional in the RFC, for one thing), to skip verifying SSL + ## certificate, etc. Leave the list blank on first attempt, then + ## add things as needed. + #'nocalendarnotfound': True, + #'nodefaultcalendar: True, + #'noproxy': True, + #'nojournal': True, + #'nofreebusy': True. + #'notodo': True, + #'nopropfind': True, + #'norecurring': True, + #'ssl_cert_verify': False + }] + +## MASTER SWITCHES FOR TEST SERVER SETUP +## With those configuration switches, pre-configured test servers in conf.py +## can be turned on or off + +## test_public_test_servers - Use the list of common public test +## servers from conf.py. This has proven to be unreliable and +## fragile, hence the default has now been flipped to False. It's +## very important to run through all the different server +## implementations and try to figure out of all breakages before any +## major release - and it ought to be done before any minor release as well. +test_public_test_servers = False + +## test_private_test_servers - test using the list configured above in this file. +test_private_test_servers = True + +## test_xandikos - since the xandikos caldav server implementation is +## written in python and can be instantiated quite easily, this will +## be the default caldav implementation to test towards ... but, unfortunately +## it works only with python 3.4 and higher +test_xandikos = True + +## DEPRECATED - only_private is superceded by test_public_servers, +## left here for backward-compatibility. +#only_private=False Binary files old/caldav-0.6.1/tests/proxy.pyc and new/caldav-0.6.2/tests/proxy.pyc differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/tests/test_caldav.py new/caldav-0.6.2/tests/test_caldav.py --- old/caldav-0.6.1/tests/test_caldav.py 2019-04-09 20:18:55.000000000 +0200 +++ new/caldav-0.6.2/tests/test_caldav.py 2019-09-10 18:18:00.000000000 +0200 @@ -6,13 +6,14 @@ import time import vobject import uuid +import tempfile from datetime import datetime from six import PY3 from nose.tools import assert_equal, assert_not_equal, assert_raises from nose.plugins.skip import SkipTest from requests.packages import urllib3 -from .conf import caldav_servers, proxy, proxy_noport +from .conf import caldav_servers, proxy, proxy_noport, test_xandikos, xandikos_port, xandikos_host from .proxy import ProxyHandler, NonThreadingHTTPServer from caldav.davclient import DAVClient @@ -24,6 +25,10 @@ from caldav.elements import dav, cdav from caldav.lib.python_utilities import to_local, to_str +if test_xandikos: + from xandikos.web import XandikosBackend, XandikosApp + from wsgiref.simple_server import make_server + if PY3: from urllib.parse import urlparse else: @@ -156,7 +161,6 @@ END:VCALENDAR """ - class RepeatedFunctionalTestsBaseClass(object): """This is a class with functional tests (tests that goes through basic functionality and actively communicates with third parties) @@ -856,6 +860,38 @@ _classname, (RepeatedFunctionalTestsBaseClass,), {'server_params': _caldav_server}) +class TestLocalXandikos(RepeatedFunctionalTestsBaseClass): + """ + Sets up a local Xandikos server and Runs the functional tests towards it + """ + def setup(self): + if not test_xandikos: + raise SkipTest("Skipping Xadikos test due to configuration") + self.serverdir = tempfile.TemporaryDirectory() + self.serverdir.__enter__() + ## TODO - we should do something with the access logs from Xandikos + self.backend = XandikosBackend(path=self.serverdir.name) + self.backend.create_principal('/sometestuser/', create_defaults=True) + self.xandikos_server = make_server(xandikos_host, xandikos_port, XandikosApp(self.backend, '/sometestuser/')) + self.xandikos_thread = threading.Thread(target=self.xandikos_server.serve_forever) + self.xandikos_thread.start() + self.server_params = {'url': 'http://%s:%i/sometestuser/' % (xandikos_host, xandikos_port), 'username': 'user1', 'password': 'password1'} + ## TODO: this should go away eventually. Ref https://github.com/jelmer/xandikos/issues/102 support for expanded search for recurring events has been fixed in the master branch of xandikos. + self.server_params['norecurring'] = True + RepeatedFunctionalTestsBaseClass.setup(self) + + def teardown(self): + if not test_xandikos: + return + self.xandikos_server.shutdown() + self.xandikos_server.socket.close() + i=0 + while (self.xandikos_thread.is_alive()): + time.sleep(0.05) + i+=1 + assert(i<100) + self.serverdir.__exit__(None, None, None) + RepeatedFunctionalTestsBaseClass.teardown(self) class TestCalDAV: """ @@ -901,6 +937,28 @@ 'http://me:[email protected]:80/someoneelse/calendars/main_calendar') assert_equal(calendar1.url, calendar2.url) + def testFailedQuery(self): + """ + ref https://github.com/python-caldav/caldav/issues/54 + """ + cal_url = "http://me:[email protected]:80/" + client = DAVClient(url=cal_url) + calhome = CalendarSet(client, cal_url + "me/") + + ## syntesize a failed response + class FailedResp: + pass + failedresp = FailedResp() + failedresp.status = 400 + failedresp.reason = "you are wrong" + failedresp.raw = "your request does not adhere to standards" + + ## synthesize a new http method + calhome.client.unknown_method = lambda url, body, depth: failedresp + + ## call it. + assert_raises(error.DAVError, calhome._query, query_method='unknown_method') + def testDefaultClient(self): """When no client is given to a DAVObject, but the parent is given, parent.client will be used""" Binary files old/caldav-0.6.1/tests/test_caldav.pyc and new/caldav-0.6.2/tests/test_caldav.pyc differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/caldav-0.6.1/tests/test_cdav.py new/caldav-0.6.2/tests/test_cdav.py --- old/caldav-0.6.1/tests/test_cdav.py 1970-01-01 01:00:00.000000000 +0100 +++ new/caldav-0.6.2/tests/test_cdav.py 2019-09-10 18:18:00.000000000 +0200 @@ -0,0 +1,48 @@ +import datetime +import pytz +import tzlocal + +from caldav.elements.cdav import _to_utc_date_string + +SOMEWHERE_REMOTE = pytz.timezone('Brazil/DeNoronha') # UTC-2 and no DST + + +def test_to_utc_date_string_date(): + input = datetime.date(2019, 5, 14) + res = _to_utc_date_string(input) + assert res == '20190514T000000Z' + + +def test_to_utc_date_string_utc(): + input = datetime.datetime(2019, 5, 14, 21, 10, 23, 23, tzinfo=pytz.utc) + try: + res = _to_utc_date_string(input.astimezone()) + except: + ## old python does not support astimezone() without a parameter given + res = _to_utc_date_string(input.astimezone(tzlocal.get_localzone())) + assert res == '20190514T211023Z' + + +def test_to_utc_date_string_dt_with_pytz_tzinfo(): + input = datetime.datetime(2019, 5, 14, 21, 10, 23, 23) + res = _to_utc_date_string(SOMEWHERE_REMOTE.localize(input)) + assert res == '20190514T231023Z' + + +def test_to_utc_date_string_dt_with_local_tz(): + input = datetime.datetime(2019, 5, 14, 21, 10, 23, 23) + try: + res = _to_utc_date_string(input.astimezone()) + except: + res = _to_utc_date_string(tzlocal.get_localzone().localize(input)) + exp_dt = tzlocal.get_localzone().localize(input).astimezone(pytz.utc) + exp = exp_dt.strftime("%Y%m%dT%H%M%SZ") + assert res == exp + + +def test_to_utc_date_string_naive_dt(): + input = datetime.datetime(2019, 5, 14, 21, 10, 23, 23) + res = _to_utc_date_string(input) + exp_dt = tzlocal.get_localzone().localize(input).astimezone(pytz.utc) + exp = exp_dt.strftime("%Y%m%dT%H%M%SZ") + assert res == exp
