nest progress messages and remove Python wrapper class

The progress messages are only really intended to be consumed by Anki.
If consumption by add-ons was expected, we'd be better off keeping the
wrapper, as the API for oneofs in Python is quite awkward to use.
This commit is contained in:
Damien Elmes 2021-02-08 16:40:27 +10:00
parent f434cff36f
commit c23b01978d
7 changed files with 58 additions and 112 deletions

View file

@ -4,7 +4,6 @@
from __future__ import annotations
import copy
import enum
import os
import pprint
import re
@ -12,7 +11,6 @@ import sys
import time
import traceback
import weakref
from dataclasses import dataclass
from typing import Any, List, Optional, Sequence, Tuple, Union
import anki._backend.backend_pb2 as _pb
@ -46,10 +44,7 @@ from anki.utils import (
# public exports
SearchTerm = _pb.SearchTerm
MediaSyncProgress = _pb.MediaSyncProgress
FullSyncProgress = _pb.FullSyncProgress
NormalSyncProgress = _pb.NormalSyncProgress
DatabaseCheckProgress = _pb.DatabaseCheckProgress
Progress = _pb.Progress
Config = _pb.Config
EmptyCardsReport = _pb.EmptyCardsReport
NoteWithEmptyCards = _pb.NoteWithEmptyCards
@ -125,7 +120,7 @@ class Collection:
##########################################################################
def latest_progress(self) -> Progress:
return Progress.from_proto(self._backend.latest_progress())
return self._backend.latest_progress()
# Scheduler
##########################################################################
@ -874,42 +869,5 @@ table.review-log {{ {revlog_style} }}
self._backend.set_preferences(prefs)
class ProgressKind(enum.Enum):
NoProgress = 0
MediaSync = 1
MediaCheck = 2
FullSync = 3
NormalSync = 4
DatabaseCheck = 5
@dataclass
class Progress:
kind: ProgressKind
val: Union[
MediaSyncProgress,
FullSyncProgress,
NormalSyncProgress,
DatabaseCheckProgress,
str,
]
@staticmethod
def from_proto(proto: _pb.Progress) -> Progress:
kind = proto.WhichOneof("value")
if kind == "media_sync":
return Progress(kind=ProgressKind.MediaSync, val=proto.media_sync)
elif kind == "media_check":
return Progress(kind=ProgressKind.MediaCheck, val=proto.media_check)
elif kind == "full_sync":
return Progress(kind=ProgressKind.FullSync, val=proto.full_sync)
elif kind == "normal_sync":
return Progress(kind=ProgressKind.NormalSync, val=proto.normal_sync)
elif kind == "database_check":
return Progress(kind=ProgressKind.DatabaseCheck, val=proto.database_check)
else:
return Progress(kind=ProgressKind.NoProgress, val="")
# legacy name
_Collection = Collection

View file

@ -6,22 +6,20 @@ from __future__ import annotations
from concurrent.futures import Future
import aqt
from anki.collection import DatabaseCheckProgress, ProgressKind
from aqt.qt import *
from aqt.utils import showText, tooltip
def on_progress(mw: aqt.main.AnkiQt) -> None:
progress = mw.col.latest_progress()
if progress.kind != ProgressKind.DatabaseCheck:
if not progress.HasField("database_check"):
return
assert isinstance(progress.val, DatabaseCheckProgress)
dbprogress = progress.database_check
mw.progress.update(
process=False,
label=progress.val.stage,
value=progress.val.stage_current,
max=progress.val.stage_total,
label=dbprogress.stage,
value=dbprogress.stage_current,
max=dbprogress.stage_total,
)

View file

@ -9,7 +9,7 @@ from concurrent.futures import Future
from typing import Iterable, List, Optional, Sequence, TypeVar
import aqt
from anki.collection import ProgressKind, SearchTerm
from anki.collection import SearchTerm
from anki.errors import Interrupted
from anki.lang import TR
from anki.media import CheckMediaOut
@ -62,11 +62,9 @@ class MediaChecker:
def _on_progress(self) -> None:
progress = self.mw.col.latest_progress()
if progress.kind != ProgressKind.MediaCheck:
if not progress.HasField("media_check"):
return
assert isinstance(progress.val, str)
val = progress.val
label = progress.media_check
try:
if self.progress_dialog.wantCancel:
@ -75,7 +73,7 @@ class MediaChecker:
# dialog may not be active
pass
self.mw.taskman.run_on_main(lambda: self.mw.progress.update(val))
self.mw.taskman.run_on_main(lambda: self.mw.progress.update(label=label))
def _check(self) -> CheckMediaOut:
"Run the check on a background thread."

View file

@ -9,7 +9,7 @@ from dataclasses import dataclass
from typing import Any, Callable, List, Optional, Union
import aqt
from anki.collection import MediaSyncProgress, ProgressKind
from anki.collection import Progress
from anki.errors import Interrupted, NetworkError
from anki.lang import TR
from anki.types import assert_exhaustive
@ -18,7 +18,7 @@ from aqt import gui_hooks
from aqt.qt import QDialog, QDialogButtonBox, QPushButton, QTextCursor, QTimer, qconnect
from aqt.utils import disable_help_button, showWarning, tr
LogEntry = Union[MediaSyncProgress, str]
LogEntry = Union[Progress.MediaSync, str]
@dataclass
@ -37,11 +37,10 @@ class MediaSyncer:
def _on_progress(self) -> None:
progress = self.mw.col.latest_progress()
if progress.kind != ProgressKind.MediaSync:
if not progress.HasField("media_sync"):
return
assert isinstance(progress.val, MediaSyncProgress)
self._log_and_notify(progress.val)
sync_progress = progress.media_sync
self._log_and_notify(sync_progress)
def start(self) -> None:
"Start media syncing in the background, if it's not already running."
@ -202,13 +201,13 @@ class MediaSyncDialog(QDialog):
def _entry_to_text(self, entry: LogEntryWithTime) -> str:
if isinstance(entry.entry, str):
txt = entry.entry
elif isinstance(entry.entry, MediaSyncProgress):
elif isinstance(entry.entry, Progress.MediaSync):
txt = self._logentry_to_text(entry.entry)
else:
assert_exhaustive(entry.entry)
return self._time_and_text(entry.time, txt)
def _logentry_to_text(self, e: MediaSyncProgress) -> str:
def _logentry_to_text(self, e: Progress.MediaSync) -> str:
return f"{e.added}, {e.removed}, {e.checked}"
def _on_log_entry(self, entry: LogEntryWithTime) -> None:

View file

@ -9,7 +9,6 @@ from concurrent.futures import Future
from typing import Callable, Tuple
import aqt
from anki.collection import FullSyncProgress, NormalSyncProgress, ProgressKind
from anki.errors import Interrupted, SyncError
from anki.lang import TR, without_unicode_isolation
from anki.sync import SyncOutput, SyncStatus
@ -73,15 +72,15 @@ def handle_sync_error(mw: aqt.main.AnkiQt, err: Exception) -> None:
def on_normal_sync_timer(mw: aqt.main.AnkiQt) -> None:
progress = mw.col.latest_progress()
if progress.kind != ProgressKind.NormalSync:
if not progress.HasField("normal_sync"):
return
sync_progress = progress.normal_sync
assert isinstance(progress.val, NormalSyncProgress)
mw.progress.update(
label=f"{progress.val.added}\n{progress.val.removed}",
label=f"{sync_progress.added}\n{sync_progress.removed}",
process=False,
)
mw.progress.set_title(progress.val.stage)
mw.progress.set_title(sync_progress.stage)
if mw.progress.want_cancel():
mw.col.abort_sync()
@ -153,17 +152,17 @@ def confirm_full_download(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> N
def on_full_sync_timer(mw: aqt.main.AnkiQt) -> None:
progress = mw.col.latest_progress()
if progress.kind != ProgressKind.FullSync:
if not progress.HasField("full_sync"):
return
sync_progress = progress.full_sync
assert isinstance(progress.val, FullSyncProgress)
if progress.val.transferred == progress.val.total:
if sync_progress.transferred == sync_progress.total:
label = tr(TR.SYNC_CHECKING)
else:
label = None
mw.progress.update(
value=progress.val.transferred,
max=progress.val.total,
value=sync_progress.transferred,
max=sync_progress.total,
process=False,
label=label,
)

View file

@ -535,44 +535,38 @@ message SyncError {
///////////////////////////////////////////////////////////
message Progress {
message MediaSync {
string checked = 1;
string added = 2;
string removed = 3;
}
message FullSync {
uint32 transferred = 1;
uint32 total = 2;
}
message NormalSync {
string stage = 1;
string added = 2;
string removed = 3;
}
message DatabaseCheck {
string stage = 1;
uint32 stage_total = 2;
uint32 stage_current = 3;
}
oneof value {
Empty none = 1;
MediaSyncProgress media_sync = 2;
MediaSync media_sync = 2;
string media_check = 3;
FullSyncProgress full_sync = 4;
NormalSyncProgress normal_sync = 5;
DatabaseCheckProgress database_check = 6;
FullSync full_sync = 4;
NormalSync normal_sync = 5;
DatabaseCheck database_check = 6;
}
}
message MediaSyncProgress {
string checked = 1;
string added = 2;
string removed = 3;
}
message FullSyncProgress {
uint32 transferred = 1;
uint32 total = 2;
}
message MediaSyncUploadProgress {
uint32 files = 1;
uint32 deletions = 2;
}
message NormalSyncProgress {
string stage = 1;
string added = 2;
string removed = 3;
}
message DatabaseCheckProgress {
string stage = 1;
uint32 stage_total = 2;
uint32 stage_current = 3;
}
// Messages
///////////////////////////////////////////////////////////

View file

@ -1898,7 +1898,7 @@ fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::Progress {
let s = i18n.trn(TR::MediaCheckChecked, tr_args!["count"=>n]);
pb::progress::Value::MediaCheck(s)
}
Progress::FullSync(p) => pb::progress::Value::FullSync(pb::FullSyncProgress {
Progress::FullSync(p) => pb::progress::Value::FullSync(pb::progress::FullSync {
transferred: p.transferred_bytes as u32,
total: p.total_bytes as u32,
}),
@ -1919,7 +1919,7 @@ fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::Progress {
tr_args![
"up"=>p.local_remove, "down"=>p.remote_remove],
);
pb::progress::Value::NormalSync(pb::NormalSyncProgress {
pb::progress::Value::NormalSync(pb::progress::NormalSync {
stage,
added,
removed,
@ -1940,7 +1940,7 @@ fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::Progress {
DatabaseCheckProgress::History => i18n.tr(TR::DatabaseCheckCheckingHistory),
}
.to_string();
pb::progress::Value::DatabaseCheck(pb::DatabaseCheckProgress {
pb::progress::Value::DatabaseCheck(pb::progress::DatabaseCheck {
stage,
stage_current,
stage_total,
@ -1955,8 +1955,8 @@ fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::Progress {
}
}
fn media_sync_progress(p: MediaSyncProgress, i18n: &I18n) -> pb::MediaSyncProgress {
pb::MediaSyncProgress {
fn media_sync_progress(p: MediaSyncProgress, i18n: &I18n) -> pb::progress::MediaSync {
pb::progress::MediaSync {
checked: i18n.trn(TR::SyncMediaCheckedCount, tr_args!["count"=>p.checked]),
added: i18n.trn(
TR::SyncMediaAddedCount,