migrate notetypes, update GIL list

This commit is contained in:
Damien Elmes 2020-05-23 20:43:55 +10:00
parent 6710e3d528
commit a105037ec9
8 changed files with 302 additions and 274 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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@@

View file

@ -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:

View file

@ -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}")

View file

@ -623,6 +623,120 @@ impl BackendService for Backend {
})
}
fn field_names_for_notes(
&mut self,
input: pb::FieldNamesForNotesIn,
) -> BackendResult<pb::FieldNamesForNotesOut> {
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<Empty> {
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<pb::Json> {
// 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<pb::NoteTypeNames> {
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<pb::NoteTypeUseCounts> {
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<pb::Json> {
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<pb::NoteTypeId> {
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<pb::NoteTypeId> {
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<Empty> {
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<Vec<u8>> {
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<pb::NoteTypeNames> {
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<pb::NoteTypeUseCounts> {
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<Vec<u8>> {
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<i64> {
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<i64> {
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<pb::FieldNamesForNotesOut> {
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<u32> {
let mut search = if input.regex {
input.search
@ -1231,19 +1231,6 @@ impl Backend {
})
}
fn after_note_updates(&self, input: pb::AfterNoteUpdatesIn) -> Result<pb::Empty> {
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<Vec<u8>> {
// 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<i64>) -> Vec<NoteID> {

View file

@ -35,7 +35,53 @@ fn open_backend(init_msg: &PyBytes) -> PyResult<Backend> {
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