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.find
|
||||||
import anki.latex # sets up hook
|
import anki.latex # sets up hook
|
||||||
import anki.template
|
import anki.template
|
||||||
from anki.backend import Backend
|
|
||||||
from anki.cards import Card
|
from anki.cards import Card
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.db import DB
|
from anki.db import DB
|
||||||
|
@ -27,6 +26,7 @@ from anki.lang import _, ngettext
|
||||||
from anki.media import MediaManager
|
from anki.media import MediaManager
|
||||||
from anki.models import ModelManager
|
from anki.models import ModelManager
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
|
from anki.rsbackend import RustBackend
|
||||||
from anki.sched import Scheduler as V1Scheduler
|
from anki.sched import Scheduler as V1Scheduler
|
||||||
from anki.schedv2 import Scheduler as V2Scheduler
|
from anki.schedv2 import Scheduler as V2Scheduler
|
||||||
from anki.sound import stripSounds
|
from anki.sound import stripSounds
|
||||||
|
@ -75,12 +75,12 @@ class _Collection:
|
||||||
ls: int
|
ls: int
|
||||||
conf: Dict[str, Any]
|
conf: Dict[str, Any]
|
||||||
_undo: List[Any]
|
_undo: List[Any]
|
||||||
backend: Backend
|
backend: RustBackend
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
db: DB,
|
db: DB,
|
||||||
backend: Backend,
|
backend: RustBackend,
|
||||||
server: Optional["anki.storage.ServerData"] = None,
|
server: Optional["anki.storage.ServerData"] = None,
|
||||||
log: bool = False,
|
log: bool = False,
|
||||||
) -> None:
|
) -> 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
|
# pylint: skip-file
|
||||||
|
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
@ -44,7 +46,7 @@ def proto_template_reqs_to_legacy(
|
||||||
return legacy_reqs
|
return legacy_reqs
|
||||||
|
|
||||||
|
|
||||||
class Backend:
|
class RustBackend:
|
||||||
def __init__(self, path: str):
|
def __init__(self, path: str):
|
||||||
self._backend = ankirspy.Backend(path)
|
self._backend = ankirspy.Backend(path)
|
||||||
|
|
|
@ -12,11 +12,11 @@ from operator import itemgetter
|
||||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
||||||
|
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
from anki.backend import SchedTimingToday
|
|
||||||
from anki.cards import Card
|
from anki.cards import Card
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.hooks import runHook
|
from anki.hooks import runHook
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
|
from anki.rsbackend import SchedTimingToday
|
||||||
from anki.utils import fmtTimeSpan, ids2str, intTime
|
from anki.utils import fmtTimeSpan, ids2str, intTime
|
||||||
|
|
||||||
# card types: 0=new, 1=lrn, 2=rev, 3=relrn
|
# card types: 0=new, 1=lrn, 2=rev, 3=relrn
|
||||||
|
|
|
@ -7,11 +7,11 @@ import os
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Optional, Tuple
|
from typing import Any, Dict, Optional, Tuple
|
||||||
|
|
||||||
from anki.backend import Backend
|
|
||||||
from anki.collection import _Collection
|
from anki.collection import _Collection
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.db import DB
|
from anki.db import DB
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
|
from anki.rsbackend import RustBackend
|
||||||
from anki.stdmodels import (
|
from anki.stdmodels import (
|
||||||
addBasicModel,
|
addBasicModel,
|
||||||
addBasicTypingModel,
|
addBasicTypingModel,
|
||||||
|
@ -30,7 +30,7 @@ def Collection(
|
||||||
path: str, lock: bool = True, server: Optional[ServerData] = None, log: bool = False
|
path: str, lock: bool = True, server: Optional[ServerData] = None, log: bool = False
|
||||||
) -> _Collection:
|
) -> _Collection:
|
||||||
"Open a new or existing collection. Path must be unicode."
|
"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
|
# fixme: this call is temporarily here to ensure the brige is working
|
||||||
# on all platforms, and should be removed in a future beta
|
# on all platforms, and should be removed in a future beta
|
||||||
assert backend.plus_one(5) == 6
|
assert backend.plus_one(5) == 6
|
||||||
|
|
Loading…
Reference in a new issue