Package: release.debian.org Severity: normal User: release.debian....@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)
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 <fi...@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 <fi...@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 <fi...@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 <fi...@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 <fi...@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) +@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 <fi...@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§ion=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/u...@example.com/calendar/" username = "u...@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') +@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
signature.asc
Description: PGP signature