mirror of
https://github.com/ankitects/anki.git
synced 2025-12-10 13:26:56 -05:00
return a localized error for all error kinds
some errors are not yet localized, but now the Python code doesn't need to think about which property to use
This commit is contained in:
parent
bec4699e27
commit
644670d0d6
5 changed files with 40 additions and 57 deletions
|
|
@ -73,13 +73,16 @@ message BackendOutput {
|
|||
}
|
||||
|
||||
message BackendError {
|
||||
// localized error description suitable for displaying to the user
|
||||
string localized = 1;
|
||||
// error specifics
|
||||
oneof value {
|
||||
StringError invalid_input = 1;
|
||||
TemplateParseError template_parse = 2;
|
||||
StringError io_error = 3;
|
||||
StringError db_error = 4;
|
||||
NetworkError network_error = 5;
|
||||
SyncError sync_error = 6;
|
||||
StringError invalid_input = 2;
|
||||
StringError template_parse = 3;
|
||||
StringError io_error = 4;
|
||||
StringError db_error = 5;
|
||||
NetworkError network_error = 6;
|
||||
SyncError sync_error = 7;
|
||||
// user interrupted operation
|
||||
Empty interrupted = 8;
|
||||
}
|
||||
|
|
@ -96,10 +99,6 @@ message StringError {
|
|||
string info = 1;
|
||||
}
|
||||
|
||||
message TemplateParseError {
|
||||
string info = 1;
|
||||
}
|
||||
|
||||
message NetworkError {
|
||||
string info = 1;
|
||||
enum NetworkErrorKind {
|
||||
|
|
@ -109,7 +108,6 @@ message NetworkError {
|
|||
PROXY_AUTH = 3;
|
||||
}
|
||||
NetworkErrorKind kind = 2;
|
||||
string localized = 3;
|
||||
}
|
||||
|
||||
message SyncError {
|
||||
|
|
@ -125,7 +123,6 @@ message SyncError {
|
|||
RESYNC_REQUIRED = 7;
|
||||
}
|
||||
SyncErrorKind kind = 2;
|
||||
string localized = 3;
|
||||
}
|
||||
|
||||
message MediaSyncProgress {
|
||||
|
|
|
|||
|
|
@ -32,14 +32,17 @@ class StringError(Exception):
|
|||
|
||||
|
||||
NetworkErrorKind = pb.NetworkError.NetworkErrorKind
|
||||
SyncErrorKind = pb.SyncError.SyncErrorKind
|
||||
|
||||
|
||||
class NetworkError(StringError):
|
||||
def kind(self) -> NetworkErrorKind:
|
||||
return self.args[1]
|
||||
|
||||
def localized(self) -> str:
|
||||
return self.args[2]
|
||||
|
||||
class SyncError(StringError):
|
||||
def kind(self) -> SyncErrorKind:
|
||||
return self.args[1]
|
||||
|
||||
|
||||
class IOError(StringError):
|
||||
|
|
@ -54,35 +57,22 @@ class TemplateError(StringError):
|
|||
pass
|
||||
|
||||
|
||||
SyncErrorKind = pb.SyncError.SyncErrorKind
|
||||
|
||||
|
||||
class SyncError(StringError):
|
||||
def kind(self) -> SyncErrorKind:
|
||||
return self.args[1]
|
||||
|
||||
def localized(self) -> str:
|
||||
return self.args[2]
|
||||
|
||||
|
||||
def proto_exception_to_native(err: pb.BackendError) -> Exception:
|
||||
val = err.WhichOneof("value")
|
||||
if val == "interrupted":
|
||||
return Interrupted()
|
||||
elif val == "network_error":
|
||||
e = err.network_error
|
||||
return NetworkError(e.info, e.kind, e.localized)
|
||||
elif val == "io_error":
|
||||
return IOError(err.io_error.info)
|
||||
elif val == "db_error":
|
||||
return DBError(err.db_error.info)
|
||||
elif val == "template_parse":
|
||||
return TemplateError(err.template_parse.info)
|
||||
elif val == "invalid_input":
|
||||
return StringError(err.invalid_input.info)
|
||||
return NetworkError(err.localized, err.network_error.kind)
|
||||
elif val == "sync_error":
|
||||
e2 = err.sync_error
|
||||
return SyncError(e2.info, e2.kind, e2.localized)
|
||||
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 StringError(err.localized)
|
||||
else:
|
||||
assert_impossible_literal(val)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@ from anki.rsbackend import (
|
|||
FString,
|
||||
Interrupted,
|
||||
MediaSyncProgress,
|
||||
NetworkError,
|
||||
Progress,
|
||||
ProgressKind,
|
||||
SyncError,
|
||||
)
|
||||
from anki.types import assert_impossible
|
||||
from anki.utils import intTime
|
||||
|
|
@ -109,13 +107,7 @@ class MediaSyncer:
|
|||
return
|
||||
|
||||
self._log_and_notify(tr(FString.SYNC_MEDIA_FAILED))
|
||||
if isinstance(exc, SyncError):
|
||||
showWarning(exc.localized())
|
||||
elif isinstance(exc, NetworkError):
|
||||
msg = exc.localized()
|
||||
msg += "\n\n" + tr(FString.NETWORK_DETAILS, details=str(exc))
|
||||
else:
|
||||
raise exc
|
||||
showWarning(str(exc))
|
||||
|
||||
def entries(self) -> List[LogEntryWithTime]:
|
||||
return self._log
|
||||
|
|
|
|||
|
|
@ -45,23 +45,24 @@ fn anki_error_to_proto_error(err: AnkiError, i18n: &I18n) -> pb::BackendError {
|
|||
let localized = err.localized_description(i18n);
|
||||
let value = match err {
|
||||
AnkiError::InvalidInput { info } => V::InvalidInput(pb::StringError { info }),
|
||||
AnkiError::TemplateError { info } => V::TemplateParse(pb::TemplateParseError { info }),
|
||||
AnkiError::TemplateError { info } => V::TemplateParse(pb::StringError { info }),
|
||||
AnkiError::IOError { info } => V::IoError(pb::StringError { info }),
|
||||
AnkiError::DBError { info } => V::DbError(pb::StringError { info }),
|
||||
AnkiError::NetworkError { info, kind } => V::NetworkError(pb::NetworkError {
|
||||
info,
|
||||
kind: kind.into(),
|
||||
localized,
|
||||
}),
|
||||
AnkiError::SyncError { info, kind } => V::SyncError(pb::SyncError {
|
||||
info,
|
||||
kind: kind.into(),
|
||||
localized,
|
||||
}),
|
||||
AnkiError::Interrupted => V::Interrupted(Empty {}),
|
||||
};
|
||||
|
||||
pb::BackendError { value: Some(value) }
|
||||
pb::BackendError {
|
||||
value: Some(value),
|
||||
localized,
|
||||
}
|
||||
}
|
||||
|
||||
// Convert an Anki error to a protobuf output.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use crate::i18n::{FString, I18n};
|
||||
use crate::i18n::{tr_strs, FString, I18n};
|
||||
pub use failure::{Error, Fail};
|
||||
use reqwest::StatusCode;
|
||||
use std::io;
|
||||
|
|
@ -67,13 +67,16 @@ impl AnkiError {
|
|||
SyncErrorKind::ResyncRequired => i18n.tr(FString::SyncResyncRequired),
|
||||
}
|
||||
.into(),
|
||||
AnkiError::NetworkError { kind, .. } => match kind {
|
||||
NetworkErrorKind::Offline => i18n.tr(FString::NetworkOffline),
|
||||
NetworkErrorKind::Timeout => i18n.tr(FString::NetworkTimeout),
|
||||
NetworkErrorKind::ProxyAuth => i18n.tr(FString::NetworkProxyAuth),
|
||||
NetworkErrorKind::Other => i18n.tr(FString::NetworkOther),
|
||||
AnkiError::NetworkError { kind, info } => {
|
||||
let summary = match kind {
|
||||
NetworkErrorKind::Offline => i18n.tr(FString::NetworkOffline),
|
||||
NetworkErrorKind::Timeout => i18n.tr(FString::NetworkTimeout),
|
||||
NetworkErrorKind::ProxyAuth => i18n.tr(FString::NetworkProxyAuth),
|
||||
NetworkErrorKind::Other => i18n.tr(FString::NetworkOther),
|
||||
};
|
||||
let details = i18n.trn(FString::NetworkDetails, tr_strs!["details"=>info]);
|
||||
format!("{}\n{}", summary, details)
|
||||
}
|
||||
.into(),
|
||||
_ => "".into(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue