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


Reply via email to