From a105037ec9395e1cdb12fe39177e20f574e56112 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sat, 23 May 2020 20:43:55 +1000 Subject: [PATCH] migrate notetypes, update GIL list --- proto/backend.proto | 51 ++++---- pylib/anki/find.py | 2 +- pylib/anki/models.py | 45 ++++--- pylib/anki/rsbackend.py | 170 ++++++++++++-------------- pylib/anki/stdmodels.py | 6 +- pylib/tools/genbackend.py | 4 +- rslib/src/backend/mod.rs | 250 +++++++++++++++++--------------------- rspy/src/lib.rs | 48 +++++++- 8 files changed, 302 insertions(+), 274 deletions(-) diff --git a/proto/backend.proto b/proto/backend.proto index 54958c848..d35486b11 100644 --- a/proto/backend.proto +++ b/proto/backend.proto @@ -128,6 +128,18 @@ service BackendService { rpc AddNoteTags (AddNoteTagsIn) returns (UInt32); rpc UpdateNoteTags (UpdateNoteTagsIn) returns (UInt32); rpc ClozeNumbersInNote (Note) returns (ClozeNumbersInNoteOut); + rpc AfterNoteUpdates (AfterNoteUpdatesIn) returns (Empty); + rpc FieldNamesForNotes (FieldNamesForNotesIn) returns (FieldNamesForNotesOut); + + // note types + + rpc AddOrUpdateNotetype (AddOrUpdateNotetypeIn) returns (NoteTypeID); + rpc GetStockNotetypeLegacy (GetStockNotetypeIn) returns (Json); + rpc GetNotetypeLegacy (NoteTypeID) returns (Json); + rpc GetNotetypeNames (Empty) returns (NoteTypeNames); + rpc GetNotetypeNamesAndCounts (Empty) returns (NoteTypeUseCounts); + rpc GetNotetypeIDByName (String) returns (NoteTypeID); + rpc RemoveNotetype (NoteTypeID) returns (Empty); // misc @@ -379,34 +391,31 @@ message I18nBackendInit { message BackendInput { oneof value { AddMediaFileIn add_media_file = 26; + Empty empty_trash = 34; + Empty restore_trash = 35; + Empty abort_media_sync = 46; + TranslateStringIn translate_string = 30; FormatTimeSpanIn format_time_span = 31; StudiedTodayIn studied_today = 32; CongratsLearnMsgIn congrats_learn_msg = 33; - Empty empty_trash = 34; - Empty restore_trash = 35; + OpenCollectionIn open_collection = 36; CloseCollectionIn close_collection = 37; - Empty abort_media_sync = 46; + Empty before_upload = 47; + RegisterTagsIn register_tags = 48; Empty all_tags = 50; int32 get_changed_tags = 51; + string get_config_json = 52; SetConfigJson set_config_json = 53; bytes set_all_config = 54; Empty get_all_config = 55; - int32 get_changed_notetypes = 56; - AddOrUpdateNotetypeIn add_or_update_notetype = 57; - StockNoteType get_stock_notetype_legacy = 60; - int64 get_notetype_legacy = 61; - Empty get_notetype_names = 62; - Empty get_notetype_names_and_counts = 63; - string get_notetype_id_by_name = 64; - int64 remove_notetype = 65; - FieldNamesForNotesIn field_names_for_notes = 78; + FindAndReplaceIn find_and_replace = 79; - AfterNoteUpdatesIn after_note_updates = 80; + int32 set_local_minutes_west = 83; Empty get_preferences = 84; Preferences set_preferences = 85; @@ -436,20 +445,12 @@ message BackendOutput { Empty set_config_json = 53; Empty set_all_config = 54; bytes get_all_config = 55; - bytes get_changed_notetypes = 56; - int64 add_or_update_notetype = 57; - bytes get_notetype_legacy = 61; - NoteTypeNames get_notetype_names = 62; - NoteTypeUseCounts get_notetype_names_and_counts = 63; - int64 get_notetype_id_by_name = 64; - Empty remove_notetype = 65; - FieldNamesForNotesOut field_names_for_notes = 78; + uint32 find_and_replace = 79; - Empty after_note_updates = 80; + Empty set_local_minutes_west = 83; Preferences get_preferences = 84; Empty set_preferences = 85; - bytes get_stock_notetype_legacy = 60; BackendError error = 2047; } @@ -766,6 +767,10 @@ enum StockNoteType { STOCK_NOTE_TYPE_CLOZE = 4; } +message GetStockNotetypeIn { + StockNoteType kind = 1; +} + message NoteTypeNames { repeated NoteTypeNameID entries = 1; } diff --git a/pylib/anki/find.py b/pylib/anki/find.py index 23dff8d5d..5eb751b9f 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -42,7 +42,7 @@ def findReplace( def fieldNamesForNotes(col: Collection, nids: List[int]) -> List[str]: - return list(col.backend.field_names_for_note_ids(nids)) + return list(col.backend.field_names_for_notes(nids)) # Find duplicates diff --git a/pylib/anki/models.py b/pylib/anki/models.py index 2c7c1c84c..6cbc2eec3 100644 --- a/pylib/anki/models.py +++ b/pylib/anki/models.py @@ -5,13 +5,13 @@ from __future__ import annotations import copy import time -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Dict, List, Optional, Sequence, Tuple, Union import anki # pylint: disable=unused-import import anki.backend_pb2 as pb from anki.consts import * from anki.lang import _ -from anki.rsbackend import StockNoteType +from anki.rsbackend import NotFoundError, StockNoteType, from_json_bytes, to_json_bytes from anki.utils import checksum, ids2str, intTime, joinFields, splitFields # types @@ -109,11 +109,11 @@ class ModelManager: # Listing note types ############################################################# - def all_names_and_ids(self) -> List[pb.NoteTypeNameID]: - return self.col.backend.get_notetype_names_and_ids() + def all_names_and_ids(self) -> Sequence[pb.NoteTypeNameID]: + return self.col.backend.get_notetype_names() - def all_use_counts(self) -> List[pb.NoteTypeNameIDUseCount]: - return self.col.backend.get_notetype_use_counts() + def all_use_counts(self) -> Sequence[pb.NoteTypeNameIDUseCount]: + return self.col.backend.get_notetype_names_and_counts() # legacy @@ -149,7 +149,10 @@ class ModelManager: ############################################################# def id_for_name(self, name: str) -> Optional[int]: - return self.col.backend.get_notetype_id_by_name(name) + try: + return self.col.backend.get_notetype_id_by_name(name) + except NotFoundError: + return None def get(self, id: int) -> Optional[NoteType]: "Get model with ID, or None." @@ -161,9 +164,11 @@ class ModelManager: nt = self._get_cached(id) if not nt: - nt = self.col.backend.get_notetype_legacy(id) - if nt: + try: + nt = from_json_bytes(self.col.backend.get_notetype_legacy(id)) self._update_cache(nt) + except NotFoundError: + return None return nt def all(self) -> List[NoteType]: @@ -181,8 +186,10 @@ class ModelManager: def new(self, name: str) -> NoteType: "Create a new model, and return it." # caller should call save() after modifying - nt = self.col.backend.get_stock_notetype_legacy( - StockNoteType.STOCK_NOTE_TYPE_BASIC + nt = from_json_bytes( + self.col.backend.get_stock_notetype_legacy( + StockNoteType.STOCK_NOTE_TYPE_BASIC + ) ) nt["flds"] = [] nt["tmpls"] = [] @@ -215,7 +222,9 @@ class ModelManager: "Add or update an existing model. Use .save() instead." self._remove_from_cache(m["id"]) self.ensureNameUnique(m) - self.col.backend.add_or_update_notetype(m, preserve_usn=preserve_usn) + m["id"] = self.col.backend.add_or_update_notetype( + to_json_bytes(m), preserve_usn_and_mtime=preserve_usn + ) self.setCurrent(m) self._mutate_after_write(m) @@ -268,8 +277,10 @@ class ModelManager: def new_field(self, name: str) -> Field: assert isinstance(name, str) - nt = self.col.backend.get_stock_notetype_legacy( - StockNoteType.STOCK_NOTE_TYPE_BASIC + nt = from_json_bytes( + self.col.backend.get_stock_notetype_legacy( + StockNoteType.STOCK_NOTE_TYPE_BASIC + ) ) field = nt["flds"][0] field["name"] = name @@ -327,8 +338,10 @@ class ModelManager: ################################################## def new_template(self, name: str) -> Template: - nt = self.col.backend.get_stock_notetype_legacy( - StockNoteType.STOCK_NOTE_TYPE_BASIC + nt = from_json_bytes( + self.col.backend.get_stock_notetype_legacy( + StockNoteType.STOCK_NOTE_TYPE_BASIC + ) ) template = nt["tmpls"][0] template["name"] = name diff --git a/pylib/anki/rsbackend.py b/pylib/anki/rsbackend.py index 5db11cc5c..5550c6ce0 100644 --- a/pylib/anki/rsbackend.py +++ b/pylib/anki/rsbackend.py @@ -370,70 +370,6 @@ class RustBackend: def set_all_config(self, conf: Dict[str, Any]): self._run_command(pb.BackendInput(set_all_config=orjson.dumps(conf))) - def get_changed_notetypes(self, usn: int) -> Dict[str, Dict[str, Any]]: - jstr = self._run_command( - pb.BackendInput(get_changed_notetypes=usn) - ).get_changed_notetypes - return orjson.loads(jstr) - - def get_stock_notetype_legacy(self, kind: StockNoteType) -> Dict[str, Any]: - bytes = self._run_command( - pb.BackendInput(get_stock_notetype_legacy=kind) - ).get_stock_notetype_legacy - return orjson.loads(bytes) - - def get_notetype_names_and_ids(self) -> List[pb.NoteTypeNameID]: - return list( - self._run_command( - pb.BackendInput(get_notetype_names=pb.Empty()) - ).get_notetype_names.entries - ) - - def get_notetype_use_counts(self) -> List[pb.NoteTypeNameIDUseCount]: - return list( - self._run_command( - pb.BackendInput(get_notetype_names_and_counts=pb.Empty()) - ).get_notetype_names_and_counts.entries - ) - - def get_notetype_legacy(self, ntid: int) -> Optional[Dict]: - try: - bytes = self._run_command( - pb.BackendInput(get_notetype_legacy=ntid) - ).get_notetype_legacy - except NotFoundError: - return None - return orjson.loads(bytes) - - def get_notetype_id_by_name(self, name: str) -> Optional[int]: - return ( - self._run_command( - pb.BackendInput(get_notetype_id_by_name=name) - ).get_notetype_id_by_name - or None - ) - - def add_or_update_notetype(self, nt: Dict[str, Any], preserve_usn: bool) -> None: - bjson = orjson.dumps(nt) - id = self._run_command( - pb.BackendInput( - add_or_update_notetype=pb.AddOrUpdateNotetypeIn( - json=bjson, preserve_usn_and_mtime=preserve_usn - ) - ), - release_gil=True, - ).add_or_update_notetype - nt["id"] = id - - def remove_notetype(self, ntid: int) -> None: - self._run_command(pb.BackendInput(remove_notetype=ntid), release_gil=True) - - def field_names_for_note_ids(self, nids: List[int]) -> Sequence[str]: - return self._run_command( - pb.BackendInput(field_names_for_notes=pb.FieldNamesForNotesIn(nids=nids)), - release_gil=True, - ).field_names_for_notes.fields - def find_and_replace( self, nids: List[int], @@ -457,20 +393,6 @@ class RustBackend: release_gil=True, ).find_and_replace - def after_note_updates( - self, nids: List[int], generate_cards: bool, mark_notes_modified: bool - ) -> None: - self._run_command( - pb.BackendInput( - after_note_updates=pb.AfterNoteUpdatesIn( - nids=nids, - generate_cards=generate_cards, - mark_notes_modified=mark_notes_modified, - ) - ), - release_gil=True, - ) - def set_local_minutes_west(self, mins: int) -> None: self._run_command(pb.BackendInput(set_local_minutes_west=mins)) @@ -599,15 +521,15 @@ class RustBackend: def deck_tree_legacy(self) -> bytes: input = pb.Empty() - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(16, input)) - return output.val + return output.json def get_all_decks_legacy(self) -> bytes: input = pb.Empty() - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(17, input)) - return output.val + return output.json def get_deck_id_by_name(self, val: str) -> int: input = pb.String(val=val) @@ -617,9 +539,9 @@ class RustBackend: def get_deck_legacy(self, did: int) -> bytes: input = pb.DeckID(did=did) - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(19, input)) - return output.val + return output.json def get_deck_names( self, skip_empty_default: bool, include_filtered: bool @@ -633,9 +555,9 @@ class RustBackend: def new_deck_legacy(self, val: bool) -> bytes: input = pb.Bool(val=val) - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(21, input)) - return output.val + return output.json def remove_deck(self, did: int) -> pb.Empty: input = pb.DeckID(did=did) @@ -655,21 +577,21 @@ class RustBackend: def all_deck_config_legacy(self) -> bytes: input = pb.Empty() - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(24, input)) - return output.val + return output.json def get_deck_config_legacy(self, dcid: int) -> bytes: input = pb.DeckConfigID(dcid=dcid) - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(25, input)) - return output.val + return output.json def new_deck_config_legacy(self) -> bytes: input = pb.Empty() - output = pb.Bytes() + output = pb.Json() output.ParseFromString(self._run_command2(26, input)) - return output.val + return output.json def remove_deck_config(self, dcid: int) -> pb.Empty: input = pb.DeckConfigID(dcid=dcid) @@ -737,10 +659,72 @@ class RustBackend: output.ParseFromString(self._run_command2(37, input)) return output.numbers + def after_note_updates( + self, nids: Sequence[int], mark_notes_modified: bool, generate_cards: bool + ) -> pb.Empty: + input = pb.AfterNoteUpdatesIn( + nids=nids, + mark_notes_modified=mark_notes_modified, + generate_cards=generate_cards, + ) + output = pb.Empty() + output.ParseFromString(self._run_command2(38, input)) + return output + + def field_names_for_notes(self, nids: Sequence[int]) -> Sequence[str]: + input = pb.FieldNamesForNotesIn(nids=nids) + output = pb.FieldNamesForNotesOut() + output.ParseFromString(self._run_command2(39, input)) + return output.fields + + def add_or_update_notetype(self, json: bytes, preserve_usn_and_mtime: bool) -> int: + input = pb.AddOrUpdateNotetypeIn( + json=json, preserve_usn_and_mtime=preserve_usn_and_mtime + ) + output = pb.NoteTypeID() + output.ParseFromString(self._run_command2(40, input)) + return output.ntid + + def get_stock_notetype_legacy(self, kind: pb.StockNoteType) -> bytes: + input = pb.GetStockNotetypeIn(kind=kind) + output = pb.Json() + output.ParseFromString(self._run_command2(41, input)) + return output.json + + def get_notetype_legacy(self, ntid: int) -> bytes: + input = pb.NoteTypeID(ntid=ntid) + output = pb.Json() + output.ParseFromString(self._run_command2(42, input)) + return output.json + + def get_notetype_names(self) -> Sequence[pb.NoteTypeNameID]: + input = pb.Empty() + output = pb.NoteTypeNames() + output.ParseFromString(self._run_command2(43, input)) + return output.entries + + def get_notetype_names_and_counts(self) -> Sequence[pb.NoteTypeNameIDUseCount]: + input = pb.Empty() + output = pb.NoteTypeUseCounts() + output.ParseFromString(self._run_command2(44, input)) + return output.entries + + def get_notetype_id_by_name(self, val: str) -> int: + input = pb.String(val=val) + output = pb.NoteTypeID() + output.ParseFromString(self._run_command2(45, input)) + return output.ntid + + def remove_notetype(self, ntid: int) -> pb.Empty: + input = pb.NoteTypeID(ntid=ntid) + output = pb.Empty() + output.ParseFromString(self._run_command2(46, input)) + return output + def check_database(self) -> Sequence[str]: input = pb.Empty() output = pb.CheckDatabaseOut() - output.ParseFromString(self._run_command2(38, input)) + output.ParseFromString(self._run_command2(47, input)) return output.problems # @@AUTOGEN@@ diff --git a/pylib/anki/stdmodels.py b/pylib/anki/stdmodels.py index 8303bf2f1..de5fdd7c1 100644 --- a/pylib/anki/stdmodels.py +++ b/pylib/anki/stdmodels.py @@ -5,7 +5,7 @@ from typing import Callable, List, Tuple from anki.collection import Collection from anki.models import NoteType -from anki.rsbackend import StockNoteType +from anki.rsbackend import StockNoteType, from_json_bytes # add-on authors can add ("note type name", function_like_addBasicModel) # to this list to have it shown in the add/clone note type screen @@ -13,7 +13,7 @@ models: List[Tuple] = [] def add_stock_notetype(col: Collection, kind: StockNoteType) -> NoteType: - m = col.backend.get_stock_notetype_legacy(kind) + m = from_json_bytes(col.backend.get_stock_notetype_legacy(kind)) col.models.add(m) return m @@ -55,7 +55,7 @@ def get_stock_notetypes( ), (StockNoteType.STOCK_NOTE_TYPE_CLOZE, addClozeModel), ]: - m = col.backend.get_stock_notetype_legacy(kind) + m = from_json_bytes(col.backend.get_stock_notetype_legacy(kind)) out.append((m["name"], func)) # add extras from add-ons for (name_or_func, func) in models: diff --git a/pylib/tools/genbackend.py b/pylib/tools/genbackend.py index 969d7bebb..5c4dc7cb8 100755 --- a/pylib/tools/genbackend.py +++ b/pylib/tools/genbackend.py @@ -49,8 +49,10 @@ def python_type_inner(field): return "str" elif type == TYPE_BYTES: return "bytes" - elif type == 11: + elif type == TYPE_MESSAGE: return "pb." + field.message_type.name + elif type == TYPE_ENUM: + return "pb." + field.enum_type.name else: raise Exception(f"unknown type: {type}") diff --git a/rslib/src/backend/mod.rs b/rslib/src/backend/mod.rs index bd500de2e..4d210734e 100644 --- a/rslib/src/backend/mod.rs +++ b/rslib/src/backend/mod.rs @@ -623,6 +623,120 @@ impl BackendService for Backend { }) } + fn field_names_for_notes( + &mut self, + input: pb::FieldNamesForNotesIn, + ) -> BackendResult { + self.with_col(|col| { + let nids: Vec<_> = input.nids.into_iter().map(NoteID).collect(); + col.storage + .field_names_for_notes(&nids) + .map(|fields| pb::FieldNamesForNotesOut { fields }) + }) + } + + fn after_note_updates(&mut self, input: pb::AfterNoteUpdatesIn) -> BackendResult { + self.with_col(|col| { + col.transact(None, |col| { + col.after_note_updates( + &to_nids(input.nids), + input.generate_cards, + input.mark_notes_modified, + )?; + Ok(pb::Empty {}) + }) + }) + } + + // notetypes + //------------------------------------------------------------------- + + fn get_stock_notetype_legacy( + &mut self, + input: pb::GetStockNotetypeIn, + ) -> BackendResult { + // fixme: use individual functions instead of full vec + let mut all = all_stock_notetypes(&self.i18n); + let idx = (input.kind as usize).min(all.len() - 1); + let nt = all.swap_remove(idx); + let schema11: NoteTypeSchema11 = nt.into(); + serde_json::to_vec(&schema11) + .map_err(Into::into) + .map(Into::into) + } + + fn get_notetype_names(&mut self, _input: Empty) -> BackendResult { + self.with_col(|col| { + let entries: Vec<_> = col + .storage + .get_all_notetype_names()? + .into_iter() + .map(|(id, name)| pb::NoteTypeNameId { id: id.0, name }) + .collect(); + Ok(pb::NoteTypeNames { entries }) + }) + } + + fn get_notetype_names_and_counts( + &mut self, + _input: Empty, + ) -> BackendResult { + self.with_col(|col| { + let entries: Vec<_> = col + .storage + .get_notetype_use_counts()? + .into_iter() + .map(|(id, name, use_count)| pb::NoteTypeNameIdUseCount { + id: id.0, + name, + use_count, + }) + .collect(); + Ok(pb::NoteTypeUseCounts { entries }) + }) + } + + fn get_notetype_legacy(&mut self, input: pb::NoteTypeId) -> BackendResult { + self.with_col(|col| { + let schema11: NoteTypeSchema11 = col + .storage + .get_notetype(input.into())? + .ok_or(AnkiError::NotFound)? + .into(); + Ok(serde_json::to_vec(&schema11)?).map(Into::into) + }) + } + + fn get_notetype_id_by_name(&mut self, input: pb::String) -> BackendResult { + self.with_col(|col| { + col.storage + .get_notetype_id(&input.val) + .and_then(|nt| nt.ok_or(AnkiError::NotFound)) + .map(|ntid| pb::NoteTypeId { ntid: ntid.0 }) + }) + } + + fn add_or_update_notetype( + &mut self, + input: pb::AddOrUpdateNotetypeIn, + ) -> BackendResult { + self.with_col(|col| { + let legacy: NoteTypeSchema11 = serde_json::from_slice(&input.json)?; + let mut nt: NoteType = legacy.into(); + if nt.id.0 == 0 { + col.add_notetype(&mut nt)?; + } else { + col.update_notetype(&mut nt, input.preserve_usn_and_mtime)?; + } + Ok(pb::NoteTypeId { ntid: nt.id.0 }) + }) + } + + fn remove_notetype(&mut self, input: pb::NoteTypeId) -> BackendResult { + self.with_col(|col| col.remove_notetype(input.into())) + .map(Into::into) + } + // media //------------------------------------------------------------------- @@ -828,37 +942,7 @@ impl Backend { pb::Empty {} }), Value::GetAllConfig(_) => OValue::GetAllConfig(self.get_all_config()?), - Value::GetChangedNotetypes(_) => { - OValue::GetChangedNotetypes(self.get_changed_notetypes()?) - } - Value::GetStockNotetypeLegacy(kind) => { - OValue::GetStockNotetypeLegacy(self.get_stock_notetype_legacy(kind)?) - } - Value::GetNotetypeLegacy(id) => { - OValue::GetNotetypeLegacy(self.get_notetype_legacy(id)?) - } - Value::GetNotetypeNames(_) => OValue::GetNotetypeNames(self.get_notetype_names()?), - Value::GetNotetypeNamesAndCounts(_) => { - OValue::GetNotetypeNamesAndCounts(self.get_notetype_use_counts()?) - } - - Value::GetNotetypeIdByName(name) => { - OValue::GetNotetypeIdByName(self.get_notetype_id_by_name(name)?) - } - Value::AddOrUpdateNotetype(input) => { - OValue::AddOrUpdateNotetype(self.add_or_update_notetype_legacy(input)?) - } - Value::RemoveNotetype(id) => { - self.remove_notetype(id)?; - OValue::RemoveNotetype(pb::Empty {}) - } - Value::FieldNamesForNotes(input) => { - OValue::FieldNamesForNotes(self.field_names_for_notes(input)?) - } Value::FindAndReplace(input) => OValue::FindAndReplace(self.find_and_replace(input)?), - Value::AfterNoteUpdates(input) => { - OValue::AfterNoteUpdates(self.after_note_updates(input)?) - } Value::SetLocalMinutesWest(mins) => OValue::SetLocalMinutesWest({ self.set_local_mins_west(mins)?; pb::Empty {} @@ -1125,90 +1209,6 @@ impl Backend { }) } - fn get_changed_notetypes(&self) -> Result> { - todo!("filter by usn"); - // self.with_col(|col| { - // let nts = col.storage.get_all_notetypes_as_schema11()?; - // serde_json::to_vec(&nts).map_err(Into::into) - // }) - } - - fn get_notetype_names(&self) -> Result { - self.with_col(|col| { - let entries: Vec<_> = col - .storage - .get_all_notetype_names()? - .into_iter() - .map(|(id, name)| pb::NoteTypeNameId { id: id.0, name }) - .collect(); - Ok(pb::NoteTypeNames { entries }) - }) - } - - fn get_notetype_use_counts(&self) -> Result { - self.with_col(|col| { - let entries: Vec<_> = col - .storage - .get_notetype_use_counts()? - .into_iter() - .map(|(id, name, use_count)| pb::NoteTypeNameIdUseCount { - id: id.0, - name, - use_count, - }) - .collect(); - Ok(pb::NoteTypeUseCounts { entries }) - }) - } - - fn get_notetype_legacy(&self, id: i64) -> Result> { - self.with_col(|col| { - let schema11: NoteTypeSchema11 = col - .storage - .get_notetype(NoteTypeID(id))? - .ok_or(AnkiError::NotFound)? - .into(); - Ok(serde_json::to_vec(&schema11)?) - }) - } - - fn get_notetype_id_by_name(&self, name: String) -> Result { - self.with_col(|col| { - col.storage - .get_notetype_id(&name) - .map(|nt| nt.unwrap_or(NoteTypeID(0)).0) - }) - } - - fn add_or_update_notetype_legacy(&self, input: pb::AddOrUpdateNotetypeIn) -> Result { - self.with_col(|col| { - let legacy: NoteTypeSchema11 = serde_json::from_slice(&input.json)?; - let mut nt: NoteType = legacy.into(); - if nt.id.0 == 0 { - col.add_notetype(&mut nt)?; - } else { - col.update_notetype(&mut nt, input.preserve_usn_and_mtime)?; - } - Ok(nt.id.0) - }) - } - - fn remove_notetype(&self, id: i64) -> Result<()> { - self.with_col(|col| col.remove_notetype(NoteTypeID(id))) - } - - fn field_names_for_notes( - &self, - input: pb::FieldNamesForNotesIn, - ) -> Result { - self.with_col(|col| { - let nids: Vec<_> = input.nids.into_iter().map(NoteID).collect(); - col.storage - .field_names_for_notes(&nids) - .map(|fields| pb::FieldNamesForNotesOut { fields }) - }) - } - fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> Result { let mut search = if input.regex { input.search @@ -1231,19 +1231,6 @@ impl Backend { }) } - fn after_note_updates(&self, input: pb::AfterNoteUpdatesIn) -> Result { - self.with_col(|col| { - col.transact(None, |col| { - col.after_note_updates( - &to_nids(input.nids), - input.generate_cards, - input.mark_notes_modified, - )?; - Ok(pb::Empty {}) - }) - }) - } - fn set_local_mins_west(&self, mins: i32) -> Result<()> { self.with_col(|col| col.transact(None, |col| col.set_local_mins_west(mins))) } @@ -1255,15 +1242,6 @@ impl Backend { fn set_preferences(&self, prefs: pb::Preferences) -> Result<()> { self.with_col(|col| col.transact(None, |col| col.set_preferences(prefs))) } - - fn get_stock_notetype_legacy(&self, kind: i32) -> Result> { - // fixme: use individual functions instead of full vec - let mut all = all_stock_notetypes(&self.i18n); - let idx = (kind as usize).min(all.len() - 1); - let nt = all.swap_remove(idx); - let schema11: NoteTypeSchema11 = nt.into(); - serde_json::to_vec(&schema11).map_err(Into::into) - } } fn to_nids(ids: Vec) -> Vec { diff --git a/rspy/src/lib.rs b/rspy/src/lib.rs index fcc7b1f55..4fc637757 100644 --- a/rspy/src/lib.rs +++ b/rspy/src/lib.rs @@ -35,7 +35,53 @@ fn open_backend(init_msg: &PyBytes) -> PyResult { fn want_release_gil(method: u32) -> bool { if let Ok(method) = BackendMethod::try_from(method) { match method { - _ => false, + BackendMethod::ExtractAVTags => false, + BackendMethod::ExtractLatex => false, + BackendMethod::GetEmptyCards => true, + BackendMethod::RenderExistingCard => false, + BackendMethod::RenderUncommittedCard => false, + BackendMethod::StripAVTags => false, + BackendMethod::SearchCards => true, + BackendMethod::SearchNotes => true, + BackendMethod::LocalMinutesWest => false, + BackendMethod::SchedTimingToday => false, + BackendMethod::CheckMedia => true, + BackendMethod::SyncMedia => true, + BackendMethod::TrashMediaFiles => true, + BackendMethod::AddOrUpdateDeckLegacy => false, + BackendMethod::DeckTree => true, + BackendMethod::DeckTreeLegacy => true, + BackendMethod::GetAllDecksLegacy => true, + BackendMethod::GetDeckIDByName => true, + BackendMethod::GetDeckLegacy => true, + BackendMethod::GetDeckNames => true, + BackendMethod::NewDeckLegacy => false, + BackendMethod::RemoveDeck => true, + BackendMethod::AddOrUpdateDeckConfigLegacy => true, + BackendMethod::AllDeckConfigLegacy => true, + BackendMethod::GetDeckConfigLegacy => true, + BackendMethod::NewDeckConfigLegacy => false, + BackendMethod::RemoveDeckConfig => true, + BackendMethod::GetCard => true, + BackendMethod::UpdateCard => true, + BackendMethod::AddCard => true, + BackendMethod::NewNote => true, + BackendMethod::AddNote => true, + BackendMethod::UpdateNote => true, + BackendMethod::GetNote => true, + BackendMethod::AddNoteTags => true, + BackendMethod::UpdateNoteTags => true, + BackendMethod::ClozeNumbersInNote => true, + BackendMethod::AfterNoteUpdates => true, + BackendMethod::FieldNamesForNotes => true, + BackendMethod::AddOrUpdateNotetype => true, + BackendMethod::GetStockNotetypeLegacy => false, + BackendMethod::GetNotetypeLegacy => true, + BackendMethod::GetNotetypeNames => true, + BackendMethod::GetNotetypeNamesAndCounts => true, + BackendMethod::GetNotetypeIDByName => true, + BackendMethod::RemoveNotetype => true, + BackendMethod::CheckDatabase => true, } } else { false