From 8b063c39cb3e26a2beef5b6beed7e99c9e9641ac Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 13 Feb 2025 09:00:58 +0100 Subject: [PATCH] atomicwrites: remove dependency on abandoned library --- .builds/tests-archlinux.yml | 1 - .pre-commit-config.yaml | 1 - CHANGELOG.rst | 5 +++++ setup.py | 2 -- vdirsyncer/cli/utils.py | 2 +- vdirsyncer/storage/filesystem.py | 3 +-- vdirsyncer/storage/google.py | 2 +- vdirsyncer/storage/singlefile.py | 3 +-- vdirsyncer/utils.py | 26 ++++++++++++++++++++++++++ 9 files changed, 35 insertions(+), 10 deletions(-) diff --git a/.builds/tests-archlinux.yml b/.builds/tests-archlinux.yml index b11fe30..494f6c7 100644 --- a/.builds/tests-archlinux.yml +++ b/.builds/tests-archlinux.yml @@ -10,7 +10,6 @@ packages: - python-installer - python-setuptools-scm # Runtime dependencies: - - python-atomicwrites - python-click - python-click-log - python-click-threading diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7304056..6beb3a4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,6 @@ repos: - types-setuptools - types-docutils - types-requests - - types-atomicwrites - repo: https://github.com/charliermarsh/ruff-pre-commit rev: 'v0.2.2' hooks: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b43a33d..bc32cfd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,11 @@ Package maintainers and users who have to manually update their installation may want to subscribe to `GitHub's tag feed `_. +Version 0.19.4 +============== + +- Remove dependency on abandoned ``atomicwrites`` library. + Version 0.19.3 ============== diff --git a/setup.py b/setup.py index 47f45a4..30cdc9c 100644 --- a/setup.py +++ b/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.2,<4.0.0", "aiostream>=0.4.3,<0.5.0", ] diff --git a/vdirsyncer/cli/utils.py b/vdirsyncer/cli/utils.py index 428a9c9..97f48ed 100644 --- a/vdirsyncer/cli/utils.py +++ b/vdirsyncer/cli/utils.py @@ -10,7 +10,6 @@ from typing import Any import aiohttp import click -from atomicwrites import atomic_write from .. import BUGTRACKER_HOME from .. import DOCS_HOME @@ -21,6 +20,7 @@ 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 . import cli_logger diff --git a/vdirsyncer/storage/filesystem.py b/vdirsyncer/storage/filesystem.py index ec0ab52..8785acc 100644 --- a/vdirsyncer/storage/filesystem.py +++ b/vdirsyncer/storage/filesystem.py @@ -5,9 +5,8 @@ import logging 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 diff --git a/vdirsyncer/storage/google.py b/vdirsyncer/storage/google.py index 93b7848..ed496a0 100644 --- a/vdirsyncer/storage/google.py +++ b/vdirsyncer/storage/google.py @@ -11,9 +11,9 @@ from threading import Thread 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 diff --git a/vdirsyncer/storage/singlefile.py b/vdirsyncer/storage/singlefile.py index 9827632..41e7e33 100644 --- a/vdirsyncer/storage/singlefile.py +++ b/vdirsyncer/storage/singlefile.py @@ -8,9 +8,8 @@ import logging 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 diff --git a/vdirsyncer/utils.py b/vdirsyncer/utils.py index 2e0fd9c..657d2d6 100644 --- a/vdirsyncer/utils.py +++ b/vdirsyncer/utils.py @@ -1,8 +1,10 @@ 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)