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 deck_tree(self, include_counts: bool, top_deck_id: int = 0) -> DeckTreeNode: return self._run_command( pb.BackendInput( deck_tree=pb.DeckTreeIn(include_counts=include_counts, top_deck_id=top_deck_id))).deck_tree
def close_collection(self, downgrade=True): self._run_command( pb.BackendInput( close_collection=pb.CloseCollectionIn(downgrade_to_schema11=downgrade) ), release_gil=True, )
def sched_timing_today( self, created_secs: int, created_mins_west: Optional[int], now_mins_west: Optional[int], rollover: Optional[int], ) -> SchedTimingToday: if created_mins_west is not None: crt_west = pb.OptionalInt32(val=created_mins_west) else: crt_west = None if now_mins_west is not None: now_west = pb.OptionalInt32(val=now_mins_west) else: now_west = None if rollover is not None: roll = pb.OptionalInt32(val=rollover) else: roll = None return self._run_command( pb.BackendInput(sched_timing_today=pb.SchedTimingTodayIn( created_secs=created_secs, now_secs=intTime(), created_mins_west=crt_west, now_mins_west=now_west, rollover_hour=roll, ))).sched_timing_today
def get_deck_legacy(self, did: int) -> Optional[Dict]: try: bytes = self._run_command( pb.BackendInput(get_deck_legacy=did)).get_deck_legacy return orjson.loads(bytes) except NotFoundError: return None
def get_av_tags(self, text: str) -> List[AVTag]: return list( map( av_tag_to_native, self._run_command( pb.BackendInput(get_av_tags=text)).get_av_tags.av_tags, ))
def studied_today( self, cards: int, seconds: float, ) -> str: return self._run_command( pb.BackendInput(studied_today=pb.StudiedTodayIn( cards=cards, seconds=seconds))).studied_today
def extract_av_tags(self, text: str, question_side: bool) -> Tuple[str, List[AVTag]]: out = self._run_command( pb.BackendInput(extract_av_tags=pb.ExtractAVTagsIn( text=text, question_side=question_side))).extract_av_tags native_tags = list(map(av_tag_to_native, out.av_tags)) return out.text, native_tags
def sync_media(self, hkey: str, endpoint: str) -> None: self._run_command( pb.BackendInput(sync_media=pb.SyncMediaIn( hkey=hkey, endpoint=endpoint, )), release_gil=True, )
def format_time_span( self, seconds: float, context: FormatTimeSpanContext = FormatTimeSpanContext.INTERVALS, ) -> str: return self._run_command( pb.BackendInput(format_time_span=pb.FormatTimeSpanIn( seconds=seconds, context=context))).format_time_span
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 learning_congrats_msg(self, next_due: float, remaining: int) -> str: return self._run_command( pb.BackendInput( congrats_learn_msg=pb.CongratsLearnMsgIn( next_due=next_due, remaining=remaining ) ) ).congrats_learn_msg
def add_or_update_deck_legacy(self, deck: Dict[str, Any], preserve_usn: bool) -> None: deck_json = orjson.dumps(deck) id = self._run_command( pb.BackendInput( add_or_update_deck_legacy=pb.AddOrUpdateDeckLegacyIn( deck=deck_json, preserve_usn_and_mtime=preserve_usn)) ).add_or_update_deck_legacy deck["id"] = id
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 get_deck_names_and_ids( self, skip_empty_default: bool, include_filtered: bool = True) -> Sequence[pb.DeckNameID]: return self._run_command( pb.BackendInput(get_deck_names=pb.GetDeckNamesIn( skip_empty_default=skip_empty_default, include_filtered=include_filtered, ))).get_deck_names.entries
def add_or_update_deck_config(self, conf: Dict[str, Any], preserve_usn) -> None: conf_json = orjson.dumps(conf) id = self._run_command( pb.BackendInput( add_or_update_deck_config=pb.AddOrUpdateDeckConfigIn( config=conf_json, preserve_usn_and_mtime=preserve_usn)) ).add_or_update_deck_config conf["id"] = id
def sched_timing_today(self, start: int, end: int, offset: int, rollover: int) -> SchedTimingToday: return self._run_command( pb.BackendInput(sched_timing_today=pb.SchedTimingTodayIn( created=start, now=end, minutes_west=offset, rollover_hour=rollover, ))).sched_timing_today
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 template_requirements(self, template_fronts: List[str], field_map: Dict[str, int]) -> AllTemplateReqs: input = pb.BackendInput( template_requirements=pb.TemplateRequirementsIn( template_front=template_fronts, field_names_to_ordinals=field_map)) output = self._run_command(input).template_requirements reqs: List[ pb.TemplateRequirement] = output.requirements # type: ignore return proto_template_reqs_to_legacy(reqs)
def open_collection(self, col_path: str, media_folder_path: str, media_db_path: str, log_path: str): self._run_command( pb.BackendInput(open_collection=pb.OpenCollectionIn( collection_path=col_path, media_folder_path=media_folder_path, media_db_path=media_db_path, log_path=log_path, )), release_gil=True, )
def extract_latex(self, text: str, svg: bool) -> ExtractedLatexOutput: out = self._run_command( pb.BackendInput(extract_latex=pb.ExtractLatexIn(text=text, svg=svg)) ).extract_latex return ExtractedLatexOutput( html=out.text, latex=[ ExtractedLatex(filename=l.filename, latex_body=l.latex_body) for l in out.latex ], )
def render_existing_card(self, cid: int, browser: bool) -> PartiallyRenderedCard: out = self._run_command( pb.BackendInput(render_existing_card=pb.RenderExistingCardIn( card_id=cid, browser=browser, ))).render_existing_card qnodes = proto_replacement_list_to_native( out.question_nodes) # type: ignore anodes = proto_replacement_list_to_native( out.answer_nodes) # type: ignore return PartiallyRenderedCard(qnodes, anodes)
def translate( self, group: pb.StringsGroup, key: str, **kwargs: Union[str, int, float] ): args = {} for (k, v) in kwargs.items(): if isinstance(v, str): args[k] = pb.TranslateArgValue(str=v) else: args[k] = pb.TranslateArgValue(number=str(v)) return self._run_command( pb.BackendInput( translate_string=pb.TranslateStringIn(group=group, key=key, args=args) ) ).translate_string
def register_tags(self, tags: str, usn: Optional[int], clear_first: bool) -> bool: if usn is None: preserve_usn = False usn_ = 0 else: usn_ = usn preserve_usn = True return self._run_command( pb.BackendInput(register_tags=pb.RegisterTagsIn( tags=tags, usn=usn_, preserve_usn=preserve_usn, clear_first=clear_first, ))).register_tags
def sched_timing_today( self, created_secs: int, created_mins_west: int, now_secs: int, now_mins_west: int, rollover: int, ) -> SchedTimingToday: return self._run_command( pb.BackendInput(sched_timing_today=pb.SchedTimingTodayIn( created_secs=created_secs, created_mins_west=created_mins_west, now_secs=now_secs, now_mins_west=now_mins_west, rollover_hour=rollover, ))).sched_timing_today
def render_card( self, qfmt: str, afmt: str, fields: Dict[str, str], card_ord: int ) -> Tuple[TemplateReplacementList, TemplateReplacementList]: out = self._run_command( pb.BackendInput(render_card=pb.RenderCardIn( question_template=qfmt, answer_template=afmt, fields=fields, card_ordinal=card_ord, ))).render_card qnodes = proto_replacement_list_to_native( out.question_nodes) # type: ignore anodes = proto_replacement_list_to_native( out.answer_nodes) # type: ignore return (qnodes, anodes)
def render_uncommitted_card(self, note: BackendNote, card_ord: int, template: Dict, fill_empty: bool) -> PartiallyRenderedCard: template_json = orjson.dumps(template) out = self._run_command( pb.BackendInput(render_uncommitted_card=pb.RenderUncommittedCardIn( note=note, template=template_json, card_ord=card_ord, fill_empty=fill_empty, ))).render_uncommitted_card qnodes = proto_replacement_list_to_native( out.question_nodes) # type: ignore anodes = proto_replacement_list_to_native( out.answer_nodes) # type: ignore return PartiallyRenderedCard(qnodes, anodes)
def flatten_template( self, template: str, nonempty_fields: List[str] ) -> List[Union[str, TemplateReplacement]]: out = self._run_command( pb.BackendInput(flatten_template=pb.FlattenTemplateIn( template_text=template, nonempty_field_names=nonempty_fields))).flatten_template results: List[Union[str, TemplateReplacement]] = [] for node in out.nodes: if node.WhichOneof("value") == "text": results.append(node.text) else: results.append( TemplateReplacement( field_name=node.replacement.field_name, filters=list(node.replacement.filters), )) return results
def search_cards(self, search: str, order: Union[bool, str, int], reverse: bool = False) -> Sequence[int]: if isinstance(order, str): mode = pb.SortOrder(custom=order) elif order is True: mode = pb.SortOrder(from_config=pb.Empty()) elif order is False: mode = pb.SortOrder(none=pb.Empty()) else: # sadly we can't use the protobuf type in a Union, so we # have to accept an int and convert it kind = BuiltinSortKind.Value(BuiltinSortKind.Name(order)) mode = pb.SortOrder( builtin=pb.BuiltinSearchOrder(kind=kind, reverse=reverse)) return self._run_command( pb.BackendInput(search_cards=pb.SearchCardsIn( search=search, order=mode))).search_cards.card_ids
def find_and_replace( self, nids: List[int], search: str, repl: str, re: bool, nocase: bool, field_name: Optional[str], ) -> int: return self._run_command( pb.BackendInput(find_and_replace=pb.FindAndReplaceIn( nids=nids, search=search, replacement=repl, regex=re, match_case=not nocase, field_name=field_name, )), release_gil=True, ).find_and_replace