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