[Python-apps-team] Bug#858814: unblock: vdirsyncer/0.14.1-1

Filip Pytloun filip at pytloun.cz
Mon Mar 27 08:07:18 UTC 2017


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock

Please unblock package vdirsyncer

Hello,

Version 0.14.1 is bugfixing version which fixes mainly documentation and
2 bugs in code. For list of changes please refer to comparison of 0.14.0
and 0.14.1 git tags:

https://github.com/pimutils/vdirsyncer/compare/0.14.0...0.14.1

Debdiff is attached.

Thank you

unblock vdirsyncer/0.14.1-1

-- System Information:
Debian Release: 9.0
  APT prefers testing
  APT policy: (400, 'testing'), (100, 'unstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=cs_CZ.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
-------------- next part --------------
diff -Nru vdirsyncer-0.14.0/CHANGELOG.rst vdirsyncer-0.14.1/CHANGELOG.rst
--- vdirsyncer-0.14.0/CHANGELOG.rst	2016-10-26 16:35:37.000000000 +0200
+++ vdirsyncer-0.14.1/CHANGELOG.rst	2017-01-05 17:48:30.000000000 +0100
@@ -9,6 +9,15 @@
 may want to subscribe to `GitHub's tag feed
 <https://github.com/pimutils/vdirsyncer/tags.atom>`_.
 
+Version 0.14.1
+==============
+
+*released on 05 January 2017*
+
+- ``vdirsyncer repair`` no longer changes "unsafe" UIDs by default, an extra
+  option has to be specified. See :gh:`527`.
+- A lot of important documentation updates.
+
 Version 0.14.0
 ==============
 
diff -Nru vdirsyncer-0.14.0/debian/changelog vdirsyncer-0.14.1/debian/changelog
--- vdirsyncer-0.14.0/debian/changelog	2017-01-05 10:31:08.000000000 +0100
+++ vdirsyncer-0.14.1/debian/changelog	2017-03-27 09:41:21.000000000 +0200
@@ -1,3 +1,11 @@
+vdirsyncer (0.14.1-1) unstable; urgency=medium
+
+  * New upstream release
+  * d/patches: drop 0005-Direct-users-to-Debian-BTS.patch as upstream docs
+    already covers Debian packages
+
+ -- Filip Pytloun <filip at pytloun.cz>  Mon, 27 Mar 2017 09:41:21 +0200
+
 vdirsyncer (0.14.0-3) unstable; urgency=medium
 
   * d/patches: Direct users to Debian BTS to avoid bothering upstream with
diff -Nru vdirsyncer-0.14.0/debian/files vdirsyncer-0.14.1/debian/files
--- vdirsyncer-0.14.0/debian/files	1970-01-01 01:00:00.000000000 +0100
+++ vdirsyncer-0.14.1/debian/files	2017-03-27 09:41:21.000000000 +0200
@@ -0,0 +1 @@
+vdirsyncer_0.14.1-1_source.buildinfo utils optional
diff -Nru vdirsyncer-0.14.0/debian/patches/0001-Don-t-use-subtest.patch vdirsyncer-0.14.1/debian/patches/0001-Don-t-use-subtest.patch
--- vdirsyncer-0.14.0/debian/patches/0001-Don-t-use-subtest.patch	2016-10-31 14:52:10.000000000 +0100
+++ vdirsyncer-0.14.1/debian/patches/0001-Don-t-use-subtest.patch	2017-03-27 09:40:40.000000000 +0200
@@ -1,4 +1,4 @@
-From 0c7227f42c25525f3029da0086b94597b318361c Mon Sep 17 00:00:00 2001
+From e952d015f28441a703edbee4b26051145047ef0f Mon Sep 17 00:00:00 2001
 From: Filip Pytloun <filip at pytloun.cz>
 Date: Mon, 31 Oct 2016 14:40:47 +0100
 Subject: [PATCH 1/4] Don't use subtest
@@ -94,5 +94,5 @@
      runner.write_with_general(dedent('''
      [pair foobar]
 -- 
-2.1.4
+2.11.0
 
diff -Nru vdirsyncer-0.14.0/debian/patches/0002-Include-license-from-copyright-file.patch vdirsyncer-0.14.1/debian/patches/0002-Include-license-from-copyright-file.patch
--- vdirsyncer-0.14.0/debian/patches/0002-Include-license-from-copyright-file.patch	2016-10-31 14:52:10.000000000 +0100
+++ vdirsyncer-0.14.1/debian/patches/0002-Include-license-from-copyright-file.patch	2017-03-27 09:40:40.000000000 +0200
@@ -1,4 +1,4 @@
-From 76db0343cbdd6b48dabcaecee255b28d30c838a6 Mon Sep 17 00:00:00 2001
+From 82598e72b021eab12ba2e7fb0918788bf96052f7 Mon Sep 17 00:00:00 2001
 From: Filip Pytloun <filip at pytloun.cz>
 Date: Thu, 11 Aug 2016 14:35:29 +0200
 Subject: [PATCH 2/4] Include license from copyright file
@@ -18,5 +18,5 @@
 -.. include:: ../LICENSE
 +.. literalinclude:: /usr/share/doc/vdirsyncer-doc/copyright
 -- 
-2.1.4
+2.11.0
 
diff -Nru vdirsyncer-0.14.0/debian/patches/0003-Skip-SSL-tests.patch vdirsyncer-0.14.1/debian/patches/0003-Skip-SSL-tests.patch
--- vdirsyncer-0.14.0/debian/patches/0003-Skip-SSL-tests.patch	2016-10-31 14:52:10.000000000 +0100
+++ vdirsyncer-0.14.1/debian/patches/0003-Skip-SSL-tests.patch	2017-03-27 09:40:40.000000000 +0200
@@ -1,4 +1,4 @@
-From c758b0d86679aecfcd58750fe22c49696023cab2 Mon Sep 17 00:00:00 2001
+From a341ff03f0dcecead442e174b5d1a89775e68097 Mon Sep 17 00:00:00 2001
 From: Filip Pytloun <filip at pytloun.cz>
 Date: Mon, 31 Oct 2016 14:42:00 +0100
 Subject: [PATCH 3/4] Skip SSL tests
@@ -28,5 +28,5 @@
                      reason='https://github.com/shazow/urllib3/issues/529')
  @pytest.mark.parametrize('fingerprint', [
 -- 
-2.1.4
+2.11.0
 
diff -Nru vdirsyncer-0.14.0/debian/patches/0004-Suppress-HealthCheck.too_slow-to-fix-build-on-slow-p.patch vdirsyncer-0.14.1/debian/patches/0004-Suppress-HealthCheck.too_slow-to-fix-build-on-slow-p.patch
--- vdirsyncer-0.14.0/debian/patches/0004-Suppress-HealthCheck.too_slow-to-fix-build-on-slow-p.patch	2016-11-05 09:25:35.000000000 +0100
+++ vdirsyncer-0.14.1/debian/patches/0004-Suppress-HealthCheck.too_slow-to-fix-build-on-slow-p.patch	2017-03-27 09:40:40.000000000 +0200
@@ -1,4 +1,4 @@
-From b8b8d0efa570faa7d04425d7b964cea25dd6c860 Mon Sep 17 00:00:00 2001
+From e576980183561df6c06ff0ad546d2be489288a68 Mon Sep 17 00:00:00 2001
 From: Filip Pytloun <filip at pytloun.cz>
 Date: Mon, 31 Oct 2016 14:51:50 +0100
 Subject: [PATCH 4/4] Suppress HealthCheck.too_slow to fix build on slow
@@ -34,7 +34,7 @@
                               monkeypatch):
  
 diff --git a/tests/cli/test_fetchparams.py b/tests/cli/test_fetchparams.py
-index 8c010ba..8a08873 100644
+index 8c010ba..b9af08e 100644
 --- a/tests/cli/test_fetchparams.py
 +++ b/tests/cli/test_fetchparams.py
 @@ -3,7 +3,7 @@
@@ -46,14 +46,14 @@
  
  import pytest
  
-@@ -90,6 +90,7 @@ def test_key_conflict(monkeypatch, mystrategy):
+@@ -89,6 +89,7 @@ def test_key_conflict(monkeypatch, mystrategy):
+     assert 'Can\'t set foo.fetch and foo.' in str(excinfo.value)
  
  
 + at settings(suppress_health_check=["HealthCheck.too_slow"])
  @given(s=st.text(), t=st.text(min_size=1))
  def test_fuzzing(s, t, mystrategy):
      config = expand_fetch_params({
-         '{}.fetch'.format(s): ['mystrategy', t]
 diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py
 index 0ec4b94..d23b85b 100644
 --- a/tests/storage/__init__.py
@@ -97,7 +97,7 @@
           conflict_resolution='a wins')
  def test_fuzzing(a, b, status, keys, conflict_resolution):
 diff --git a/tests/test_repair.py b/tests/test_repair.py
-index 6d8f837..a692fb7 100644
+index 6a0d97a..10725b6 100644
 --- a/tests/test_repair.py
 +++ b/tests/test_repair.py
 @@ -11,7 +11,7 @@ from . import uid_strategy
@@ -119,5 +119,5 @@
      s = MemoryStorage()
      item = Item(u'BEGIN:VCARD\nUID:{}\nEND:VCARD'.format(uid))
 -- 
-2.1.4
+2.11.0
 
diff -Nru vdirsyncer-0.14.0/debian/patches/0005-Direct-users-to-Debian-BTS.patch vdirsyncer-0.14.1/debian/patches/0005-Direct-users-to-Debian-BTS.patch
--- vdirsyncer-0.14.0/debian/patches/0005-Direct-users-to-Debian-BTS.patch	2017-01-05 10:30:02.000000000 +0100
+++ vdirsyncer-0.14.1/debian/patches/0005-Direct-users-to-Debian-BTS.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,57 +0,0 @@
-From 1eb7764dfde4953a0a555ddd0c1c9c6f72961497 Mon Sep 17 00:00:00 2001
-From: Filip Pytloun <filip at pytloun.cz>
-Date: Thu, 5 Jan 2017 10:26:33 +0100
-Subject: [PATCH] Direct users to Debian BTS
-
----
- docs/contact.rst       | 4 ++++
- docs/contributing.rst  | 4 ++++
- vdirsyncer/__init__.py | 2 +-
- 3 files changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/docs/contact.rst b/docs/contact.rst
-index 30c38ec..492b48a 100644
---- a/docs/contact.rst
-+++ b/docs/contact.rst
-@@ -6,6 +6,10 @@ Support and Contact
-   your timezone. Use it for support and general (including off-topic)
-   discussion.
- 
-+* Use Debian `BTS <https://www.debian.org/Bugs/Reporting>`_ to report bugs
-+  against Debian stable versions. Do not use upstream bugtracker before
-+  testing latest upstream release!
-+
- * Open `a GitHub issue <https://github.com/pimutils/vdirsyncer/issues/>`_ for
-   concrete bug reports and feature requests.
- 
-diff --git a/docs/contributing.rst b/docs/contributing.rst
-index bec000b..91580a3 100644
---- a/docs/contributing.rst
-+++ b/docs/contributing.rst
-@@ -37,6 +37,10 @@ further information.
- Reporting bugs
- --------------
- 
-+* Use Debian `BTS <https://www.debian.org/Bugs/Reporting>`_ to report bugs
-+  against Debian stable versions. Do not use upstream bugtracker before
-+  testing latest upstream release!
-+
- * Make sure your problem isn't already listed in :doc:`problems`.
- 
- * Make sure you have the latest version by executing ``pip install --user
-diff --git a/vdirsyncer/__init__.py b/vdirsyncer/__init__.py
-index e658625..b94ec06 100644
---- a/vdirsyncer/__init__.py
-+++ b/vdirsyncer/__init__.py
-@@ -6,7 +6,7 @@ Vdirsyncer synchronizes calendars and contacts.
- from __future__ import print_function
- 
- PROJECT_HOME = 'https://github.com/pimutils/vdirsyncer'
--BUGTRACKER_HOME = PROJECT_HOME + '/issues'
-+BUGTRACKER_HOME = 'https://www.debian.org/Bugs/Reporting'
- DOCS_HOME = 'https://vdirsyncer.pimutils.org/en/stable'
- 
- try:
--- 
-2.1.4
-
diff -Nru vdirsyncer-0.14.0/debian/patches/series vdirsyncer-0.14.1/debian/patches/series
--- vdirsyncer-0.14.0/debian/patches/series	2017-01-05 10:27:13.000000000 +0100
+++ vdirsyncer-0.14.1/debian/patches/series	2017-03-27 09:41:11.000000000 +0200
@@ -2,4 +2,3 @@
 0002-Include-license-from-copyright-file.patch
 0003-Skip-SSL-tests.patch
 0004-Suppress-HealthCheck.too_slow-to-fix-build-on-slow-p.patch
-0005-Direct-users-to-Debian-BTS.patch
diff -Nru vdirsyncer-0.14.0/docs/conf.py vdirsyncer-0.14.1/docs/conf.py
--- vdirsyncer-0.14.0/docs/conf.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/docs/conf.py	2016-12-06 15:30:15.000000000 +0100
@@ -60,8 +60,8 @@
 ]
 
 
-def github_issue_role(name, rawtext, text, lineno, inliner, options={},
-                      content=()):
+def github_issue_role(name, rawtext, text, lineno, inliner,
+                      options={}, content=()):  # noqa: B006
     try:
         issue_num = int(text)
         if issue_num <= 0:
diff -Nru vdirsyncer-0.14.0/docs/contributing.rst vdirsyncer-0.14.1/docs/contributing.rst
--- vdirsyncer-0.14.0/docs/contributing.rst	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/docs/contributing.rst	2017-01-05 17:46:02.000000000 +0100
@@ -39,8 +39,10 @@
 
 * Make sure your problem isn't already listed in :doc:`problems`.
 
-* Make sure you have the latest version by executing ``pip install --user
-  --upgrade vdirsyncer``.
+* Make sure you have the absolutely latest version of vdirsyncer. For users of
+  some Linux distributions such as Debian or Fedora this may not be the version
+  that your distro offers. In those cases please file a bug against the distro
+  package, not against upstream vdirsyncer.
 
 * Use ``--verbosity=DEBUG`` when including output from vdirsyncer.
 
diff -Nru vdirsyncer-0.14.0/docs/installation.rst vdirsyncer-0.14.1/docs/installation.rst
--- vdirsyncer-0.14.0/docs/installation.rst	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/docs/installation.rst	2017-01-05 17:43:33.000000000 +0100
@@ -12,14 +12,21 @@
 
 - `ArchLinux (AUR) <https://aur.archlinux.org/packages/vdirsyncer>`_
 - `pkgsrc <http://pkgsrc.se/time/py-vdirsyncer>`_
-- `Fedora <https://apps.fedoraproject.org/packages/vdirsyncer>`_
 - `nixpkg <https://github.com/NixOS/nixpkgs/tree/master/pkgs/tools/misc/vdirsyncer>`_
 - `GNU Guix <https://www.gnu.org/software/guix/package-list.html#vdirsyncer>`_
 - `homebrew <http://braumeister.org/formula/vdirsyncer>`_
 - `Gentoo <https://packages.gentoo.org/packages/dev-python/vdirsyncer>`_
-- `Debian Sid <https://packages.debian.org/search?keywords=vdirsyncer&searchon=names&exact=1&suite=all&section=all>`_.
-- Debian stable and Ubuntu don't have packages, but make a manual installation
-  especially hard. See :ref:`debian-urllib3`.
+
+Some distros have multiple release channels. The following **may not contain
+the latest version:**
+
+- `Fedora <https://apps.fedoraproject.org/packages/vdirsyncer>`_
+- `Debian <https://packages.debian.org/sid/vdirsyncer>`_ (likewise for Ubuntu)
+
+Note that we only support the latest version of vdirsyncer, but you may still
+find older versions in some distro's repositories. You should have recieved
+information on how to file bugs against those packages. Please do not file bugs
+against vdirsyncer.
 
 If there is no package for your distribution, you'll need to :ref:`install
 vdirsyncer manually <manual-installation>`. There is an easy command to
@@ -65,8 +72,8 @@
 decide to uninstall it. In other words, using pip that way would pollute your
 home directory.
 
-The clean but hard way
-~~~~~~~~~~~~~~~~~~~~~~
+The clean, hard way
+~~~~~~~~~~~~~~~~~~~
 
 There is a way to install Python software without scattering stuff across
 your filesystem: virtualenv_. There are a lot of resources on how to use it,
@@ -85,8 +92,8 @@
   distro-specific issues.
 - You can delete ``~/vdirsyncer_env/`` to uninstall vdirsyncer entirely.
 
-The new, perfect way
-~~~~~~~~~~~~~~~~~~~~
+The clean, easy way
+~~~~~~~~~~~~~~~~~~~
 
 pipsi_ is a new package manager for Python-based software that automatically
 sets up a virtualenv for each program you install. Assuming you have it
diff -Nru vdirsyncer-0.14.0/docs/problems.rst vdirsyncer-0.14.1/docs/problems.rst
--- vdirsyncer-0.14.0/docs/problems.rst	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/docs/problems.rst	2016-11-19 03:35:01.000000000 +0100
@@ -6,21 +6,17 @@
 
 .. _debian-urllib3:
 
-Requests-related ImportErrors on Debian-based distributions
------------------------------------------------------------
+Requests-related ImportErrors
+-----------------------------
 
     ImportError: No module named packages.urllib3.poolmanager
 
     ImportError: cannot import name iter_field_objects
 
-Debian has had its problems in the past with the Python requests package, see
-:gh:`82` and :gh:`140`. You have several options for solving this problem:
-
-- Set the ``auth`` parameter of :storage:`caldav`, :storage:`carddav`, and/or
-  :storage:`http` to ``basic`` or ``digest`` (not ``guess``).
-
-- Upgrade your installation of the Debian requests package to at least version
-  ``2.4.3-1``.
-
-- If this doesn't help, install vdirsyncer in a virtualenv, see
-  :ref:`manual-installation`.
+Debian and nowadays even other distros make modifications to the ``requests``
+package that don't play well with packages assuming a normal ``requests``. This
+is due to stubbornness on both sides.
+
+See :gh:`82` and :gh:`140` for past discussions. You have one option to work
+around this, that is, to install vdirsyncer in a virtualenv, see
+:ref:`manual-installation`.
diff -Nru vdirsyncer-0.14.0/docs/ssl-tutorial.rst vdirsyncer-0.14.1/docs/ssl-tutorial.rst
--- vdirsyncer-0.14.0/docs/ssl-tutorial.rst	2016-10-23 01:30:10.000000000 +0200
+++ vdirsyncer-0.14.1/docs/ssl-tutorial.rst	2017-01-02 17:03:50.000000000 +0100
@@ -24,6 +24,17 @@
 
     echo -n | openssl s_client -connect unterwaditzer.net:443 | openssl x509 -noout -fingerprint
 
+Note that ``verify_fingerprint`` doesn't suffice for vdirsyncer to work with
+self-signed certifcates (or certificates that are not in your trust store). You
+most likely need to set ``verify = false`` as well. This disables verification
+of the SSL certificate's expiration time and the existence of it in your trust
+store, all that's verified now is the fingerprint.
+
+However, please consider using `Let's Encrypt <https://letsencrypt.org/>`_ such
+that you can forget about all of that. It is easier to deploy a free
+certificate from them than configuring all of your clients to accept the
+self-signed certificate.
+
 .. _ssl-cas:
 
 Custom root CAs
@@ -40,10 +51,10 @@
 trusted CAs
 <http://www.python-requests.org/en/latest/user/advanced/#ca-certificates>`_.
 
-However, the actual behavior depends on how you have installed it. Some Linux
-distributions, such as Debian, patch their ``python-requests`` package to use
-the system certificate CAs. Normally these two stores are similar enough for
-you to not care.
+However, the actual behavior depends on how you have installed it. Many Linux
+distributions patch their ``python-requests`` package to use the system
+certificate CAs. Normally these two stores are similar enough for you to not
+care.
 
 But there are cases where certificate validation fails even though you can
 access the server fine through e.g. your browser. This usually indicates that
diff -Nru vdirsyncer-0.14.0/docs/supported.rst vdirsyncer-0.14.1/docs/supported.rst
--- vdirsyncer-0.14.0/docs/supported.rst	2016-10-23 01:30:10.000000000 +0200
+++ vdirsyncer-0.14.1/docs/supported.rst	2017-01-03 15:25:54.000000000 +0100
@@ -100,13 +100,13 @@
 
     [storage cal]
     type = "caldav"
-    url = "https://example.com/owncloud/remote.php/caldav/"
+    url = "https://example.com/remote.php/dav/"
     username = ...
     password = ...
 
     [storage card]
     type = "carddav"
-    url = "https://example.com/owncloud/remote.php/carddav/"
+    url = "https://example.com/remote.php/dav/"
     username = ...
     password = ...
 
@@ -195,27 +195,27 @@
 DavMail (Exchange, Outlook)
 ---------------------------
 
-Using vdirsyncer with DavMail_ is possible, but you might get confronted with
-weird errors coming from old Exchange servers, malformed calendar entries with
-special characters and/or using an old DavMail version.
+DavMail_ is a proxy program that allows you to use Card- and CalDAV clients
+with Outlook. That allows you to use vdirsyncer with Outlook.
+
+In practice your success with DavMail may wildly vary. Depending on your
+Exchange server you might get confronted with weird errors of all sorts
+(including data-loss).
 
 **Make absolutely sure you use the latest DavMail**::
 
     [storage outlook]
     type = "caldav"
-    url = "http://localhost:1080/"
+    url = "http://localhost:1080/users/user@example.com/calendar/"
     username = "user at example.com"
     password = ...
 
 - Older versions of DavMail handle URLs case-insensitively. See :gh:`144`.
-- DavMail is handling old broken events very poorly. In such cases the
-  `Calendar Checking Tool for Outlook
+- DavMail is handling malformed data on the Exchange server very poorly. In
+  such cases the `Calendar Checking Tool for Outlook
   <https://www.microsoft.com/en-us/download/details.aspx?id=28786>`_ might
   help.
 
-If you encounter any problems, do report them to me, but it's probably not
-vdirsyncer's fault.
-
 .. _DavMail: http://davmail.sourceforge.net/
 
 Baikal
diff -Nru vdirsyncer-0.14.0/docs/when.rst vdirsyncer-0.14.1/docs/when.rst
--- vdirsyncer-0.14.0/docs/when.rst	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/docs/when.rst	2016-11-19 03:35:01.000000000 +0100
@@ -42,7 +42,7 @@
   
   This is a good idea if the user is directly interfacing with the file system
   and is able to resolve conflicts themselves.  Here it might lead to
-  errorneous behavior with e.g. ``khal``, since there are now two events with
+  erroneous behavior with e.g. ``khal``, since there are now two events with
   the same UID.
 
   This point doesn't apply to git: It has very good merging capabilities,
diff -Nru vdirsyncer-0.14.0/PKG-INFO vdirsyncer-0.14.1/PKG-INFO
--- vdirsyncer-0.14.0/PKG-INFO	2016-10-26 16:35:54.000000000 +0200
+++ vdirsyncer-0.14.1/PKG-INFO	2017-01-05 17:48:51.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: vdirsyncer
-Version: 0.14.0
+Version: 0.14.1
 Summary: Synchronize calendars and contacts
 Home-page: https://github.com/pimutils/vdirsyncer
 Author: Markus Unterwaditzer
diff -Nru vdirsyncer-0.14.0/scripts/make_travisconf.py vdirsyncer-0.14.1/scripts/make_travisconf.py
--- vdirsyncer-0.14.0/scripts/make_travisconf.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/scripts/make_travisconf.py	2016-12-19 21:21:40.000000000 +0100
@@ -10,6 +10,7 @@
 fi
     """.strip().format(x.strip())
 
+
 cfg = {}
 
 cfg['sudo'] = True
@@ -47,7 +48,7 @@
     if python == "3.5":
         dav_servers = ("radicale", "owncloud", "nextcloud", "baikal",
                        "davical")
-        rs_servers = ("mysteryshack",)
+        rs_servers = ()
     else:
         dav_servers = ("radicale",)
         rs_servers = ()
diff -Nru vdirsyncer-0.14.0/setup.py vdirsyncer-0.14.1/setup.py
--- vdirsyncer-0.14.0/setup.py	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/setup.py	2016-12-06 15:31:22.000000000 +0100
@@ -52,6 +52,7 @@
         for requirement in requirements:
             print(requirement.replace(">", "=").replace(" ", ""))
 
+
 setup(
     # General metadata
     name='vdirsyncer',
diff -Nru vdirsyncer-0.14.0/tests/test_repair.py vdirsyncer-0.14.1/tests/test_repair.py
--- vdirsyncer-0.14.0/tests/test_repair.py	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/tests/test_repair.py	2016-12-06 15:57:58.000000000 +0100
@@ -28,7 +28,7 @@
     uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()]
     assert uid1 == uid2
 
-    repair_storage(s)
+    repair_storage(s, repair_unsafe_uid=False)
 
     uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()]
     assert uid1 != uid2
@@ -44,7 +44,7 @@
     assert s.get(href)[0].uid == uid
     assert not href_safe(uid)
 
-    repair_storage(s)
+    repair_storage(s, repair_unsafe_uid=True)
 
     new_href = list(s.list())[0][0]
     assert href_safe(new_href)
diff -Nru vdirsyncer-0.14.0/tests/test_sync.py vdirsyncer-0.14.1/tests/test_sync.py
--- vdirsyncer-0.14.0/tests/test_sync.py	2016-10-23 01:23:07.000000000 +0200
+++ vdirsyncer-0.14.1/tests/test_sync.py	2016-12-21 20:26:13.000000000 +0100
@@ -211,7 +211,7 @@
     a.update = b.update = a.upload = b.upload = \
         lambda *a, **kw: pytest.fail('Method shouldn\'t have been called.')
 
-    for i in (1, 2):
+    for _ in (1, 2):
         sync(a, b, status)
         assert status == old_status
         assert items(a) == items(b) == {item.raw}
diff -Nru vdirsyncer-0.14.0/tests/utils/test_vobject.py vdirsyncer-0.14.1/tests/utils/test_vobject.py
--- vdirsyncer-0.14.0/tests/utils/test_vobject.py	2016-10-23 01:23:44.000000000 +0200
+++ vdirsyncer-0.14.1/tests/utils/test_vobject.py	2016-12-21 20:06:08.000000000 +0100
@@ -131,7 +131,7 @@
     bare = '\r\n'.join([VCARD_TEMPLATE.format(r=x, uid=x) for x in range(4)])
     with_wrapper = 'BEGIN:VADDRESSBOOK\r\n' + bare + '\nEND:VADDRESSBOOK\r\n'
 
-    for x in (bare, with_wrapper):
+    for _ in (bare, with_wrapper):
         split = list(vobject.split_collection(bare))
         assert len(split) == 4
         assert vobject.join_collection(split).splitlines() == \
diff -Nru vdirsyncer-0.14.0/.travis.yml vdirsyncer-0.14.1/.travis.yml
--- vdirsyncer-0.14.0/.travis.yml	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/.travis.yml	2016-12-19 22:11:54.000000000 +0100
@@ -43,18 +43,6 @@
         "python": "3.4"
       },
       {
-        "env": "BUILD=test REMOTESTORAGE_SERVER=mysteryshack REQUIREMENTS=devel BUILD_PRS=false",
-        "python": "3.5"
-      },
-      {
-        "env": "BUILD=test REMOTESTORAGE_SERVER=mysteryshack REQUIREMENTS=release BUILD_PRS=false",
-        "python": "3.5"
-      },
-      {
-        "env": "BUILD=test REMOTESTORAGE_SERVER=mysteryshack REQUIREMENTS=minimal BUILD_PRS=false",
-        "python": "3.5"
-      },
-      {
         "env": "BUILD=test DAV_SERVER=radicale REQUIREMENTS=devel BUILD_PRS=true",
         "python": "3.5"
       },
diff -Nru vdirsyncer-0.14.0/vdirsyncer/cli/__init__.py vdirsyncer-0.14.1/vdirsyncer/cli/__init__.py
--- vdirsyncer-0.14.0/vdirsyncer/cli/__init__.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/cli/__init__.py	2016-12-31 17:06:03.000000000 +0100
@@ -53,6 +53,7 @@
         from .config import load_config
         ctx.config = load_config(config)
 
+
 main = app
 
 
@@ -174,8 +175,8 @@
     '--list/--no-list', default=True,
     help=(
         'Whether to list all collections from both sides during discovery, '
-        'for debugging. This is quite slow. For faster discovery, disable '
-        'with --no-list.'
+        'for debugging. This is slow, but enabled by default for usability '
+        'reasons. '
     )
 )
 @max_workers_option(default=1)
@@ -206,16 +207,21 @@
 
 @app.command()
 @click.argument('collection')
+ at click.option('--repair-unsafe-uid/--no-repair-unsafe-uid', default=False,
+              help=('Some characters in item UIDs and URLs may cause problems '
+                    'with buggy software. Adding this option will reassign '
+                    'new UIDs to those items. This is disabled by default, '
+                    'which is equivalent to `--no-repair-unsafe-uid`.'))
 @pass_context
 @catch_errors
-def repair(ctx, collection):
+def repair(ctx, collection, repair_unsafe_uid):
     '''
     Repair a given collection.
 
     Runs a few checks on the collection and applies some fixes to individual
     items that may improve general stability, also with other CalDAV/CardDAV
     clients. In particular, if you encounter URL-encoding-related issues with
-    other clients, this command might help.
+    other clients, this command with --repair-unsafe-uid might help.
 
     Example: `vdirsyncer repair calendars_local/foo` repairs the `foo`
     collection of the `calendars_local` storage.
@@ -223,7 +229,8 @@
     from .tasks import repair_collection
 
     cli_logger.warning('This operation will take a very long time.')
-    cli_logger.warning('It\'s recommended to turn off other client\'s '
-                       'synchronization features.')
+    cli_logger.warning('It\'s recommended to make a backup and '
+                       'turn off other client\'s synchronization features.')
     click.confirm('Do you want to continue?', abort=True)
-    repair_collection(ctx.config, collection)
+    repair_collection(ctx.config, collection,
+                      repair_unsafe_uid=repair_unsafe_uid)
diff -Nru vdirsyncer-0.14.0/vdirsyncer/cli/tasks.py vdirsyncer-0.14.1/vdirsyncer/cli/tasks.py
--- vdirsyncer-0.14.0/vdirsyncer/cli/tasks.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/cli/tasks.py	2016-12-19 22:18:07.000000000 +0100
@@ -38,7 +38,7 @@
         wq.put(functools.partial(callback, collection=collection,
                                  general=config.general, **kwargs))
 
-    for i in range(new_workers):
+    for _ in range(new_workers):
         wq.spawn_worker()
 
 
@@ -93,7 +93,7 @@
                     .format(pair.name, json.dumps(collections)))
 
 
-def repair_collection(config, collection):
+def repair_collection(config, collection, repair_unsafe_uid):
     from ..repair import repair_storage
 
     storage_name, collection = collection, None
@@ -120,7 +120,7 @@
 
     cli_logger.info('Repairing {}/{}'.format(storage_name, collection))
     cli_logger.warning('Make sure no other program is talking to the server.')
-    repair_storage(storage)
+    repair_storage(storage, repair_unsafe_uid=repair_unsafe_uid)
 
 
 def metasync_collection(wq, collection, general):
diff -Nru vdirsyncer-0.14.0/vdirsyncer/__init__.py vdirsyncer-0.14.1/vdirsyncer/__init__.py
--- vdirsyncer-0.14.0/vdirsyncer/__init__.py	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/__init__.py	2016-12-06 15:30:54.000000000 +0100
@@ -25,22 +25,18 @@
         print('vdirsyncer requires Python 3.')
         sys.exit(1)
 
+
 _check_python_version()
 del _check_python_version
 
 
 def _detect_faulty_requests():  # pragma: no cover
-    import requests
-    if 'dist-packages' not in requests.__file__:
-        return
-
     text = (
-        '{e}\n\n'
-        'This most likely means you are running into a bug specific to '
-        'Debian-based distributions.\n\n'
-        'Consult {d}/problems.html#requests-related-importerrors-on-debian'
-        '-based-distributions on how to deal with this, or use a different '
-        'operating system.'
+        'Error during import: {e}\n\n'
+        'If you have installed vdirsyncer from a distro package, please file '
+        'a bug against that package, not vdirsyncer.\n\n'
+        'Consult {d}/problems.html#requests-related-importerrors'
+        '-based-distributions on how to work around this.'
     )
 
     try:
@@ -50,5 +46,6 @@
         print(text.format(e=str(e), d=DOCS_HOME), file=sys.stderr)
         sys.exit(1)
 
+
 _detect_faulty_requests()
 del _detect_faulty_requests
diff -Nru vdirsyncer-0.14.0/vdirsyncer/repair.py vdirsyncer-0.14.1/vdirsyncer/repair.py
--- vdirsyncer-0.14.0/vdirsyncer/repair.py	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/repair.py	2016-12-06 15:57:18.000000000 +0100
@@ -8,7 +8,7 @@
 logger = logging.getLogger(__name__)
 
 
-def repair_storage(storage):
+def repair_storage(storage, repair_unsafe_uid):
     seen_uids = set()
     all_hrefs = list(storage.list())
     for i, (href, _) in enumerate(all_hrefs):
@@ -30,8 +30,12 @@
             logger.warning('Duplicate UID, assigning random one.')
             new_item = item.with_uid(generate_href())
         elif not href_safe(item.uid) or not href_safe(basename(href)):
-            logger.warning('UID or href is unsafe, assigning random UID.')
-            new_item = item.with_uid(generate_href(item.uid))
+            if not repair_unsafe_uid:
+                logger.warning('UID or href may cause problems, add '
+                               '--repair-unsafe-hrefs to repair.')
+            else:
+                logger.warning('UID or href is unsafe, assigning random UID.')
+                new_item = item.with_uid(generate_href(item.uid))
 
         if not new_item.uid:
             logger.error('Item {!r} is malformed beyond repair. '
diff -Nru vdirsyncer-0.14.0/vdirsyncer/storage/dav.py vdirsyncer-0.14.1/vdirsyncer/storage/dav.py
--- vdirsyncer-0.14.0/vdirsyncer/storage/dav.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/storage/dav.py	2016-12-19 22:17:54.000000000 +0100
@@ -27,6 +27,7 @@
         yield x.upper()
         yield x.lower()
 
+
 _path_reserved_chars = frozenset(_generate_path_reserved_chars())
 del _generate_path_reserved_chars
 
@@ -84,6 +85,8 @@
 
 
 def _merge_xml(items):
+    if not items:
+        return []
     rv = items[0]
     for item in items[1:]:
         rv.extend(item.getiterator())
@@ -598,7 +601,7 @@
         root = _parse_xml(response.content)
 
         rv = self._parse_prop_responses(root)
-        for href, etag, prop in rv:
+        for href, etag, _prop in rv:
             yield href, etag
 
     def get_meta(self, key):
@@ -814,7 +817,7 @@
                                             headers=headers)
             root = _parse_xml(response.content)
             rv = self._parse_prop_responses(root)
-            for href, etag, prop in rv:
+            for href, etag, _prop in rv:
                 yield href, etag
 
 
diff -Nru vdirsyncer-0.14.0/vdirsyncer/storage/memory.py vdirsyncer-0.14.1/vdirsyncer/storage/memory.py
--- vdirsyncer-0.14.0/vdirsyncer/storage/memory.py	2016-10-23 01:14:05.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/storage/memory.py	2016-12-19 22:16:17.000000000 +0100
@@ -30,7 +30,7 @@
         return item.ident + self.fileext
 
     def list(self):
-        for href, (etag, item) in self.items.items():
+        for href, (etag, _item) in self.items.items():
             yield href, etag
 
     def get(self, href):
diff -Nru vdirsyncer-0.14.0/vdirsyncer/storage/remotestorage.py vdirsyncer-0.14.1/vdirsyncer/storage/remotestorage.py
--- vdirsyncer-0.14.0/vdirsyncer/storage/remotestorage.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/storage/remotestorage.py	2016-12-19 22:17:30.000000000 +0100
@@ -150,7 +150,7 @@
         except exceptions.NotFoundError:
             return
 
-        for name, info in _iter_listing(r.json()):
+        for name, _info in _iter_listing(r.json()):
             if not name.endswith('/'):
                 continue  # not a folder
 
diff -Nru vdirsyncer-0.14.0/vdirsyncer/sync.py vdirsyncer-0.14.1/vdirsyncer/sync.py
--- vdirsyncer-0.14.0/vdirsyncer/sync.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/sync.py	2017-01-02 18:19:33.000000000 +0100
@@ -85,6 +85,34 @@
     storage = None
 
 
+class _ItemMetadata:
+    href = None
+    _item = None
+    hash = None
+    etag = None
+
+    def __init__(self, **kwargs):
+        for k, v in kwargs.items():
+            assert hasattr(self, k)
+            setattr(self, k, v)
+
+    @property
+    def item(self):
+        return self._item
+
+    @item.setter
+    def item(self, item):
+        self._item = item
+        self.hash = item.hash
+
+    def to_status(self):
+        return {
+            'href': self.href,
+            'etag': self.etag,
+            'hash': self.hash
+        }
+
+
 class _StorageInfo(object):
     '''A wrapper class that holds prefetched items, the status and other
     things.'''
@@ -102,7 +130,7 @@
         self.new_status = None
 
     def prepare_new_status(self):
-        href_to_status = dict((meta['href'], (ident, meta))
+        href_to_status = dict((meta.href, (ident, meta))
                               for ident, meta
                               in self.status.items())
 
@@ -113,32 +141,31 @@
             new_props = self.new_status.setdefault(ident, props)
             if new_props is not props:
                 raise IdentConflict(storage=self.storage,
-                                    hrefs=[new_props['href'],
-                                           props['href']])
+                                    hrefs=[new_props.href,
+                                           props.href])
 
         for href, etag in self.storage.list():
-            ident, old_meta = href_to_status.get(href, (None, None))
-            meta = dict(old_meta) if old_meta is not None else {}
-            meta['href'] = href
-            meta['etag'] = etag
-            assert etag is not None
-            if meta != old_meta:
+            ident, meta = href_to_status.get(href, (None, None))
+            if meta is None:
+                meta = _ItemMetadata()
+
+            if meta.href != href or meta.etag != etag:
                 # Either the item is completely new, or updated
                 # In both cases we should prefetch
                 prefetch.append(href)
             else:
+                meta.href = href
+                meta.etag = etag
                 _store_props(ident, meta)
 
         # Prefetch items
         for href, item, etag in (self.storage.get_multi(prefetch)
                                  if prefetch else ()):
-            meta = {
-                'href': href,
-                'etag': etag,
-                'item': item,
-                'hash': item.hash,
-            }
-            _store_props(item.ident, meta)
+            _store_props(item.ident, _ItemMetadata(
+                href=href,
+                etag=etag,
+                item=item
+            ))
 
     def is_changed(self, ident):
         status = self.status.get(ident, None)
@@ -147,9 +174,9 @@
         if status is None:  # new item
             return True
 
-        if meta['etag'] != status['etag']:  # etag changed
-            old_hash = status.get('hash')
-            if old_hash is None or meta['item'].hash != old_hash:
+        if meta.etag != status.etag:  # etag changed
+            old_hash = status.hash
+            if old_hash is None or meta.hash != old_hash:
                 # item actually changed
                 return True
             else:
@@ -157,7 +184,7 @@
                 return False
 
 
-def _status_migrate(status):
+def _migrate_status(status):
     for ident in list(status):
         value = status[ident]
         if len(value) == 4:
@@ -176,19 +203,6 @@
             b.setdefault('hash', '')
 
 
-def _compress_meta(meta):
-    '''Make in-memory metadata suitable for disk storage by removing fetched
-    item content'''
-    if set(meta) == {'href', 'etag', 'hash'}:
-        return meta
-
-    return {
-        'href': meta['href'],
-        'etag': meta['etag'],
-        'hash': meta['hash']
-    }
-
-
 def sync(storage_a, storage_b, status, conflict_resolution=None,
          force_delete=False, error_callback=None, partial_sync='revert'):
     '''Synchronizes two storages.
@@ -227,13 +241,13 @@
     elif conflict_resolution == 'b wins':
         conflict_resolution = lambda a, b: b
 
-    _status_migrate(status)
+    _migrate_status(status)
 
     a_status = {}
     b_status = {}
     for ident, (meta_a, meta_b) in status.items():
-        a_status[ident] = meta_a
-        b_status[ident] = meta_b
+        a_status[ident] = _ItemMetadata(**meta_a)
+        b_status[ident] = _ItemMetadata(**meta_b)
 
     a_info = _StorageInfo(storage_a, a_status)
     b_info = _StorageInfo(storage_b, b_status)
@@ -263,8 +277,8 @@
     for ident in uniq(itertools.chain(a_info.new_status,
                                       b_info.new_status)):
         status[ident] = (
-            _compress_meta(a_info.new_status[ident]),
-            _compress_meta(b_info.new_status[ident])
+            a_info.new_status[ident].to_status(),
+            b_info.new_status[ident].to_status()
         )
 
 
@@ -317,11 +331,11 @@
             href, etag = self.dest.storage.upload(self.item)
 
         assert self.ident not in self.dest.new_status
-        self.dest.new_status[self.ident] = {
-            'href': href,
-            'hash': self.item.hash,
-            'etag': etag
-        }
+        self.dest.new_status[self.ident] = _ItemMetadata(
+            href=href,
+            hash=self.item.hash,
+            etag=etag
+        )
 
 
 class Update(Action):
@@ -333,20 +347,16 @@
     def _run_impl(self, a, b):
 
         if self.dest.storage.read_only:
-            href = etag = None
+            meta = _ItemMetadata(item=self.item)
         else:
             sync_logger.info(u'Copying (updating) item {} to {}'
                              .format(self.ident, self.dest.storage))
             meta = self.dest.new_status[self.ident]
-            href = meta['href']
-            etag = self.dest.storage.update(href, self.item, meta['etag'])
-            assert isinstance(etag, (bytes, str))
-
-        self.dest.new_status[self.ident] = {
-            'href': href,
-            'hash': self.item.hash,
-            'etag': etag
-        }
+            meta.etag = \
+                self.dest.storage.update(meta.href, self.item, meta.etag)
+            assert isinstance(meta.etag, (bytes, str))
+
+        self.dest.new_status[self.ident] = meta
 
 
 class Delete(Action):
@@ -359,7 +369,7 @@
         if not self.dest.storage.read_only:
             sync_logger.info(u'Deleting item {} from {}'
                              .format(self.ident, self.dest.storage))
-            self.dest.storage.delete(meta['href'], meta['etag'])
+            self.dest.storage.delete(meta.href, meta.etag)
         del self.dest.new_status[self.ident]
 
 
@@ -374,17 +384,17 @@
             meta_a = a.new_status[self.ident]
             meta_b = b.new_status[self.ident]
 
-            if meta_a['item'].hash == meta_b['item'].hash:
+            if meta_a.hash == meta_b.hash:
                 sync_logger.info(u'...same content on both sides.')
             elif conflict_resolution is None:
-                raise SyncConflict(ident=self.ident, href_a=meta_a['href'],
-                                   href_b=meta_b['href'])
+                raise SyncConflict(ident=self.ident, href_a=meta_a.href,
+                                   href_b=meta_b.href)
             elif callable(conflict_resolution):
-                new_item = conflict_resolution(meta_a['item'], meta_b['item'])
-                if new_item.hash != meta_a['item'].hash:
+                new_item = conflict_resolution(meta_a.item, meta_b.item)
+                if new_item.hash != meta_a.hash:
                     Update(new_item, a).run(a, b, conflict_resolution,
                                             partial_sync)
-                if new_item.hash != meta_b['item'].hash:
+                if new_item.hash != meta_b.hash:
                     Update(new_item, b).run(a, b, conflict_resolution,
                                             partial_sync)
             else:
@@ -408,15 +418,15 @@
                 yield ResolveConflict(ident)
             elif a_changed and not b_changed:
                 # item was only modified in a
-                yield Update(a['item'], b_info)
+                yield Update(a.item, b_info)
             elif not a_changed and b_changed:
                 # item was only modified in b
-                yield Update(b['item'], a_info)
+                yield Update(b.item, a_info)
         elif a and not b:
             if a_info.is_changed(ident):
                 # was deleted from b but modified on a
                 # OR: new item was created in a
-                yield Upload(a['item'], b_info)
+                yield Upload(a.item, b_info)
             else:
                 # was deleted from b and not modified on a
                 yield Delete(ident, a_info)
@@ -424,7 +434,7 @@
             if b_info.is_changed(ident):
                 # was deleted from a but modified on b
                 # OR: new item was created in b
-                yield Upload(b['item'], a_info)
+                yield Upload(b.item, a_info)
             else:
                 # was deleted from a and not changed on b
                 yield Delete(ident, b_info)
diff -Nru vdirsyncer-0.14.0/vdirsyncer/utils/__init__.py vdirsyncer-0.14.1/vdirsyncer/utils/__init__.py
--- vdirsyncer-0.14.0/vdirsyncer/utils/__init__.py	2016-10-23 01:24:49.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/utils/__init__.py	2016-12-05 14:19:22.000000000 +0100
@@ -10,6 +10,10 @@
 from .. import exceptions
 
 
+# This is only a subset of the chars allowed per the spec. In particular `@` is
+# not included, because there are some servers that (incorrectly) encode it to
+# `%40` when it's part of a URL path, and reject or "repair" URLs that contain
+# `@` in the path. So it's better to just avoid it.
 SAFE_UID_CHARS = ('abcdefghijklmnopqrstuvwxyz'
                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                   '0123456789_.-+')
diff -Nru vdirsyncer-0.14.0/vdirsyncer/utils/vobject.py vdirsyncer-0.14.1/vdirsyncer/utils/vobject.py
--- vdirsyncer-0.14.0/vdirsyncer/utils/vobject.py	2016-10-23 01:27:22.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/utils/vobject.py	2016-12-19 22:17:10.000000000 +0100
@@ -154,6 +154,7 @@
         item.subcomponents.extend(inline)
         yield u'\r\n'.join(item.dump_lines())
 
+
 _default_join_wrappers = {
     u'VCALENDAR': u'VCALENDAR',
     u'VEVENT': u'VCALENDAR',
@@ -255,7 +256,7 @@
         stack = []
         rv = []
         try:
-            for i, line in enumerate(lines):
+            for _i, line in enumerate(lines):
                 if line.startswith(u'BEGIN:'):
                     c_name = line[len(u'BEGIN:'):].strip().upper()
                     stack.append(cls(c_name, [], []))
@@ -270,7 +271,7 @@
                         stack[-1].props.append(line)
         except IndexError:
             raise ValueError('Parsing error at line {}. Check the debug log '
-                             'for more information.'.format(i + 1))
+                             'for more information.'.format(_i + 1))
 
         if multiple:
             return rv
diff -Nru vdirsyncer-0.14.0/vdirsyncer/version.py vdirsyncer-0.14.1/vdirsyncer/version.py
--- vdirsyncer-0.14.0/vdirsyncer/version.py	2016-10-26 16:35:52.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer/version.py	2017-01-05 17:48:48.000000000 +0100
@@ -1,4 +1,4 @@
 # coding: utf-8
 # file generated by setuptools_scm
 # don't change, don't track in version control
-version = '0.14.0'
+version = '0.14.1'
diff -Nru vdirsyncer-0.14.0/vdirsyncer.egg-info/PKG-INFO vdirsyncer-0.14.1/vdirsyncer.egg-info/PKG-INFO
--- vdirsyncer-0.14.0/vdirsyncer.egg-info/PKG-INFO	2016-10-26 16:35:52.000000000 +0200
+++ vdirsyncer-0.14.1/vdirsyncer.egg-info/PKG-INFO	2017-01-05 17:48:48.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: vdirsyncer
-Version: 0.14.0
+Version: 0.14.1
 Summary: Synchronize calendars and contacts
 Home-page: https://github.com/pimutils/vdirsyncer
 Author: Markus Unterwaditzer
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.alioth.debian.org/pipermail/python-apps-team/attachments/20170327/17710b00/attachment-0001.sig>


More information about the Python-apps-team mailing list