def new_field(self, name: str) -> Field: assert isinstance(name, str) nt = from_json_bytes( self.col.backend.get_stock_notetype_legacy( StockNoteType.STOCK_NOTE_TYPE_BASIC)) field = nt["flds"][0] field["name"] = name field["ord"] = None return field
def restoreToDefault(self, conf) -> None: oldOrder = conf["new"]["order"] new = from_json_bytes(self.col.backend.new_deck_config_legacy()) new["id"] = conf["id"] new["name"] = conf["name"] self.update_config(new) # if it was previously randomized, re-sort if not oldOrder: self.col.sched.resortConf(new)
def new_template(self, name: str) -> Template: nt = from_json_bytes( self.col.backend.get_stock_notetype_legacy( StockNoteType.STOCK_NOTE_TYPE_BASIC)) template = nt["tmpls"][0] template["name"] = name template["qfmt"] = "" template["afmt"] = "" template["ord"] = None return template
def new(self, name: str) -> NoteType: "Create a new model, and return it." # caller should call save() after modifying nt = from_json_bytes( self.col.backend.get_stock_notetype_legacy( StockNoteType.STOCK_NOTE_TYPE_BASIC)) nt["flds"] = [] nt["tmpls"] = [] nt["name"] = name return nt
def add_config( self, name: str, clone_from: Optional[DeckConfig] = None ) -> DeckConfig: if clone_from is not None: conf = copy.deepcopy(clone_from) conf["id"] = 0 else: conf = from_json_bytes(self.col.backend.new_deck_config_legacy()) conf["name"] = name self.update_config(conf) return conf
def get(self, id: int) -> Optional[NoteType]: "Get model with ID, or None." # deal with various legacy input types if id is None: return None elif isinstance(id, str): id = int(id) nt = self._get_cached(id) if not nt: try: nt = from_json_bytes(self.col.backend.get_notetype_legacy(id)) self._update_cache(nt) except NotFoundError: return None return nt
def get_stock_notetypes( col: Collection, ) -> List[Tuple[str, Callable[[Collection], NoteType]]]: out: List[Tuple[str, Callable[[Collection], NoteType]]] = [] # add standard for (kind, func) in [ (StockNoteType.STOCK_NOTE_TYPE_BASIC, addBasicModel), (StockNoteType.STOCK_NOTE_TYPE_BASIC_TYPING, addBasicTypingModel), (StockNoteType.STOCK_NOTE_TYPE_BASIC_AND_REVERSED, addForwardReverse), ( StockNoteType.STOCK_NOTE_TYPE_BASIC_OPTIONAL_REVERSED, addForwardOptionalReverse, ), (StockNoteType.STOCK_NOTE_TYPE_CLOZE, addClozeModel), ]: 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: if not isinstance(name_or_func, str): name = name_or_func() else: name = name_or_func out.append((name, func)) return out
def graph_data() -> bytes: args = from_json_bytes(request.data) return aqt.mw.col.backend.graphs(search=args["search"], days=args["days"])
def allroutes(pathin): directory, path = _redirectWebExports(pathin) try: isdir = os.path.isdir(os.path.join(directory, path)) except ValueError: return flask.make_response( "Path for '%s - %s' is too long!" % (directory, path), HTTPStatus.BAD_REQUEST, ) directory = os.path.realpath(directory) path = os.path.normpath(path) fullpath = os.path.realpath(os.path.join(directory, path)) # protect against directory transversal: https://security.openstack.org/guidelines/dg_using-file-paths.html if not fullpath.startswith(directory): return flask.make_response( "Path for '%s - %s' is a security leak!" % (directory, path), HTTPStatus.FORBIDDEN, ) if isdir: return flask.make_response( "Path for '%s - %s' is a directory (not supported)!" % (directory, path), HTTPStatus.FORBIDDEN, ) if devMode: print("Sending file '%s - %s'" % (directory, path)) try: if flask.request.method == "POST": if path == "graphData": body = request.data data = graph_data(aqt.mw.col, **from_json_bytes(body)) elif path == "i18nResources": data = aqt.mw.col.backend.i18n_resources() else: return flask.make_response( "Post request to '%s - %s' is a security leak!" % (directory, path), HTTPStatus.FORBIDDEN, ) response = flask.make_response(data) response.headers["Content-Type"] = "application/binary" return response if fullpath.endswith(".css"): # some users may have invalid mime type in the Windows registry mimetype = "text/css" else: # autodetect mimetype = None return flask.send_file(fullpath, mimetype=mimetype, conditional=True) except Exception as error: if devMode: print( "Caught HTTP server exception,\n%s" % "".join(traceback.format_exception(*sys.exc_info())), ) # swallow it - user likely surfed away from # review screen before an image had finished # downloading return flask.make_response( "For path '%s - %s' %s!" % (directory, path, error), HTTPStatus.INTERNAL_SERVER_ERROR, )
def add_stock_notetype(col: Collection, kind: StockNoteType) -> NoteType: m = from_json_bytes(col.backend.get_stock_notetype_legacy(kind)) col.models.add(m) return m
def get_config(self, conf_id: int) -> Any: try: return from_json_bytes( self.col.backend.get_deck_config_legacy(conf_id)) except NotFoundError: return None
def all_config(self) -> List: "A list of all deck config." return list(from_json_bytes(self.col.backend.all_deck_config_legacy()))
def new_deck_legacy(self, filtered: bool) -> Dict: return from_json_bytes(self.col.backend.new_deck_legacy(filtered))
def get_all_legacy(self) -> List[Dict]: return list( from_json_bytes(self.col.backend.get_all_decks_legacy()).values())
def get_legacy(self, did: int) -> Optional[Dict]: try: return from_json_bytes(self.col.backend.get_deck_legacy(did)) except NotFoundError: return None
def get_immutable(self, key: str) -> Any: try: return from_json_bytes(self.col.backend.get_config_json(key)) except NotFoundError as exc: raise KeyError from exc