mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Add new error variant to frontend; ensure errors are mapped appropriately
This commit is contained in:
parent
bdfa8387a5
commit
f8ed4d89ba
9 changed files with 29 additions and 7 deletions
|
@ -58,6 +58,8 @@ message BackendError {
|
|||
SEARCH_ERROR = 14;
|
||||
CUSTOM_STUDY_ERROR = 15;
|
||||
IMPORT_ERROR = 16;
|
||||
// Collection imported, but media import failed.
|
||||
IMPORT_MEDIA_ERROR = 17;
|
||||
}
|
||||
|
||||
// localized error description suitable for displaying to the user
|
||||
|
|
|
@ -33,8 +33,8 @@ message PackageMetadata {
|
|||
VERSION_LEGACY_1 = 1;
|
||||
// When `meta` missing, and collection.anki21 file present.
|
||||
VERSION_LEGACY_2 = 2;
|
||||
/// Implies MediaEntry media map, and zstd compression.
|
||||
/// collection.21b file
|
||||
// Implies MediaEntry media map, and zstd compression.
|
||||
// collection.21b file
|
||||
VERSION_LATEST = 3;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ from ..errors import (
|
|||
DBError,
|
||||
ExistsError,
|
||||
FilteredDeckError,
|
||||
ImportMediaError,
|
||||
Interrupted,
|
||||
InvalidInput,
|
||||
LocalizedError,
|
||||
|
@ -219,6 +220,9 @@ def backend_exception_to_pylib(err: backend_pb2.BackendError) -> Exception:
|
|||
elif val == kind.CUSTOM_STUDY_ERROR:
|
||||
return CustomStudyError(err.localized)
|
||||
|
||||
elif val == kind.IMPORT_MEDIA_ERROR:
|
||||
return ImportMediaError(err.localized)
|
||||
|
||||
else:
|
||||
# sadly we can't do exhaustiveness checking on protobuf enums
|
||||
# assert_exhaustive(val)
|
||||
|
|
|
@ -80,6 +80,10 @@ class AbortSchemaModification(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class ImportMediaError(LocalizedError):
|
||||
pass
|
||||
|
||||
|
||||
# legacy
|
||||
DeckRenameError = FilteredDeckError
|
||||
AnkiError = AbortSchemaModification
|
||||
|
|
|
@ -11,7 +11,7 @@ import anki.importing as importing
|
|||
import aqt.deckchooser
|
||||
import aqt.forms
|
||||
import aqt.modelchooser
|
||||
from anki.errors import Interrupted
|
||||
from anki.errors import ImportMediaError, Interrupted
|
||||
from anki.importing.anki2 import V2ImportIntoV1
|
||||
from anki.importing.apkg import AnkiPackageImporter
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
|
@ -457,7 +457,8 @@ def replace_with_apkg(
|
|||
mw: aqt.AnkiQt, filename: str, callback: Callable[[bool], None]
|
||||
) -> None:
|
||||
"""Tries to replace the provided collection with the provided backup,
|
||||
then calls the callback. True if success.
|
||||
then calls the callback. True if collection file was imported (even
|
||||
if media failed).
|
||||
"""
|
||||
dialog = mw.progress.start(immediate=True)
|
||||
timer = QTimer()
|
||||
|
@ -495,7 +496,8 @@ def replace_with_apkg(
|
|||
except Exception as error:
|
||||
if not isinstance(error, Interrupted):
|
||||
showWarning(str(error))
|
||||
callback(False)
|
||||
collection_file_imported = isinstance(error, ImportMediaError)
|
||||
callback(collection_file_imported)
|
||||
else:
|
||||
callback(True)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use crate::{
|
||||
backend_proto as pb,
|
||||
backend_proto::backend_error::Kind,
|
||||
error::{AnkiError, SyncErrorKind},
|
||||
error::{AnkiError, ImportError, SyncErrorKind},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,7 @@ impl AnkiError {
|
|||
AnkiError::MultipleNotetypesSelected => Kind::InvalidInput,
|
||||
AnkiError::DatabaseCheckRequired => Kind::InvalidInput,
|
||||
AnkiError::CustomStudyError(_) => Kind::CustomStudyError,
|
||||
AnkiError::ImportError(ImportError::MediaImportFailed(_)) => Kind::ImportMediaError,
|
||||
AnkiError::ImportError(_) => Kind::ImportError,
|
||||
AnkiError::FileIoError(_) => Kind::IoError,
|
||||
AnkiError::MediaCheckRequired => Kind::InvalidInput,
|
||||
|
|
|
@ -39,6 +39,7 @@ impl ImportExportService for Backend {
|
|||
&input.backup_path,
|
||||
&input.col_path,
|
||||
&input.media_folder,
|
||||
&self.tr,
|
||||
self.import_progress_fn(),
|
||||
)
|
||||
.map(Into::into)
|
||||
|
|
|
@ -57,6 +57,7 @@ pub fn import_colpkg(
|
|||
colpkg_path: &str,
|
||||
target_col_path: &str,
|
||||
target_media_folder: &str,
|
||||
tr: &I18n,
|
||||
mut progress_fn: impl FnMut(ImportProgress) -> Result<()>,
|
||||
) -> Result<()> {
|
||||
progress_fn(ImportProgress::Collection)?;
|
||||
|
@ -76,7 +77,12 @@ pub fn import_colpkg(
|
|||
progress_fn(ImportProgress::Collection)?;
|
||||
|
||||
let media_folder = Path::new(target_media_folder);
|
||||
let media_import_result = restore_media(&meta, progress_fn, &mut archive, media_folder);
|
||||
let media_import_result = restore_media(&meta, progress_fn, &mut archive, media_folder)
|
||||
.map_err(|err| {
|
||||
AnkiError::ImportError(ImportError::MediaImportFailed(
|
||||
err.localized_description(tr),
|
||||
))
|
||||
});
|
||||
|
||||
// Proceed with replacing collection, regardless of media import result
|
||||
tempfile.as_file().sync_all()?;
|
||||
|
|
|
@ -40,6 +40,7 @@ fn roundtrip() -> Result<()> {
|
|||
for (legacy, name) in [(true, "legacy"), (false, "v3")] {
|
||||
// export to a file
|
||||
let col = collection_with_media(dir, name)?;
|
||||
let tr = col.tr.clone();
|
||||
let colpkg_name = dir.join(format!("{name}.colpkg"));
|
||||
col.export_colpkg(&colpkg_name, true, legacy, |_| ())?;
|
||||
// import into a new collection
|
||||
|
@ -52,6 +53,7 @@ fn roundtrip() -> Result<()> {
|
|||
&colpkg_name.to_string_lossy(),
|
||||
&anki2_name,
|
||||
import_media_dir.to_str().unwrap(),
|
||||
&tr,
|
||||
|_| Ok(()),
|
||||
)?;
|
||||
// confirm collection imported
|
||||
|
|
Loading…
Reference in a new issue