diff --git a/pylib/anki/importing/supermemo_xml.py b/pylib/anki/importing/supermemo_xml.py index 07ddb1c4c..a326daf7d 100644 --- a/pylib/anki/importing/supermemo_xml.py +++ b/pylib/anki/importing/supermemo_xml.py @@ -8,8 +8,11 @@ import sys import time import unicodedata from string import capwords +from typing import List, Optional, Union from xml.dom import minidom +from xml.dom.minidom import Element, Text +from anki.collection import _Collection from anki.importing.noteimp import ForeignCard, ForeignNote, NoteImporter from anki.lang import _, ngettext from anki.stdmodels import addBasicModel @@ -26,7 +29,7 @@ class SmartDict(dict): x.get('first_name'). """ - def __init__(self, *a, **kw): + def __init__(self, *a, **kw) -> None: if a: if isinstance(type(a[0]), dict): kw.update(a[0]) @@ -42,7 +45,7 @@ class SmartDict(dict): class SuperMemoElement(SmartDict): "SmartDict wrapper to store SM Element data" - def __init__(self, *a, **kw): + def __init__(self, *a, **kw) -> None: SmartDict.__init__(self, *a, **kw) # default content self.__dict__["lTitle"] = None @@ -80,7 +83,7 @@ class SupermemoXmlImporter(NoteImporter): Code should be upgrade to support importing of SM2006 exports. """ - def __init__(self, col, file): + def __init__(self, col: _Collection, file: str) -> None: """Initialize internal varables. Pameters to be exposed to GUI are stored in self.META""" NoteImporter.__init__(self, col, file) @@ -124,13 +127,13 @@ class SupermemoXmlImporter(NoteImporter): ## TOOLS - def _fudgeText(self, text): + def _fudgeText(self, text: str) -> str: "Replace sm syntax to Anki syntax" text = text.replace("\n\r", "
") text = text.replace("\n", "
") return text - def _unicode2ascii(self, str): + def _unicode2ascii(self, str: str) -> str: "Remove diacritic punctuation from strings (titles)" return "".join( [ @@ -140,7 +143,7 @@ class SupermemoXmlImporter(NoteImporter): ] ) - def _decode_htmlescapes(self, s): + def _decode_htmlescapes(self, s: str) -> str: """Unescape HTML code.""" # In case of bad formated html you can import MinimalSoup etc.. see btflsoup source code from bs4 import BeautifulSoup as btflsoup @@ -153,7 +156,7 @@ class SupermemoXmlImporter(NoteImporter): return str(btflsoup(s, "html.parser")) - def _afactor2efactor(self, af): + def _afactor2efactor(self, af: float) -> float: # Adapted from # Ranges for A-factors and E-factors @@ -177,7 +180,7 @@ class SupermemoXmlImporter(NoteImporter): ## DEFAULT IMPORTER METHODS - def foreignNotes(self): + def foreignNotes(self) -> List[ForeignNote]: # Load file and parse it by minidom self.loadSource(self.file) @@ -195,12 +198,12 @@ class SupermemoXmlImporter(NoteImporter): ) return self.notes - def fields(self): + def fields(self) -> int: return 2 ## PARSER METHODS - def addItemToCards(self, item): + def addItemToCards(self, item: SuperMemoElement) -> None: "This method actually do conversion" # new anki card @@ -274,7 +277,7 @@ class SupermemoXmlImporter(NoteImporter): self.notes.append(note) - def logger(self, text, level=1): + def logger(self, text: str, level: int = 1) -> None: "Wrapper for Anki logger" dLevels = {0: "", 1: "Info", 2: "Verbose", 3: "Debug"} @@ -316,7 +319,7 @@ class SupermemoXmlImporter(NoteImporter): return io.StringIO(str(source)) - def loadSource(self, source): + def loadSource(self, source: str) -> None: """Load source file and parse with xml.dom.minidom""" self.source = source self.logger("Load started...") @@ -326,7 +329,7 @@ class SupermemoXmlImporter(NoteImporter): self.logger("Load done.") # PARSE - def parse(self, node=None): + def parse(self, node: Optional[Union[Text, Element]] = None) -> None: "Parse method - parses document elements" if node is None and self.xmldoc is not None: @@ -344,7 +347,7 @@ class SupermemoXmlImporter(NoteImporter): self.parse(node.documentElement) - def parse_Element(self, node): + def parse_Element(self, node: Element) -> None: "Parse XML element" _method = "do_%s" % node.tagName @@ -355,7 +358,7 @@ class SupermemoXmlImporter(NoteImporter): self.logger("No handler for method %s" % _method, level=3) # print traceback.print_exc() - def parse_Text(self, node): + def parse_Text(self, node: Text) -> None: "Parse text inside elements. Text is stored into local buffer." text = node.data @@ -368,13 +371,13 @@ class SupermemoXmlImporter(NoteImporter): # pass # DO - def do_SuperMemoCollection(self, node): + def do_SuperMemoCollection(self, node: Element) -> None: "Process SM Collection" for child in node.childNodes: self.parse(child) - def do_SuperMemoElement(self, node): + def do_SuperMemoElement(self, node: Element) -> None: "Process SM Element (Type - Title,Topics)" self.logger("=" * 45, level=3) @@ -426,14 +429,14 @@ class SupermemoXmlImporter(NoteImporter): t = self.cntMeta["title"].pop() self.logger("End of topic \t- %s" % (t), level=2) - def do_Content(self, node): + def do_Content(self, node: Element) -> None: "Process SM element Content" for child in node.childNodes: if hasattr(child, "tagName") and child.firstChild is not None: self.cntElm[-1][child.tagName] = child.firstChild.data - def do_LearningData(self, node): + def do_LearningData(self, node: Element) -> None: "Process SM element LearningData" for child in node.childNodes: @@ -450,7 +453,7 @@ class SupermemoXmlImporter(NoteImporter): # for child in node.childNodes: self.parse(child) # self.cntElm[-1][node.tagName]=self.cntBuf.pop() - def do_Title(self, node): + def do_Title(self, node: Element) -> None: "Process SM element Title" t = self._decode_htmlescapes(node.firstChild.data) @@ -459,7 +462,7 @@ class SupermemoXmlImporter(NoteImporter): self.cntElm[-1]["lTitle"] = self.cntMeta["title"] self.logger("Start of topic \t- " + " / ".join(self.cntMeta["title"]), level=2) - def do_Type(self, node): + def do_Type(self, node: Element) -> None: "Process SM element Type" if len(self.cntBuf) >= 1: