config: Add warning about unquoted strings

This commit is contained in:
Markus Unterwaditzer 2016-10-23 00:56:26 +02:00
parent 8171c46b10
commit 5a257ec2cd
17 changed files with 281 additions and 274 deletions

View file

@ -16,6 +16,8 @@ Version 0.14.0
exit code in such situations is still non-zero.
- Add ``partial_sync`` option to pair section. See :ref:`the config docs
<partial_sync_def>`.
- Vdirsyner will now warn if there's a string without quotes in your config.
Please file issues if you find documentation that uses unquoted strings.
Version 0.13.1
==============

View file

@ -16,8 +16,8 @@ status_path = ~/.vdirsyncer/status/
# A `[pair <name>]` block defines two storages `a` and `b` that should be
# synchronized. The definition of these storages follows in `[storage <name>]`
# blocks. This is similar to accounts in OfflineIMAP.
a = bob_contacts_local
b = bob_contacts_remote
a = "bob_contacts_local"
b = "bob_contacts_remote"
# Synchronize all collections that can be found.
# You need to run `vdirsyncer discover` if new calendars/addressbooks are added
@ -37,13 +37,13 @@ metadata = ["displayname"]
[storage bob_contacts_local]
# A storage references actual data on a remote server or on the local disk.
# Similar to repositories in OfflineIMAP.
type = filesystem
path = ~/.contacts/
fileext = .vcf
type = "filesystem"
path = "~/.contacts/"
fileext = ".vcf"
[storage bob_contacts_remote]
type = carddav
url = https://owncloud.example.com/remote.php/carddav/
type = "carddav"
url = "https://owncloud.example.com/remote.php/carddav/"
#username =
# The password can also be fetched from the system password storage, netrc or a
# custom command. See http://vdirsyncer.pimutils.org/en/stable/keyring.html
@ -51,20 +51,20 @@ url = https://owncloud.example.com/remote.php/carddav/
# CALDAV
[pair bob_calendar]
a = bob_calendar_local
b = bob_calendar_remote
a = "bob_calendar_local"
b = "bob_calendar_remote"
collections = ["from a", "from b"]
# Calendars also have a color property
metadata = ["displayname", "color"]
[storage bob_calendar_local]
type = filesystem
path = ~/.calendars/
fileext = .ics
type = "filesystem"
path = "~/.calendars/"
fileext = ".ics"
[storage bob_calendar_remote]
type = caldav
url = https://owncloud.example.com/remote.php/caldav/
type = "caldav"
url = "https://owncloud.example.com/remote.php/caldav/"
#username =
#password =

View file

@ -14,24 +14,24 @@ Command
Say you have the following configuration::
[storage foo]
type = caldav
type = "caldav"
url = ...
username = foo
password = bar
username = "foo"
password = "bar"
But it bugs you that the password is stored in cleartext in the config file.
You can do this::
[storage foo]
type = caldav
type = "caldav"
url = ...
username = foo
username = "foo"
password.fetch = ["command", "~/get-password.sh", "more", "args"]
You can fetch the username as well::
[storage foo]
type = caldav
type = "caldav"
url = ...
username.fetch = ["command", "~/get-username.sh"]
password.fetch = ["command", "~/get-password.sh"]
@ -62,6 +62,6 @@ Password Prompt
You can also simply prompt for the password::
[storage foo]
type = caldav
username = myusername
type = "caldav"
username = "myusername"
password.fetch = ["prompt", "Password for CalDAV"]

View file

@ -25,17 +25,17 @@ Step 2: Creating the config
Paste this into your vdirsyncer config::
[pair holidays]
a = holidays_public
b = holidays_private
a = "holidays_public"
b = "holidays_private"
collections = null
[storage holidays_public]
type = http
type = "http"
# The URL to your iCalendar file.
url = ...
[storage holidays_private]
type = caldav
type = "caldav"
# The direct URL to your calendar.
url = ...
# The credentials to your CalDAV server
@ -60,8 +60,8 @@ doesn't have the rights to do so.
For such purposes you can set the ``partial_sync`` parameter to ``ignore``::
[pair holidays]
a = holidays_public
b = holidays_private
a = "holidays_public"
b = "holidays_private"
collections = null
partial_sync = ignore

View file

@ -12,7 +12,7 @@ Pinning by fingerprint
To pin the certificate by fingerprint::
[storage foo]
type = caldav
type = "caldav"
...
verify_fingerprint = "94:FD:7A:CB:50:75:A4:69:82:0A:F8:23:DF:07:FC:69:3E:CD:90:CA"
#verify = false # Optional: Disable CA validation, useful for self-signed certs
@ -32,7 +32,7 @@ Custom root CAs
To point vdirsyncer to a custom set of root CAs::
[storage foo]
type = caldav
type = "caldav"
...
verify = "/path/to/cert.pem"
@ -62,13 +62,13 @@ Client certificates may be specified with the ``auth_cert`` parameter. If the
key and certificate are stored in the same file, it may be a string::
[storage foo]
type = caldav
type = "caldav"
...
auth_cert = "/path/to/certificate.pem"
If the key and certificate are separate, a list may be used::
[storage foo]
type = caldav
type = "caldav"
...
auth_cert = ["/path/to/certificate.crt", "/path/to/key.key"]

View file

@ -99,14 +99,14 @@ ownCloud
Vdirsyncer is continuously tested against the latest version of ownCloud_::
[storage cal]
type = caldav
url = https://example.com/owncloud/remote.php/caldav/
type = "caldav"
url = "https://example.com/owncloud/remote.php/caldav/"
username = ...
password = ...
[storage card]
type = carddav
url = https://example.com/owncloud/remote.php/carddav/
type = "carddav"
url = "https://example.com/owncloud/remote.php/carddav/"
username = ...
password = ...
@ -123,14 +123,14 @@ nextCloud
Vdirsyncer is continuously tested against the latest version of nextCloud_::
[storage cal]
type = caldav
url = https://nextcloud.example.com/
type = "caldav"
url = "https://nextcloud.example.com/"
username = ...
password = ...
[storage card]
type = carddav
url = https://nextcloud.example.com/
type = "carddav"
url = "https://nextcloud.example.com/"
- WebCAL-subscriptions can't be discovered by vdirsyncer. See `this relevant
issue <https://github.com/nextcloud/calendar/issues/63>`_.
@ -147,14 +147,14 @@ with it. `FastMail's support pages
the settings to use::
[storage cal]
type = caldav
url = https://caldav.messagingengine.com/
type = "caldav"
url = "https://caldav.messagingengine.com/"
username = ...
password = ...
[storage card]
type = carddav
url = https://carddav.messagingengine.com/
type = "carddav"
url = "https://carddav.messagingengine.com/"
username = ...
password = ...
@ -170,14 +170,14 @@ Vdirsyncer is irregularly tested against iCloud_.
::
[storage cal]
type = caldav
url = https://caldav.icloud.com/
type = "caldav"
url = "https://caldav.icloud.com/"
username = ...
password = ...
[storage card]
type = carddav
url = https://contacts.icloud.com/
type = "carddav"
url = "https://contacts.icloud.com/"
username = ...
password = ...
@ -202,9 +202,9 @@ special characters and/or using an old DavMail version.
**Make absolutely sure you use the latest DavMail**::
[storage outlook]
type = caldav
url = http://localhost:1080/
username = user@example.com
type = "caldav"
url = "http://localhost:1080/"
username = "user@example.com"
password = ...
- Older versions of DavMail handle URLs case-insensitively. See :gh:`144`.

View file

@ -56,22 +56,22 @@ The following example synchronizes ownCloud's addressbooks to ``~/.contacts/``::
[pair my_contacts]
a = my_contacts_local
b = my_contacts_remote
a = "my_contacts_local"
b = "my_contacts_remote"
collections = ["from a", "from b"]
[storage my_contacts_local]
type = filesystem
path = ~/.contacts/
fileext = .vcf
type = "filesystem"
path = "~/.contacts/"
fileext = ".vcf"
[storage my_contacts_remote]
type = carddav
type = "carddav"
# We can simplify this URL here as well. In theory it shouldn't matter.
url = https://owncloud.example.com/remote.php/carddav/
username = bob
password = asdf
url = "https://owncloud.example.com/remote.php/carddav/"
username = "bob"
password = "asdf"
.. note::
@ -127,22 +127,22 @@ color associated with a calendar. For the purpose of explaining this feature,
let's switch to a different base example. This time we'll synchronize calendars::
[pair my_calendars]
a = my_calendars_local
b = my_calendars_remote
a = "my_calendars_local"
b = "my_calendars_remote"
collections = ["from a", "from b"]
metadata = ["color"]
[storage my_calendars_local]
type = filesystem
path = ~/.calendars/
fileext = .ics
type = "filesystem"
path = "~/.calendars/"
fileext = ".ics"
[storage my_calendars_remote]
type = caldav
type = "caldav"
url = https://owncloud.example.com/remote.php/caldav/
username = bob
password = asdf
url = "https://owncloud.example.com/remote.php/caldav/"
username = "bob"
password = "asdf"
Run ``vdirsyncer discover`` for discovery. Then you can use ``vdirsyncer
metasync`` to synchronize the ``color`` property between your local calendars
@ -179,19 +179,19 @@ The last one requires a bit more explanation. Assume this config which
synchronizes two directories of addressbooks::
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = ["from a", "from b"]
[storage foo]
type = filesystem
fileext = .vcf
path = ./contacts_foo/
type = "filesystem"
fileext = ".vcf"
path = "./contacts_foo/"
[storage bar]
type = filesystem
fileext = .vcf
path = ./contacts_bar/
type = "filesystem"
fileext = ".vcf"
path = "./contacts_bar/"
As we saw previously this will synchronize all collections in
``./contacts_foo/`` with each same-named collection in ``./contacts_bar/``. If

View file

@ -23,7 +23,7 @@ class _CustomRunner(object):
def write_with_general(self, data):
self.cfg.write(dedent('''
[general]
status_path = {}/status/
status_path = "{}/status/"
''').format(str(self.tmpdir)))
self.cfg.write(data, mode='a')

View file

@ -43,19 +43,19 @@ def test_read_config(read_config):
status_path = /tmp/status/
[pair bob]
a = bob_a
b = bob_b
a = "bob_a"
b = "bob_b"
collections = null
[storage bob_a]
type = filesystem
path = /tmp/contacts/
fileext = .vcf
type = "filesystem"
path = "/tmp/contacts/"
fileext = ".vcf"
yesno = false
number = 42
[storage bob_b]
type = carddav
type = "carddav"
''')
assert c.general == {'status_path': '/tmp/status/'}
@ -79,14 +79,14 @@ def test_missing_collections_param(read_config):
status_path = /tmp/status/
[pair bob]
a = bob_a
b = bob_b
a = "bob_a"
b = "bob_b"
[storage bob_a]
type = lmao
type = "lmao"
[storage bob_b]
type = lmao
type = "lmao"
''')
assert 'collections parameter missing' in str(excinfo.value)
@ -120,19 +120,19 @@ def test_missing_general_section(read_config):
with pytest.raises(exceptions.UserError) as excinfo:
read_config(u'''
[pair my_pair]
a = my_a
b = my_b
a = "my_a"
b = "my_b"
collections = null
[storage my_a]
type = filesystem
path = {base}/path_a/
fileext = .txt
type = "filesystem"
path = "{base}/path_a/"
fileext = ".txt"
[storage my_b]
type = filesystem
path = {base}/path_b/
fileext = .txt
type = "filesystem"
path = "{base}/path_b/"
fileext = ".txt"
''')
assert 'Invalid general section.' in str(excinfo.value)
@ -171,19 +171,19 @@ def test_invalid_collections_arg(read_config):
status_path = /tmp/status/
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = [null]
[storage foo]
type = filesystem
path = /tmp/foo/
fileext = .txt
type = "filesystem"
path = "/tmp/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = /tmp/bar/
fileext = .txt
type = "filesystem"
path = "/tmp/bar/"
fileext = ".txt"
''')
assert 'Expected string' in str(excinfo.value)
@ -196,19 +196,19 @@ def test_duplicate_sections(read_config):
status_path = /tmp/status/
[pair foobar]
a = foobar
b = bar
a = "foobar"
b = "bar"
collections = null
[storage foobar]
type = filesystem
path = /tmp/foo/
fileext = .txt
type = "filesystem"
path = "/tmp/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = /tmp/bar/
fileext = .txt
type = "filesystem"
path = "/tmp/bar/"
fileext = ".txt"
''')
assert 'Name "foobar" already used' in str(excinfo.value)
@ -219,10 +219,10 @@ def test_parse_config_value(parse_config_value):
assert x('123 # comment!') is invalid
assert x('True') == ('True', 1)
assert x('False') == ('False', 1)
assert x('Yes') == ('Yes', 1)
assert x('None') == ('None', 1)
assert x('True') is invalid
assert x('False') is invalid
assert x('Yes') is invalid
assert x('None') is invalid
assert x('"True"') == ('True', 0)
assert x('"False"') == ('False', 0)
@ -231,7 +231,7 @@ def test_parse_config_value(parse_config_value):
assert x('false') == (False, 0)
assert x('null') == (None, 0)
assert x('3.14') == (3.14, 0)
assert x('') == ('', 0)
assert x('') == ('', 1)
assert x('""') == ('', 0)

View file

@ -1,3 +1,4 @@
import json
from textwrap import dedent
import hypothesis.strategies as st
@ -10,18 +11,18 @@ from vdirsyncer.storage.base import Storage
def test_discover_command(tmpdir, runner):
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
path = {0}/foo/
fileext = .txt
type = "filesystem"
path = "{0}/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = {0}/bar/
fileext = .txt
type = "filesystem"
path = "{0}/bar/"
fileext = ".txt"
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = ["from a"]
''').format(str(tmpdir)))
@ -68,18 +69,18 @@ def test_discover_different_collection_names(tmpdir, runner):
bar = tmpdir.mkdir('bar')
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
fileext = .txt
path = {foo}
type = "filesystem"
fileext = ".txt"
path = "{foo}"
[storage bar]
type = filesystem
fileext = .txt
path = {bar}
type = "filesystem"
fileext = ".txt"
path = "{bar}"
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = [
["coll1", "coll_a1", "coll_b1"],
"coll2"
@ -114,18 +115,18 @@ def test_discover_direct_path(tmpdir, runner):
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
fileext = .txt
path = {foo}
type = "filesystem"
fileext = ".txt"
path = "{foo}"
[storage bar]
type = filesystem
fileext = .txt
path = {bar}
type = "filesystem"
fileext = ".txt"
path = "{bar}"
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
''').format(foo=str(foo), bar=str(bar)))
@ -142,18 +143,18 @@ def test_discover_direct_path(tmpdir, runner):
def test_null_collection_with_named_collection(tmpdir, runner):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = [["baz", "baz", null]]
[storage foo]
type = filesystem
path = {base}/foo/
fileext = .txt
type = "filesystem"
path = "{base}/foo/"
fileext = ".txt"
[storage bar]
type = singlefile
path = {base}/bar.txt
type = "singlefile"
path = "{base}/bar.txt"
'''.format(base=str(tmpdir))))
result = runner.invoke(['discover'], input='y\n' * 2)
@ -192,18 +193,18 @@ def test_collection_required(a_requires, b_requires, tmpdir, runner,
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
[storage foo]
type = test
type = "test"
require_collection = {a}
[storage bar]
type = test
type = "test"
require_collection = {b}
'''.format(a=a_requires, b=b_requires)))
'''.format(a=json.dumps(a_requires), b=json.dumps(b_requires))))
result = runner.invoke(['discover'])
if a_requires or b_requires:

View file

@ -41,18 +41,18 @@ def value_cache(monkeypatch):
def test_get_password_from_command(tmpdir, runner):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = ["a", "b", "c"]
[storage foo]
type = filesystem
path = {base}/foo/
type = "filesystem"
path = "{base}/foo/"
fileext.fetch = ["command", "echo", ".txt"]
[storage bar]
type = filesystem
path = {base}/bar/
type = "filesystem"
path = "{base}/bar/"
fileext.fetch = ["prompt", "Fileext for bar"]
'''.format(base=str(tmpdir))))

View file

@ -9,9 +9,9 @@ import pytest
def test_full(tmpdir, runner, collection):
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
path = {base}/foo/
fileext = .txt
type = "filesystem"
path = "{base}/foo/"
fileext = ".txt"
''').format(base=str(tmpdir)))
storage = tmpdir.mkdir('foo')

View file

@ -13,19 +13,19 @@ import pytest
def test_simple_run(tmpdir, runner):
runner.write_with_general(dedent('''
[pair my_pair]
a = my_a
b = my_b
a = "my_a"
b = "my_b"
collections = null
[storage my_a]
type = filesystem
path = {0}/path_a/
fileext = .txt
type = "filesystem"
path = "{0}/path_a/"
fileext = ".txt"
[storage my_b]
type = filesystem
path = {0}/path_b/
fileext = .txt
type = "filesystem"
path = "{0}/path_b/"
fileext = ".txt"
''').format(str(tmpdir)))
tmpdir.mkdir('path_a')
@ -54,19 +54,19 @@ def test_sync_inexistant_pair(tmpdir, runner):
def test_debug_connections(tmpdir, runner):
runner.write_with_general(dedent('''
[pair my_pair]
a = my_a
b = my_b
a = "my_a"
b = "my_b"
collections = null
[storage my_a]
type = filesystem
path = {0}/path_a/
fileext = .txt
type = "filesystem"
path = "{0}/path_a/"
fileext = ".txt"
[storage my_b]
type = filesystem
path = {0}/path_b/
fileext = .txt
type = "filesystem"
path = "{0}/path_b/"
fileext = ".txt"
''').format(str(tmpdir)))
tmpdir.mkdir('path_a')
@ -85,19 +85,19 @@ def test_debug_connections(tmpdir, runner):
def test_empty_storage(tmpdir, runner):
runner.write_with_general(dedent('''
[pair my_pair]
a = my_a
b = my_b
a = "my_a"
b = "my_b"
collections = null
[storage my_a]
type = filesystem
path = {0}/path_a/
fileext = .txt
type = "filesystem"
path = "{0}/path_a/"
fileext = ".txt"
[storage my_b]
type = filesystem
path = {0}/path_b/
fileext = .txt
type = "filesystem"
path = "{0}/path_b/"
fileext = ".txt"
''').format(str(tmpdir)))
tmpdir.mkdir('path_a')
@ -137,18 +137,18 @@ def test_collections_cache_invalidation(tmpdir, runner):
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
path = {0}/foo/
fileext = .txt
type = "filesystem"
path = "{0}/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = {0}/bar/
fileext = .txt
type = "filesystem"
path = "{0}/bar/"
fileext = ".txt"
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = ["a", "b", "c"]
''').format(str(tmpdir)))
@ -167,18 +167,18 @@ def test_collections_cache_invalidation(tmpdir, runner):
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
path = {0}/foo/
fileext = .txt
type = "filesystem"
path = "{0}/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = {0}/bar2/
fileext = .txt
type = "filesystem"
path = "{0}/bar2/"
fileext = ".txt"
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = ["a", "b", "c"]
''').format(str(tmpdir)))
@ -207,18 +207,18 @@ def test_collections_cache_invalidation(tmpdir, runner):
def test_invalid_pairs_as_cli_arg(tmpdir, runner):
runner.write_with_general(dedent('''
[storage foo]
type = filesystem
path = {0}/foo/
fileext = .txt
type = "filesystem"
path = "{0}/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = {0}/bar/
fileext = .txt
type = "filesystem"
path = "{0}/bar/"
fileext = ".txt"
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = ["a", "b", "c"]
''').format(str(tmpdir)))
@ -240,17 +240,17 @@ def test_multiple_pairs(tmpdir, runner):
for name_a, name_b in ('foo', 'bar'), ('bam', 'baz'):
yield dedent('''
[pair {a}{b}]
a = {a}
b = {b}
a = "{a}"
b = "{b}"
collections = null
''').format(a=name_a, b=name_b)
for name in name_a, name_b:
yield dedent('''
[storage {name}]
type = filesystem
path = {path}
fileext = .txt
type = "filesystem"
path = "{path}"
fileext = ".txt"
''').format(name=name, path=str(tmpdir.mkdir(name)))
runner.write_with_general(''.join(get_cfg()))
@ -291,19 +291,19 @@ def test_create_collections(subtest, collections):
def test_inner(tmpdir, runner):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = {colls}
[storage foo]
type = filesystem
path = {base}/foo/
fileext = .txt
type = "filesystem"
path = "{base}/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = {base}/bar/
fileext = .txt
type = "filesystem"
path = "{base}/bar/"
fileext = ".txt"
'''.format(base=str(tmpdir), colls=json.dumps(list(collections)))))
result = runner.invoke(
@ -337,19 +337,19 @@ def test_create_collections(subtest, collections):
def test_ident_conflict(tmpdir, runner):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
[storage foo]
type = filesystem
path = {base}/foo/
fileext = .txt
type = "filesystem"
path = "{base}/foo/"
fileext = ".txt"
[storage bar]
type = filesystem
path = {base}/bar/
fileext = .txt
type = "filesystem"
path = "{base}/bar/"
fileext = ".txt"
'''.format(base=str(tmpdir))))
foo = tmpdir.mkdir('foo')
@ -380,14 +380,14 @@ def test_ident_conflict(tmpdir, runner):
def test_unknown_storage(tmpdir, runner, existing, missing):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
[storage {existing}]
type = filesystem
path = {base}/{existing}/
fileext = .txt
type = "filesystem"
path = "{base}/{existing}/"
fileext = ".txt"
'''.format(base=str(tmpdir), existing=existing)))
tmpdir.mkdir(existing)
@ -418,20 +418,20 @@ def test_conflict_resolution(tmpdir, runner, resolution, expect_foo,
expect_bar):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
conflict_resolution = {val}
[storage foo]
type = filesystem
fileext = .txt
path = {base}/foo
type = "filesystem"
fileext = ".txt"
path = "{base}/foo"
[storage bar]
type = filesystem
fileext = .txt
path = {base}/bar
type = "filesystem"
fileext = ".txt"
path = "{base}/bar"
'''.format(base=str(tmpdir), val=json.dumps(resolution))))
foo = tmpdir.join('foo')
@ -455,21 +455,21 @@ def test_conflict_resolution(tmpdir, runner, resolution, expect_foo,
def test_partial_sync(tmpdir, runner, partial_sync):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
{partial_sync}
[storage foo]
type = filesystem
fileext = .txt
path = {base}/foo
type = "filesystem"
fileext = ".txt"
path = "{base}/foo"
[storage bar]
type = filesystem
type = "filesystem"
read_only = true
fileext = .txt
path = {base}/bar
fileext = ".txt"
path = "{base}/bar"
'''.format(
partial_sync=('partial_sync = {}\n'.format(partial_sync)
if partial_sync else ''),
@ -523,28 +523,28 @@ def test_fetch_only_necessary_params(tmpdir, runner):
runner.write_with_general(dedent('''
[pair foobar]
a = foo
b = bar
a = "foo"
b = "bar"
collections = null
[pair bambar]
a = bam
b = bar
a = "bam"
b = "bar"
collections = null
[storage foo]
type = filesystem
path = {path}
fileext = .txt
type = "filesystem"
path = "{path}"
fileext = ".txt"
[storage bar]
type = filesystem
path = {path}
fileext = .txt
type = "filesystem"
path = "{path}"
fileext = ".txt"
[storage bam]
type = filesystem
path = {path}
type = "filesystem"
path = "{path}"
fileext.fetch = ["command", "sh", "{script}"]
'''.format(path=str(tmpdir.mkdir('bogus')), script=str(fetch_script))))

View file

@ -71,7 +71,7 @@ def test_list(monkeypatch):
def test_readonly_param():
url = u'http://example.com/'
url = 'http://example.com/'
with pytest.raises(ValueError):
HttpStorage(url=url, read_only=False)

View file

@ -158,9 +158,9 @@ def _parse_config_value(value):
(('none',), 'null')
]:
if value.lower() in wrong + (right,):
cli_logger.warning('You probably meant {} instead of "{}", which '
'will now be interpreted as a literal string.'
.format(right, value))
raise ValueError('You probably meant {} instead of {}. Surround '
'your string with double-quotes if not.'
.format(right, value))
if '#' in value:
raise ValueError('Invalid value:{}\n'
@ -176,6 +176,10 @@ def _parse_config_value(value):
# # my comment
raise ValueError('No multiline-values allowed:\n{}'.format(value))
cli_logger.warning('Soon, all strings have to be in double quotes. Please '
'replace {} with {}'
.format(value, json.dumps(value)))
return value

View file

@ -117,12 +117,12 @@ class HttpStorage(Storage):
collections = null
[storage holidays_local]
type = filesystem
type = "filesystem"
path = ~/.config/vdir/calendars/holidays/
fileext = .ics
[storage holidays_remote]
type = http
type = "http"
url = https://example.com/holidays_from_hicksville.ics
'''

View file

@ -53,11 +53,11 @@ class SingleFileStorage(Storage):
collections = ["from a", "from b"]
[storage my_calendar_local]
type = singlefile
type = "singlefile"
path = ~/.calendars/%s.ics
[storage my_calendar_remote]
type = caldav
type = "caldav"
url = https://caldav.example.org/
#username =
#password =
@ -69,11 +69,11 @@ class SingleFileStorage(Storage):
b = my_calendar_remote
[storage my_calendar_local]
type = singlefile
type = "singlefile"
path = ~/my_calendar.ics
[storage my_calendar_remote]
type = caldav
type = "caldav"
url = https://caldav.example.org/username/my_calendar/
#username =
#password =