From 7506d5f06c5ddcf1851408cbb22f1cdce5353050 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Mon, 28 Mar 2022 14:40:31 +1000 Subject: [PATCH] Fall back on regular deletion when trash folder unavailable https://github.com/ankitects/anki/commit/aa0cac1ed3e117ae2d5840e404b55811e3a7449d#commitcomment-69668166 --- qt/aqt/addons.py | 5 +++-- qt/aqt/profiles.py | 15 ++++++--------- qt/aqt/utils.py | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index fcc7c8159..b05778111 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -12,6 +12,7 @@ from collections import defaultdict from concurrent.futures import Future from dataclasses import dataclass from datetime import datetime +from pathlib import Path from typing import IO, Any, Callable, Iterable, Union from urllib.parse import parse_qs, urlparse from zipfile import ZipFile @@ -20,7 +21,6 @@ import jsonschema import markdown from jsonschema.exceptions import ValidationError from markdown.extensions import md_in_html -from send2trash import send2trash import anki import anki.utils @@ -42,6 +42,7 @@ from aqt.utils import ( restoreSplitter, saveGeom, saveSplitter, + send_to_trash, showInfo, showWarning, tooltip, @@ -452,7 +453,7 @@ class AddonManager: # true on success def deleteAddon(self, module: str) -> bool: try: - send2trash(self.addonsFolder(module)) + send_to_trash(Path(self.addonsFolder(module))) return True except OSError as e: showWarning( diff --git a/qt/aqt/profiles.py b/qt/aqt/profiles.py index 2ef8821d4..8f09c3253 100644 --- a/qt/aqt/profiles.py +++ b/qt/aqt/profiles.py @@ -9,10 +9,9 @@ import random import shutil import traceback from enum import Enum +from pathlib import Path from typing import Any -from send2trash import send2trash - import anki.lang import aqt.forms import aqt.sound @@ -24,7 +23,7 @@ from anki.utils import int_time, is_mac, is_win, point_version from aqt import appHelpSite from aqt.qt import * from aqt.theme import Theme -from aqt.utils import disable_help_button, showWarning, tr +from aqt.utils import disable_help_button, send_to_trash, showWarning, tr # Profile handling ########################################################################## @@ -233,16 +232,14 @@ class ProfileManager: self.db.commit() def remove(self, name: str) -> None: - p = self.profileFolder() - if os.path.exists(p): - send2trash(p) + path = self.profileFolder(create=False) + send_to_trash(Path(path)) self.db.execute("delete from profiles where name = ?", name) self.db.commit() def trashCollection(self) -> None: - p = self.collectionPath() - if os.path.exists(p): - send2trash(p) + path = self.collectionPath() + send_to_trash(Path(path)) def rename(self, name: str) -> None: oldName = self.name diff --git a/qt/aqt/utils.py b/qt/aqt/utils.py index 88dfc5764..52a270970 100644 --- a/qt/aqt/utils.py +++ b/qt/aqt/utils.py @@ -4,11 +4,15 @@ from __future__ import annotations import os import re +import shutil import subprocess import sys from functools import wraps +from pathlib import Path from typing import TYPE_CHECKING, Any, Literal, Sequence, no_type_check +from send2trash import send2trash + import aqt from anki._legacy import DeprecatedNamesMixinForModule from anki.collection import Collection, HelpPage @@ -703,6 +707,21 @@ def current_window() -> QWidget | None: return None +def send_to_trash(path: Path) -> None: + "Place file/folder in recyling bin, or delete permanently on failure." + if not path.exists(): + return + try: + send2trash(path) + except Exception as exc: + # Linux users may not have a trash folder set up + print("trash failure:", path, exc) + if path.is_dir: + shutil.rmtree(path) + else: + path.unlink() + + # Tooltips ######################################################################