mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 23:12:21 -04:00
add a partial Python implementation of the backend
This commit is contained in:
parent
8df5f49c52
commit
99141d9dfb
5 changed files with 91 additions and 7 deletions
|
@ -16,7 +16,6 @@ from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
|
|||
import anki.find
|
||||
import anki.latex # sets up hook
|
||||
import anki.template
|
||||
from anki.backend import Backend
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.db import DB
|
||||
|
@ -27,6 +26,7 @@ from anki.lang import _, ngettext
|
|||
from anki.media import MediaManager
|
||||
from anki.models import ModelManager
|
||||
from anki.notes import Note
|
||||
from anki.rsbackend import RustBackend
|
||||
from anki.sched import Scheduler as V1Scheduler
|
||||
from anki.schedv2 import Scheduler as V2Scheduler
|
||||
from anki.sound import stripSounds
|
||||
|
@ -75,12 +75,12 @@ class _Collection:
|
|||
ls: int
|
||||
conf: Dict[str, Any]
|
||||
_undo: List[Any]
|
||||
backend: Backend
|
||||
backend: RustBackend
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
db: DB,
|
||||
backend: Backend,
|
||||
backend: RustBackend,
|
||||
server: Optional["anki.storage.ServerData"] = None,
|
||||
log: bool = False,
|
||||
) -> None:
|
||||
|
|
82
pylib/anki/pybackend.py
Normal file
82
pylib/anki/pybackend.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
"""
|
||||
A Python implementation of some backend commands.
|
||||
|
||||
Unimplemented commands will be forwarded on to the Rust backend.
|
||||
"""
|
||||
|
||||
from typing import Tuple, Any, Dict
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki.backend_pb2 as pb
|
||||
|
||||
|
||||
class PythonBackend:
|
||||
def __init__(self, col: "anki.storage._Collection"):
|
||||
self.col = col
|
||||
|
||||
def run_command_bytes(self, input: bytes) -> bytes:
|
||||
pb_input = pb.BackendInput()
|
||||
pb_input.ParseFromString(input)
|
||||
|
||||
pb_output = self.run_command(pb_input)
|
||||
|
||||
output = pb_output.SerializeToString()
|
||||
return output
|
||||
|
||||
def run_command(self, input: pb.BackendInput) -> pb.BackendOutput:
|
||||
kind = input.WhichOneof("value")
|
||||
handler = getattr(self, kind, None)
|
||||
# run the equivalent of the following, based on available method names
|
||||
# if kind == "deck_tree":
|
||||
# return pb.BackendOutput(deck_tree=self.deck_tree(input.deck_tree))
|
||||
if handler is not None:
|
||||
input_variant = getattr(input, kind)
|
||||
output_variant = handler(input_variant)
|
||||
output_args: Dict[str, Any] = {kind: output_variant}
|
||||
output = pb.BackendOutput(**output_args)
|
||||
return output
|
||||
else:
|
||||
# forward any unknown commands onto the Rust backend
|
||||
return self.col.backend._run_command(input)
|
||||
|
||||
def deck_tree(self, _input: pb.Empty) -> pb.DeckTreeOut:
|
||||
native = self.col.sched.deckDueTree()
|
||||
return native_deck_tree_to_proto(native)
|
||||
|
||||
def find_cards(self, input: pb.FindCardsIn) -> pb.FindCardsOut:
|
||||
cids = self.col.findCards(input.search)
|
||||
return pb.FindCardsOut(card_ids=cids)
|
||||
|
||||
def browser_rows(self, input: pb.BrowserRowsIn) -> pb.BrowserRowsOut:
|
||||
sort_fields = []
|
||||
for cid in input.card_ids:
|
||||
sort_fields.append(
|
||||
self.col.db.scalar(
|
||||
"select sfld from notes n,cards c where n.id=c.nid and c.id=?", cid
|
||||
)
|
||||
)
|
||||
return pb.BrowserRowsOut(sort_fields=sort_fields)
|
||||
|
||||
|
||||
def native_deck_tree_to_proto(native):
|
||||
top = pb.DeckTreeNode(children=[native_deck_node_to_proto(c) for c in native])
|
||||
out = pb.DeckTreeOut(top=top)
|
||||
return out
|
||||
|
||||
|
||||
def native_deck_node_to_proto(native: Tuple) -> pb.DeckTreeNode:
|
||||
return pb.DeckTreeNode(
|
||||
# fixme: need to decide whether full list
|
||||
# should be included or just tail element
|
||||
names=[native[0]],
|
||||
deck_id=native[1],
|
||||
review_count=native[2],
|
||||
learn_count=native[3],
|
||||
new_count=native[4],
|
||||
children=[native_deck_node_to_proto(c) for c in native[5]],
|
||||
# fixme: currently hard-coded
|
||||
collapsed=False,
|
||||
)
|
|
@ -1,3 +1,5 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
# pylint: skip-file
|
||||
|
||||
from typing import Dict, List
|
||||
|
@ -44,7 +46,7 @@ def proto_template_reqs_to_legacy(
|
|||
return legacy_reqs
|
||||
|
||||
|
||||
class Backend:
|
||||
class RustBackend:
|
||||
def __init__(self, path: str):
|
||||
self._backend = ankirspy.Backend(path)
|
||||
|
|
@ -12,11 +12,11 @@ from operator import itemgetter
|
|||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
from anki.backend import SchedTimingToday
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.hooks import runHook
|
||||
from anki.lang import _
|
||||
from anki.rsbackend import SchedTimingToday
|
||||
from anki.utils import fmtTimeSpan, ids2str, intTime
|
||||
|
||||
# card types: 0=new, 1=lrn, 2=rev, 3=relrn
|
||||
|
|
|
@ -7,11 +7,11 @@ import os
|
|||
import re
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
from anki.backend import Backend
|
||||
from anki.collection import _Collection
|
||||
from anki.consts import *
|
||||
from anki.db import DB
|
||||
from anki.lang import _
|
||||
from anki.rsbackend import RustBackend
|
||||
from anki.stdmodels import (
|
||||
addBasicModel,
|
||||
addBasicTypingModel,
|
||||
|
@ -30,7 +30,7 @@ def Collection(
|
|||
path: str, lock: bool = True, server: Optional[ServerData] = None, log: bool = False
|
||||
) -> _Collection:
|
||||
"Open a new or existing collection. Path must be unicode."
|
||||
backend = Backend(path)
|
||||
backend = RustBackend(path)
|
||||
# fixme: this call is temporarily here to ensure the brige is working
|
||||
# on all platforms, and should be removed in a future beta
|
||||
assert backend.plus_one(5) == 6
|
||||
|
|
Loading…
Reference in a new issue