diff --git a/docs/conf.py b/docs/conf.py
index 10cdc91..4b2c93b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -20,7 +20,7 @@ copyright = "2014-{}, Markus Unterwaditzer & contributors".format(
release = get_distribution("vdirsyncer").version
version = ".".join(release.split(".")[:2]) # The short X.Y version.
-rst_epilog = ".. |vdirsyncer_version| replace:: %s" % release
+rst_epilog = f".. |vdirsyncer_version| replace:: {release}"
exclude_patterns = ["_build"]
diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py
index 0f11930..53c2bb4 100644
--- a/tests/storage/__init__.py
+++ b/tests/storage/__init__.py
@@ -10,16 +10,15 @@ import aiostream
import pytest
import pytest_asyncio
+from tests import EVENT_TEMPLATE
+from tests import TASK_TEMPLATE
+from tests import VCARD_TEMPLATE
+from tests import assert_item_equals
+from tests import normalize_item
from vdirsyncer import exceptions
from vdirsyncer.storage.base import normalize_meta_value
from vdirsyncer.vobject import Item
-from .. import EVENT_TEMPLATE
-from .. import TASK_TEMPLATE
-from .. import VCARD_TEMPLATE
-from .. import assert_item_equals
-from .. import normalize_item
-
def get_server_mixin(server_name):
from . import __name__ as base
diff --git a/tests/storage/dav/__init__.py b/tests/storage/dav/__init__.py
index 912530e..f49362f 100644
--- a/tests/storage/dav/__init__.py
+++ b/tests/storage/dav/__init__.py
@@ -8,12 +8,11 @@ import aiostream
import pytest
from tests import assert_item_equals
+from tests.storage import StorageTests
+from tests.storage import get_server_mixin
from vdirsyncer import exceptions
from vdirsyncer.vobject import Item
-from .. import StorageTests
-from .. import get_server_mixin
-
dav_server = os.environ.get("DAV_SERVER", "skip")
ServerMixin = get_server_mixin(dav_server)
diff --git a/tests/storage/dav/test_caldav.py b/tests/storage/dav/test_caldav.py
index 656c7b4..ef534a0 100644
--- a/tests/storage/dav/test_caldav.py
+++ b/tests/storage/dav/test_caldav.py
@@ -11,10 +11,10 @@ from aioresponses import aioresponses
from tests import EVENT_TEMPLATE
from tests import TASK_TEMPLATE
from tests import VCARD_TEMPLATE
+from tests.storage import format_item
from vdirsyncer import exceptions
from vdirsyncer.storage.dav import CalDAVStorage
-from .. import format_item
from . import DAVStorageTests
from . import dav_server
diff --git a/vdirsyncer/cli/__init__.py b/vdirsyncer/cli/__init__.py
index 0885429..defa178 100644
--- a/vdirsyncer/cli/__init__.py
+++ b/vdirsyncer/cli/__init__.py
@@ -10,8 +10,8 @@ import aiohttp
import click
import click_log
-from .. import BUGTRACKER_HOME
-from .. import __version__
+from vdirsyncer import BUGTRACKER_HOME
+from vdirsyncer import __version__
cli_logger = logging.getLogger(__name__)
click_log.basic_config("vdirsyncer")
diff --git a/vdirsyncer/cli/config.py b/vdirsyncer/cli/config.py
index bbfec2c..ccc7bc6 100644
--- a/vdirsyncer/cli/config.py
+++ b/vdirsyncer/cli/config.py
@@ -8,13 +8,13 @@ from itertools import chain
from typing import IO
from typing import Any
from typing import Generator
-from typing import Tuple
-from .. import PROJECT_HOME
-from .. import exceptions
-from ..utils import cached_property
-from ..utils import expand_path
-from ..vobject import Item
+from vdirsyncer import PROJECT_HOME
+from vdirsyncer import exceptions
+from vdirsyncer.utils import cached_property
+from vdirsyncer.utils import expand_path
+from vdirsyncer.vobject import Item
+
from .fetchparams import expand_fetch_params
from .utils import storage_class_from_config
@@ -232,7 +232,7 @@ class PairConfig:
self.name_b: str = options.pop("b")
self._partial_sync: str | None = options.pop("partial_sync", None)
- self.metadata: str | Tuple[()] = options.pop("metadata", ())
+ self.metadata: str | tuple[()] = options.pop("metadata", ())
self.conflict_resolution = self._process_conflict_resolution_param(
options.pop("conflict_resolution", None)
@@ -338,7 +338,7 @@ def _resolve_conflict_via_command(
if _check_call is None:
from subprocess import check_call as _check_call
- from ..vobject import Item
+ from vdirsyncer.vobject import Item
dir = tempfile.mkdtemp(prefix="vdirsyncer-conflict.")
try:
diff --git a/vdirsyncer/cli/discover.py b/vdirsyncer/cli/discover.py
index 62495a7..52b132f 100644
--- a/vdirsyncer/cli/discover.py
+++ b/vdirsyncer/cli/discover.py
@@ -9,7 +9,8 @@ import sys
import aiohttp
import aiostream
-from .. import exceptions
+from vdirsyncer import exceptions
+
from .utils import handle_collection_not_found
from .utils import handle_storage_init_error
from .utils import load_status
diff --git a/vdirsyncer/cli/fetchparams.py b/vdirsyncer/cli/fetchparams.py
index 87a483a..79e9c98 100644
--- a/vdirsyncer/cli/fetchparams.py
+++ b/vdirsyncer/cli/fetchparams.py
@@ -4,9 +4,10 @@ import logging
import click
-from .. import exceptions
-from ..utils import expand_path
-from ..utils import synchronized
+from vdirsyncer import exceptions
+from vdirsyncer.utils import expand_path
+from vdirsyncer.utils import synchronized
+
from . import AppContext
SUFFIX = ".fetch"
diff --git a/vdirsyncer/cli/tasks.py b/vdirsyncer/cli/tasks.py
index 6e8f5ba..7ab1c0b 100644
--- a/vdirsyncer/cli/tasks.py
+++ b/vdirsyncer/cli/tasks.py
@@ -4,8 +4,9 @@ import json
import aiohttp
-from .. import exceptions
-from .. import sync
+from vdirsyncer import exceptions
+from vdirsyncer import sync
+
from .config import CollectionConfig
from .discover import DiscoverResult
from .discover import collections_for_pair
@@ -35,10 +36,8 @@ async def prepare_pair(pair_name, collections, config, *, connector):
config_a, config_b = all_collections[collection_name]
except KeyError:
raise exceptions.UserError(
- "Pair {}: Collection {} not found. These are the "
- "configured collections:\n{}".format(
- pair_name, json.dumps(collection_name), list(all_collections)
- )
+ f"Pair {pair_name}: Collection {json.dumps(collection_name)} not found. These are the "
+ f"configured collections:\n{list(all_collections)}"
)
collection = CollectionConfig(pair, collection_name, config_a, config_b)
@@ -105,7 +104,7 @@ async def repair_collection(
*,
connector: aiohttp.TCPConnector,
):
- from ..repair import repair_storage
+ from vdirsyncer.repair import repair_storage
storage_name, collection = collection, None
if "/" in storage_name:
@@ -136,7 +135,7 @@ async def repair_collection(
async def metasync_collection(collection, general, *, connector: aiohttp.TCPConnector):
- from ..metasync import metasync
+ from vdirsyncer.metasync import metasync
pair = collection.pair
status_name = get_status_name(pair.name, collection.name)
diff --git a/vdirsyncer/cli/utils.py b/vdirsyncer/cli/utils.py
index 8fa51ee..51b2991 100644
--- a/vdirsyncer/cli/utils.py
+++ b/vdirsyncer/cli/utils.py
@@ -11,18 +11,19 @@ from typing import Any
import aiohttp
import click
-from .. import BUGTRACKER_HOME
-from .. import DOCS_HOME
-from .. import exceptions
-from ..storage.base import Storage
-from ..sync.exceptions import IdentConflict
-from ..sync.exceptions import PartialSync
-from ..sync.exceptions import StorageEmpty
-from ..sync.exceptions import SyncConflict
-from ..sync.status import SqliteStatus
-from ..utils import atomic_write
-from ..utils import expand_path
-from ..utils import get_storage_init_args
+from vdirsyncer import BUGTRACKER_HOME
+from vdirsyncer import DOCS_HOME
+from vdirsyncer import exceptions
+from vdirsyncer.storage.base import Storage
+from vdirsyncer.sync.exceptions import IdentConflict
+from vdirsyncer.sync.exceptions import PartialSync
+from vdirsyncer.sync.exceptions import StorageEmpty
+from vdirsyncer.sync.exceptions import SyncConflict
+from vdirsyncer.sync.status import SqliteStatus
+from vdirsyncer.utils import atomic_write
+from vdirsyncer.utils import expand_path
+from vdirsyncer.utils import get_storage_init_args
+
from . import cli_logger
STATUS_PERMISSIONS = 0o600
@@ -78,13 +79,11 @@ def handle_cli_error(status_name=None, e=None):
cli_logger.critical(e)
except StorageEmpty as e:
cli_logger.error(
- '{status_name}: Storage "{name}" was completely emptied. If you '
+ f'{status_name}: Storage "{e.empty_storage.instance_name}" was completely emptied. If you '
"want to delete ALL entries on BOTH sides, then use "
- "`vdirsyncer sync --force-delete {status_name}`. "
- "Otherwise delete the files for {status_name} in your status "
- "directory.".format(
- name=e.empty_storage.instance_name, status_name=status_name
- )
+ f"`vdirsyncer sync --force-delete {status_name}`. "
+ f"Otherwise delete the files for {status_name} in your status "
+ "directory."
)
except PartialSync as e:
cli_logger.error(
diff --git a/vdirsyncer/storage/base.py b/vdirsyncer/storage/base.py
index fcbc379..38cb188 100644
--- a/vdirsyncer/storage/base.py
+++ b/vdirsyncer/storage/base.py
@@ -6,11 +6,10 @@ from abc import ABCMeta
from abc import abstractmethod
from typing import Iterable
+from vdirsyncer import exceptions
+from vdirsyncer.utils import uniq
from vdirsyncer.vobject import Item
-from .. import exceptions
-from ..utils import uniq
-
def mutating_storage_method(f):
"""Wrap a method and fail if the instance is readonly."""
@@ -141,10 +140,7 @@ class Storage(metaclass=StorageMeta):
except ValueError:
pass
- return "<{}(**{})>".format(
- self.__class__.__name__,
- {x: getattr(self, x) for x in self._repr_attributes},
- )
+ return f"<{self.__class__.__name__}(**{ ({x: getattr(self, x) for x in self._repr_attributes}) })>"
@abstractmethod
async def list(self) -> list[tuple]:
diff --git a/vdirsyncer/storage/dav.py b/vdirsyncer/storage/dav.py
index 6546322..4defb47 100644
--- a/vdirsyncer/storage/dav.py
+++ b/vdirsyncer/storage/dav.py
@@ -11,16 +11,16 @@ from inspect import signature
import aiohttp
import aiostream
+from vdirsyncer import exceptions
+from vdirsyncer import http
+from vdirsyncer import utils
from vdirsyncer.exceptions import Error
+from vdirsyncer.http import USERAGENT
+from vdirsyncer.http import prepare_auth
+from vdirsyncer.http import prepare_client_cert
+from vdirsyncer.http import prepare_verify
from vdirsyncer.vobject import Item
-from .. import exceptions
-from .. import http
-from .. import utils
-from ..http import USERAGENT
-from ..http import prepare_auth
-from ..http import prepare_client_cert
-from ..http import prepare_verify
from .base import Storage
from .base import normalize_meta_value
@@ -321,7 +321,7 @@ class Discover:
class CalDiscover(Discover):
_namespace = "urn:ietf:params:xml:ns:caldav"
- _resourcetype = "{%s}calendar" % _namespace
+ _resourcetype = f"{{{_namespace}}}calendar"
_homeset_xml = b"""
@@ -329,13 +329,13 @@ class CalDiscover(Discover):
"""
- _homeset_tag = "{%s}calendar-home-set" % _namespace
+ _homeset_tag = f"{{{_namespace}}}calendar-home-set"
_well_known_uri = "/.well-known/caldav"
class CardDiscover(Discover):
_namespace = "urn:ietf:params:xml:ns:carddav"
- _resourcetype: str | None = "{%s}addressbook" % _namespace
+ _resourcetype: str | None = f"{{{_namespace}}}addressbook"
_homeset_xml = b"""
@@ -343,7 +343,7 @@ class CardDiscover(Discover):
"""
- _homeset_tag = "{%s}addressbook-home-set" % _namespace
+ _homeset_tag = f"{{{_namespace}}}addressbook-home-set"
_well_known_uri = "/.well-known/carddav"
diff --git a/vdirsyncer/storage/filesystem.py b/vdirsyncer/storage/filesystem.py
index 8785acc..bb91641 100644
--- a/vdirsyncer/storage/filesystem.py
+++ b/vdirsyncer/storage/filesystem.py
@@ -5,13 +5,14 @@ import logging
import os
import subprocess
-from .. import exceptions
-from ..utils import atomic_write
-from ..utils import checkdir
-from ..utils import expand_path
-from ..utils import generate_href
-from ..utils import get_etag_from_file
-from ..vobject import Item
+from vdirsyncer import exceptions
+from vdirsyncer.utils import atomic_write
+from vdirsyncer.utils import checkdir
+from vdirsyncer.utils import expand_path
+from vdirsyncer.utils import generate_href
+from vdirsyncer.utils import get_etag_from_file
+from vdirsyncer.vobject import Item
+
from .base import Storage
from .base import normalize_meta_value
diff --git a/vdirsyncer/storage/google.py b/vdirsyncer/storage/google.py
index 3109213..d7e44e0 100644
--- a/vdirsyncer/storage/google.py
+++ b/vdirsyncer/storage/google.py
@@ -12,11 +12,12 @@ from threading import Thread
import aiohttp
import click
-from .. import exceptions
-from ..utils import atomic_write
-from ..utils import checkdir
-from ..utils import expand_path
-from ..utils import open_graphical_browser
+from vdirsyncer import exceptions
+from vdirsyncer.utils import atomic_write
+from vdirsyncer.utils import checkdir
+from vdirsyncer.utils import expand_path
+from vdirsyncer.utils import open_graphical_browser
+
from . import base
from . import dav
from .google_helpers import _RedirectWSGIApp
diff --git a/vdirsyncer/storage/http.py b/vdirsyncer/storage/http.py
index 9c4ce40..7ce891b 100644
--- a/vdirsyncer/storage/http.py
+++ b/vdirsyncer/storage/http.py
@@ -6,14 +6,15 @@ import urllib.parse as urlparse
import aiohttp
-from .. import exceptions
-from ..http import USERAGENT
-from ..http import prepare_auth
-from ..http import prepare_client_cert
-from ..http import prepare_verify
-from ..http import request
-from ..vobject import Item
-from ..vobject import split_collection
+from vdirsyncer import exceptions
+from vdirsyncer.http import USERAGENT
+from vdirsyncer.http import prepare_auth
+from vdirsyncer.http import prepare_client_cert
+from vdirsyncer.http import prepare_verify
+from vdirsyncer.http import request
+from vdirsyncer.vobject import Item
+from vdirsyncer.vobject import split_collection
+
from .base import Storage
logger = logging.getLogger(__name__)
diff --git a/vdirsyncer/storage/memory.py b/vdirsyncer/storage/memory.py
index d872312..9a8b869 100644
--- a/vdirsyncer/storage/memory.py
+++ b/vdirsyncer/storage/memory.py
@@ -2,7 +2,8 @@ from __future__ import annotations
import random
-from .. import exceptions
+from vdirsyncer import exceptions
+
from .base import Storage
from .base import normalize_meta_value
diff --git a/vdirsyncer/storage/singlefile.py b/vdirsyncer/storage/singlefile.py
index 405e7cb..5dafbcb 100644
--- a/vdirsyncer/storage/singlefile.py
+++ b/vdirsyncer/storage/singlefile.py
@@ -8,15 +8,16 @@ import logging
import os
from typing import Iterable
-from .. import exceptions
-from ..utils import atomic_write
-from ..utils import checkfile
-from ..utils import expand_path
-from ..utils import get_etag_from_file
-from ..utils import uniq
-from ..vobject import Item
-from ..vobject import join_collection
-from ..vobject import split_collection
+from vdirsyncer import exceptions
+from vdirsyncer.utils import atomic_write
+from vdirsyncer.utils import checkfile
+from vdirsyncer.utils import expand_path
+from vdirsyncer.utils import get_etag_from_file
+from vdirsyncer.utils import uniq
+from vdirsyncer.vobject import Item
+from vdirsyncer.vobject import join_collection
+from vdirsyncer.vobject import split_collection
+
from .base import Storage
logger = logging.getLogger(__name__)
diff --git a/vdirsyncer/sync/__init__.py b/vdirsyncer/sync/__init__.py
index 25b46a3..8b24219 100644
--- a/vdirsyncer/sync/__init__.py
+++ b/vdirsyncer/sync/__init__.py
@@ -16,11 +16,11 @@ import contextlib
import itertools
import logging
+from vdirsyncer.exceptions import UserError
from vdirsyncer.storage.base import Storage
+from vdirsyncer.utils import uniq
from vdirsyncer.vobject import Item
-from ..exceptions import UserError
-from ..utils import uniq
from .exceptions import BothReadOnly
from .exceptions import IdentAlreadyExists
from .exceptions import PartialSync
diff --git a/vdirsyncer/sync/exceptions.py b/vdirsyncer/sync/exceptions.py
index 9fa5bf2..dfe5fbc 100644
--- a/vdirsyncer/sync/exceptions.py
+++ b/vdirsyncer/sync/exceptions.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from .. import exceptions
+from vdirsyncer import exceptions
class SyncError(exceptions.Error):