Obtained from: https://github.com/pimutils/vdirsyncer/commit/8b063c39cb3e26a2beef5b6beed7e99c9e9641ac --- setup.py.orig 2024-09-11 15:26:58 UTC +++ setup.py @@ -16,8 +16,6 @@ requirements = [ "click>=5.0,<9.0", "click-log>=0.3.0, <0.5.0", "requests >=2.20.0", - # https://github.com/untitaker/python-atomicwrites/commit/4d12f23227b6a944ab1d99c507a69fdbc7c9ed6d # noqa - "atomicwrites>=0.1.7", "aiohttp>=3.8.0,<4.0.0", "aiostream>=0.4.3,<0.5.0", ] --- vdirsyncer/cli/utils.py.orig 2024-09-11 15:26:58 UTC +++ vdirsyncer/cli/utils.py @@ -10,7 +10,6 @@ import click import aiohttp import click -from atomicwrites import atomic_write from .. import BUGTRACKER_HOME from .. import DOCS_HOME @@ -21,6 +20,7 @@ from ..sync.status import SqliteStatus 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 . import cli_logger --- vdirsyncer/storage/filesystem.py.orig 2024-09-11 15:26:58 UTC +++ vdirsyncer/storage/filesystem.py @@ -5,9 +5,8 @@ import subprocess import os import subprocess -from atomicwrites import atomic_write - from .. import exceptions +from ..utils import atomic_write from ..utils import checkdir from ..utils import expand_path from ..utils import generate_href --- vdirsyncer/storage/google.py.orig 2024-09-11 15:26:58 UTC +++ vdirsyncer/storage/google.py @@ -11,9 +11,9 @@ import click import aiohttp import click -from atomicwrites import atomic_write from .. import exceptions +from ..utils import atomic_write from ..utils import checkdir from ..utils import expand_path from ..utils import open_graphical_browser --- vdirsyncer/storage/singlefile.py.orig 2024-09-11 15:26:58 UTC +++ vdirsyncer/storage/singlefile.py @@ -8,9 +8,8 @@ from typing import Iterable import os from typing import Iterable -from atomicwrites import atomic_write - from .. import exceptions +from ..utils import atomic_write from ..utils import checkfile from ..utils import expand_path from ..utils import get_etag_from_file --- vdirsyncer/utils.py.orig 2024-09-11 15:26:58 UTC +++ vdirsyncer/utils.py @@ -1,8 +1,10 @@ from __future__ import annotations from __future__ import annotations +import contextlib import functools import os import sys +import tempfile import uuid from inspect import getfullargspec from typing import Callable @@ -220,3 +222,27 @@ def open_graphical_browser(url, new=0, autoraise=True) return raise RuntimeError("No graphical browser found. Please open the URL " "manually.") + + +@contextlib.contextmanager +def atomic_write(dest, mode="wb", overwrite=False): + if "w" not in mode: + raise RuntimeError("`atomic_write` requires write access") + + fd, src = tempfile.mkstemp(prefix=os.path.basename(dest), dir=os.path.dirname(dest)) + file = os.fdopen(fd, mode=mode) + + try: + yield file + except Exception: + os.unlink(src) + raise + else: + file.flush() + file.close() + + if overwrite: + os.rename(src, dest) + else: + os.link(src, dest) + os.unlink(src)