Merge pull request #1040 from RumovZ/deck-name-err

Catch deck rename errors and localise warnings
This commit is contained in:
Damien Elmes 2021-03-01 09:40:55 +10:00 committed by GitHub
commit 5564fd9e13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 45 additions and 34 deletions

View File

@ -1,3 +1,4 @@
errors-invalid-input-empty = Invalid input. errors-invalid-input-empty = Invalid input.
errors-invalid-input-details = Invalid input: { $details } errors-invalid-input-details = Invalid input: { $details }
errors-parse-number-fail = A number was invalid or out of range. errors-parse-number-fail = A number was invalid or out of range.
errors-filtered-parent-deck = Invalid deck name: Filtered decks cannot be parent decks.

View File

@ -12,7 +12,7 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union
import anki # pylint: disable=unused-import import anki # pylint: disable=unused-import
import anki._backend.backend_pb2 as _pb import anki._backend.backend_pb2 as _pb
from anki.consts import * from anki.consts import *
from anki.errors import DeckIsFilteredError, DeckRenameError, NotFoundError from anki.errors import NotFoundError
from anki.utils import from_json_bytes, ids2str, intTime, to_json_bytes from anki.utils import from_json_bytes, ids2str, intTime, to_json_bytes
# public exports # public exports
@ -246,12 +246,9 @@ class DeckManager:
def update(self, g: Deck, preserve_usn: bool = True) -> None: def update(self, g: Deck, preserve_usn: bool = True) -> None:
"Add or update an existing deck. Used for syncing and merging." "Add or update an existing deck. Used for syncing and merging."
try: g["id"] = self.col._backend.add_or_update_deck_legacy(
g["id"] = self.col._backend.add_or_update_deck_legacy( deck=to_json_bytes(g), preserve_usn_and_mtime=preserve_usn
deck=to_json_bytes(g), preserve_usn_and_mtime=preserve_usn )
)
except DeckIsFilteredError as exc:
raise DeckRenameError("deck was filtered") from exc
def rename(self, g: Deck, newName: str) -> None: def rename(self, g: Deck, newName: str) -> None:
"Rename deck prefix to NAME if not exists. Updates children." "Rename deck prefix to NAME if not exists. Updates children."

View File

@ -47,7 +47,15 @@ class ExistsError(Exception):
pass pass
class DeckIsFilteredError(Exception): class DeckRenameError(Exception):
"""Legacy error, use DeckIsFilteredError instead."""
def __init__(self, description: str, *args: object) -> None:
super().__init__(description, *args)
self.description = description
class DeckIsFilteredError(StringError, DeckRenameError):
pass pass
@ -78,7 +86,7 @@ def backend_exception_to_pylib(err: _pb.BackendError) -> Exception:
elif val == "exists": elif val == "exists":
return ExistsError() return ExistsError()
elif val == "deck_is_filtered": elif val == "deck_is_filtered":
return DeckIsFilteredError() return DeckIsFilteredError(err.localized)
elif val == "proto_error": elif val == "proto_error":
return StringError(err.localized) return StringError(err.localized)
else: else:
@ -95,12 +103,3 @@ class AnkiError(Exception):
def __str__(self) -> str: def __str__(self) -> str:
return self.type return self.type
class DeckRenameError(Exception):
def __init__(self, description: str) -> None:
super().__init__()
self.description = description
def __str__(self) -> str:
return f"Couldn't rename deck: {self.description}"

View File

@ -9,7 +9,7 @@ from typing import Any
import aqt import aqt
from anki.decks import DeckTreeNode from anki.decks import DeckTreeNode
from anki.errors import DeckRenameError from anki.errors import DeckIsFilteredError
from anki.utils import intTime from anki.utils import intTime
from aqt import AnkiQt, gui_hooks from aqt import AnkiQt, gui_hooks
from aqt.qt import * from aqt.qt import *
@ -88,11 +88,7 @@ class DeckBrowser:
elif cmd == "import": elif cmd == "import":
self.mw.onImport() self.mw.onImport()
elif cmd == "create": elif cmd == "create":
deck = getOnlyText(tr(TR.DECKS_NAME_FOR_DECK)) self._on_create()
if deck:
self.mw.col.decks.id(deck)
gui_hooks.sidebar_should_refresh_decks()
self.refresh()
elif cmd == "drag": elif cmd == "drag":
source, target = arg.split(",") source, target = arg.split(",")
self._handle_drag_and_drop(int(source), int(target or 0)) self._handle_drag_and_drop(int(source), int(target or 0))
@ -272,8 +268,8 @@ class DeckBrowser:
try: try:
self.mw.col.decks.rename(deck, newName) self.mw.col.decks.rename(deck, newName)
gui_hooks.sidebar_should_refresh_decks() gui_hooks.sidebar_should_refresh_decks()
except DeckRenameError as e: except DeckIsFilteredError as err:
showWarning(e.description) showWarning(str(err))
return return
self.show() self.show()
@ -352,6 +348,17 @@ class DeckBrowser:
def _onShared(self) -> None: def _onShared(self) -> None:
openLink(f"{aqt.appShared}decks/") openLink(f"{aqt.appShared}decks/")
def _on_create(self) -> None:
deck = getOnlyText(tr(TR.DECKS_NAME_FOR_DECK))
if deck:
try:
self.mw.col.decks.id(deck)
except DeckIsFilteredError as err:
showWarning(str(err))
return
gui_hooks.sidebar_should_refresh_decks()
self.refresh()
###################################################################### ######################################################################
def _v1_upgrade_message(self) -> str: def _v1_upgrade_message(self) -> str:

View File

@ -4,8 +4,8 @@ from typing import Callable, List, Optional, Tuple
import aqt import aqt
from anki.collection import SearchNode from anki.collection import SearchNode
from anki.decks import Deck, DeckRenameError from anki.decks import Deck
from anki.errors import InvalidInput from anki.errors import DeckIsFilteredError, InvalidInput
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from aqt import AnkiQt, colors, gui_hooks from aqt import AnkiQt, colors, gui_hooks
from aqt.qt import * from aqt.qt import *
@ -301,8 +301,8 @@ class DeckConf(QDialog):
self.saveConf() self.saveConf()
except InvalidInput as err: except InvalidInput as err:
show_invalid_search_error(err) show_invalid_search_error(err)
except DeckRenameError as err: except DeckIsFilteredError as err:
showWarning(err.description) showWarning(str(err))
else: else:
if not self.col.sched.rebuild_filtered_deck(self.deck["id"]): if not self.col.sched.rebuild_filtered_deck(self.deck["id"]):
if askUser(tr(TR.DECKS_THE_PROVIDED_SEARCH_DID_NOT_MATCH)): if askUser(tr(TR.DECKS_THE_PROVIDED_SEARCH_DID_NOT_MATCH)):

View File

@ -10,7 +10,7 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, cast
import aqt import aqt
from anki.collection import Config, SearchNode from anki.collection import Config, SearchNode
from anki.decks import DeckTreeNode from anki.decks import DeckTreeNode
from anki.errors import DeckRenameError, InvalidInput from anki.errors import DeckIsFilteredError, InvalidInput
from anki.tags import TagTreeNode from anki.tags import TagTreeNode
from anki.types import assert_exhaustive from anki.types import assert_exhaustive
from aqt import colors, gui_hooks from aqt import colors, gui_hooks
@ -988,8 +988,8 @@ class SidebarTreeView(QTreeView):
self.mw.checkpoint(tr(TR.ACTIONS_RENAME_DECK)) self.mw.checkpoint(tr(TR.ACTIONS_RENAME_DECK))
try: try:
self.mw.col.decks.rename(deck, new_name) self.mw.col.decks.rename(deck, new_name)
except DeckRenameError as e: except DeckIsFilteredError as err:
showWarning(e.description) showWarning(str(err))
return return
self.refresh() self.refresh()
self.mw.deckBrowser.refresh() self.mw.deckBrowser.refresh()

View File

@ -4,6 +4,7 @@
from typing import List, Optional from typing import List, Optional
import aqt import aqt
from anki.errors import DeckIsFilteredError
from aqt import gui_hooks from aqt import gui_hooks
from aqt.qt import * from aqt.qt import *
from aqt.utils import ( from aqt.utils import (
@ -17,6 +18,7 @@ from aqt.utils import (
saveGeom, saveGeom,
shortcut, shortcut,
showInfo, showInfo,
showWarning,
tr, tr,
) )
@ -162,7 +164,11 @@ class StudyDeck(QDialog):
n = getOnlyText(tr(TR.DECKS_NEW_DECK_NAME), default=default) n = getOnlyText(tr(TR.DECKS_NEW_DECK_NAME), default=default)
n = n.strip() n = n.strip()
if n: if n:
did = self.mw.col.decks.id(n) try:
did = self.mw.col.decks.id(n)
except DeckIsFilteredError as err:
showWarning(str(err))
return
# deck name may not be the same as user input. ex: ", :: # deck name may not be the same as user input. ex: ", ::
self.name = self.mw.col.decks.name(did) self.name = self.mw.col.decks.name(did)
# make sure we clean up reset hook when manually exiting # make sure we clean up reset hook when manually exiting

View File

@ -208,6 +208,7 @@ impl AnkiError {
} }
} }
AnkiError::ParseNumError => i18n.tr(TR::ErrorsParseNumberFail).into(), AnkiError::ParseNumError => i18n.tr(TR::ErrorsParseNumberFail).into(),
AnkiError::DeckIsFiltered => i18n.tr(TR::ErrorsFilteredParentDeck).into(),
_ => format!("{:?}", self), _ => format!("{:?}", self),
} }
} }