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