Anki/pylib/anki/errors.py
Damien Elmes 9d853bbb03 start work on more clearly defining backend/protobuf boundaries
- anki._backend stores the protobuf files and rsbackend.py code
- pylib modules import protobuf messages directly from the
_pb2 files, and explicitly export any will be returned or consumed
by public pylib functions, so that calling code can import from pylib
- the "rsbackend" no longer imports and re-exports protobuf messages
- pylib can just consume them directly.
- move errors to errors.py

Still todo:

- rsbridge
- finishing the work on rsbackend, and check what we need to add
back to the original file location to avoid breaking add-ons
2021-01-31 18:55:45 +10:00

110 lines
2.5 KiB
Python

# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from typing import Any
import anki._backend.backend_pb2 as _pb
# fixme: notfounderror etc need to be in rsbackend.py
class StringError(Exception):
def __str__(self) -> str:
return self.args[0] # pylint: disable=unsubscriptable-object
class Interrupted(Exception):
pass
class NetworkError(StringError):
pass
class SyncError(StringError):
# pylint: disable=no-member
def is_auth_error(self) -> bool:
return self.args[1] == _pb.SyncError.SyncErrorKind.AUTH_FAILED
class IOError(StringError):
pass
class DBError(StringError):
pass
class TemplateError(StringError):
pass
class NotFoundError(Exception):
pass
class ExistsError(Exception):
pass
class DeckIsFilteredError(Exception):
pass
class InvalidInput(StringError):
pass
def backend_exception_to_pylib(err: _pb.BackendError) -> Exception:
val = err.WhichOneof("value")
if val == "interrupted":
return Interrupted()
elif val == "network_error":
return NetworkError(err.localized, err.network_error.kind)
elif val == "sync_error":
return SyncError(err.localized, err.sync_error.kind)
elif val == "io_error":
return IOError(err.localized)
elif val == "db_error":
return DBError(err.localized)
elif val == "template_parse":
return TemplateError(err.localized)
elif val == "invalid_input":
return InvalidInput(err.localized)
elif val == "json_error":
return StringError(err.localized)
elif val == "not_found_error":
return NotFoundError()
elif val == "exists":
return ExistsError()
elif val == "deck_is_filtered":
return DeckIsFilteredError()
elif val == "proto_error":
return StringError(err.localized)
else:
print("unhandled error type:", val)
return StringError(err.localized)
class AnkiError(Exception):
def __init__(self, type, **data) -> None:
super().__init__()
self.type = type
self.data = data
def __str__(self) -> Any:
m = self.type
if self.data:
m += ": %s" % repr(self.data)
return m
class DeckRenameError(Exception):
def __init__(self, description: str) -> None:
super().__init__()
self.description = description
def __str__(self):
return "Couldn't rename deck: " + self.description