mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
add a bunch of extra hints for mypy
This commit is contained in:
parent
d8d7e78b6b
commit
12093f2f2e
7 changed files with 46 additions and 51 deletions
|
@ -8,10 +8,9 @@ from anki.storage import Collection
|
|||
from anki.utils import intTime, splitFields, joinFields
|
||||
from anki.importing.base import Importer
|
||||
from anki.lang import _
|
||||
from typing import Any, Optional
|
||||
|
||||
from typing import Any, Optional, Dict, Tuple, List
|
||||
from anki.collection import _Collection
|
||||
from typing import List, Union
|
||||
|
||||
GUID = 1
|
||||
MID = 2
|
||||
MOD = 3
|
||||
|
@ -19,15 +18,16 @@ MOD = 3
|
|||
class Anki2Importer(Importer):
|
||||
|
||||
needMapper = False
|
||||
deckPrefix = None
|
||||
deckPrefix: Optional[str] = None
|
||||
allowUpdate = True
|
||||
src: _Collection
|
||||
dst: _Collection
|
||||
|
||||
def __init__(self, col: _Collection, file: str) -> None:
|
||||
super().__init__(col, file)
|
||||
|
||||
# set later, defined here for typechecking
|
||||
self.src = None
|
||||
self._decks = {}
|
||||
self._decks: Dict[int,int] = {}
|
||||
self.mustResetLearning = False
|
||||
|
||||
def run(self, media: None = None) -> None:
|
||||
|
@ -79,7 +79,7 @@ class Anki2Importer(Importer):
|
|||
|
||||
def _importNotes(self) -> None:
|
||||
# build guid -> (id,mod,mid) hash & map of existing note ids
|
||||
self._notes = {}
|
||||
self._notes: Dict[str, Tuple[int,int,int]] = {}
|
||||
existing = {}
|
||||
for id, guid, mod, mid in self.dst.db.execute(
|
||||
"select id, guid, mod, mid from notes"):
|
||||
|
@ -87,10 +87,10 @@ class Anki2Importer(Importer):
|
|||
existing[id] = True
|
||||
# we may need to rewrite the guid if the model schemas don't match,
|
||||
# so we need to keep track of the changes for the card import stage
|
||||
self._changedGuids = {}
|
||||
self._changedGuids: Dict[str, bool] = {}
|
||||
# we ignore updates to changed schemas. we need to note the ignored
|
||||
# guids, so we avoid importing invalid cards
|
||||
self._ignoredGuids = {}
|
||||
self._ignoredGuids: Dict[str, bool] = {}
|
||||
# iterate over source collection
|
||||
add = []
|
||||
update = []
|
||||
|
@ -188,7 +188,7 @@ class Anki2Importer(Importer):
|
|||
|
||||
# determine if note is a duplicate, and adjust mid and/or guid as required
|
||||
# returns true if note should be added
|
||||
def _uniquifyNote(self, note: List[Union[int, str]]) -> bool:
|
||||
def _uniquifyNote(self, note: List[Any]) -> bool:
|
||||
origGuid = note[GUID]
|
||||
srcMid = note[MID]
|
||||
dstMid = self._mid(srcMid)
|
||||
|
@ -212,7 +212,7 @@ class Anki2Importer(Importer):
|
|||
|
||||
def _prepareModels(self) -> None:
|
||||
"Prepare index of schema hashes."
|
||||
self._modelMap = {}
|
||||
self._modelMap: Dict[int, int] = {}
|
||||
|
||||
def _mid(self, srcMid: int) -> Any:
|
||||
"Return local id for remote MID."
|
||||
|
@ -302,7 +302,7 @@ class Anki2Importer(Importer):
|
|||
if self.mustResetLearning:
|
||||
self.src.changeSchedulerVer(2)
|
||||
# build map of (guid, ord) -> cid and used id cache
|
||||
self._cards = {}
|
||||
self._cards: Dict[Tuple[str,int], int] = {}
|
||||
existing = {}
|
||||
for guid, ord, cid in self.dst.db.execute(
|
||||
"select f.guid, c.ord, c.id from cards c, notes f "
|
||||
|
@ -403,7 +403,7 @@ insert or ignore into revlog values (?,?,?,?,?,?,?,?,?)""", revlog)
|
|||
with open(path, "rb") as f:
|
||||
return f.read()
|
||||
except (IOError, OSError):
|
||||
return
|
||||
return b''
|
||||
|
||||
def _srcMediaData(self, fname: str) -> bytes:
|
||||
"Data for FNAME in src collection."
|
||||
|
@ -423,8 +423,8 @@ insert or ignore into revlog values (?,?,?,?,?,?,?,?,?)""", revlog)
|
|||
# the user likely used subdirectories
|
||||
pass
|
||||
|
||||
def _mungeMedia(self, mid: int, fields: str) -> str:
|
||||
fields = splitFields(fields)
|
||||
def _mungeMedia(self, mid: int, fieldsStr: str) -> str:
|
||||
fields = splitFields(fieldsStr)
|
||||
def repl(match):
|
||||
fname = match.group("fname")
|
||||
srcData = self._srcMediaData(fname)
|
||||
|
|
|
@ -7,18 +7,13 @@ import unicodedata
|
|||
import json
|
||||
from anki.utils import tmpfile
|
||||
from anki.importing.anki2 import Anki2Importer
|
||||
from typing import Any
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from anki.collection import _Collection
|
||||
class AnkiPackageImporter(Anki2Importer):
|
||||
nameToNum: Dict[str, str]
|
||||
zip: Optional[zipfile.ZipFile]
|
||||
|
||||
def __init__(self, col: _Collection, file: str) -> None:
|
||||
super().__init__(col, file)
|
||||
# set later; set here for typechecking
|
||||
self.nameToNum = {}
|
||||
self.zip = None
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self) -> None: # type: ignore
|
||||
# extract the deck from the zip file
|
||||
self.zip = z = zipfile.ZipFile(self.file)
|
||||
# v2 scheduler?
|
||||
|
@ -56,5 +51,5 @@ class AnkiPackageImporter(Anki2Importer):
|
|||
|
||||
def _srcMediaData(self, fname: str) -> Any:
|
||||
if fname in self.nameToNum:
|
||||
return self.zip.read(self.nameToNum[fname])
|
||||
return self.zip.read(self.nameToNum[fname]) # pytype: disable=attribute-error
|
||||
return None
|
||||
|
|
|
@ -3,20 +3,21 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from anki.utils import maxID
|
||||
from typing import Any
|
||||
from typing import Any, Optional, List
|
||||
from anki.collection import _Collection
|
||||
|
||||
# Base importer
|
||||
##########################################################################
|
||||
|
||||
from anki.collection import _Collection
|
||||
class Importer:
|
||||
|
||||
needMapper = False
|
||||
needDelimiter = False
|
||||
dst: Optional[_Collection]
|
||||
|
||||
def __init__(self, col: _Collection, file: str) -> None:
|
||||
self.file = file
|
||||
self.log = []
|
||||
self.log: List[str] = []
|
||||
self.col = col
|
||||
self.total = 0
|
||||
self.dst = None
|
||||
|
|
|
@ -7,8 +7,7 @@ import re
|
|||
|
||||
from anki.importing.noteimp import NoteImporter, ForeignNote
|
||||
from anki.lang import _
|
||||
from typing import List
|
||||
|
||||
from typing import List, Optional, Any, TextIO, Union
|
||||
|
||||
from anki.collection import _Collection
|
||||
class TextImporter(NoteImporter):
|
||||
|
@ -19,10 +18,12 @@ class TextImporter(NoteImporter):
|
|||
def __init__(self, col: _Collection, file: str) -> None:
|
||||
NoteImporter.__init__(self, col, file)
|
||||
self.lines = None
|
||||
self.fileobj = None
|
||||
self.delimiter = None
|
||||
self.tagsToAdd = []
|
||||
self.fileobj: Optional[TextIO] = None
|
||||
self.delimiter: Optional[str] = None
|
||||
self.tagsToAdd: List[str] = []
|
||||
self.numFields = 0
|
||||
self.dialect: Optional[Any]
|
||||
self.data: Optional[Union[str, List[str]]]
|
||||
|
||||
def foreignNotes(self) -> List[ForeignNote]:
|
||||
self.open()
|
||||
|
|
|
@ -12,20 +12,19 @@ from anki.utils import fieldChecksum, guid64, timestampID, \
|
|||
joinFields, intTime, splitFields
|
||||
from anki.importing.base import Importer
|
||||
from anki.lang import ngettext
|
||||
from typing import Any, List, Optional
|
||||
from typing import Any, List, Optional, Tuple, Dict, Union
|
||||
from anki.collection import _Collection
|
||||
|
||||
# Stores a list of fields, tags and deck
|
||||
######################################################################
|
||||
|
||||
from anki.collection import _Collection
|
||||
from typing import List, Optional, Union
|
||||
class ForeignNote:
|
||||
"An temporary object storing fields and attributes."
|
||||
def __init__(self) -> None:
|
||||
self.fields = []
|
||||
self.tags = []
|
||||
self.fields: List[str] = []
|
||||
self.tags: List[str] = []
|
||||
self.deck = None
|
||||
self.cards = {} # map of ord -> card
|
||||
self.cards: Dict[int,ForeignCard] = {} # map of ord -> card
|
||||
self.fieldsStr = ""
|
||||
|
||||
class ForeignCard:
|
||||
|
@ -56,12 +55,12 @@ class NoteImporter(Importer):
|
|||
needDelimiter = False
|
||||
allowHTML = False
|
||||
importMode = 0
|
||||
mapping: Optional[List[str]]
|
||||
|
||||
def __init__(self, col: _Collection, file: str) -> None:
|
||||
Importer.__init__(self, col, file)
|
||||
self.model = col.models.current()
|
||||
self.mapping = None
|
||||
self._deckMap = {}
|
||||
self._tagsMapped = False
|
||||
|
||||
def run(self) -> None:
|
||||
|
@ -105,14 +104,14 @@ class NoteImporter(Importer):
|
|||
if f == "_tags":
|
||||
self._tagsMapped = True
|
||||
# gather checks for duplicate comparison
|
||||
csums = {}
|
||||
csums: Dict[str, List[int]] = {}
|
||||
for csum, id in self.col.db.execute(
|
||||
"select csum, id from notes where mid = ?", self.model['id']):
|
||||
if csum in csums:
|
||||
csums[csum].append(id)
|
||||
else:
|
||||
csums[csum] = [id]
|
||||
firsts = {}
|
||||
firsts: Dict[str, bool] = {}
|
||||
fld0idx = self.mapping.index(self.model['flds'][0]['name'])
|
||||
self._fmap = self.col.models.fieldMap(self.model)
|
||||
self._nextID = timestampID(self.col.db, "notes")
|
||||
|
@ -122,11 +121,11 @@ class NoteImporter(Importer):
|
|||
updateLogTxt = _("First field matched: %s")
|
||||
dupeLogTxt = _("Added duplicate with first field: %s")
|
||||
new = []
|
||||
self._ids = []
|
||||
self._cards = []
|
||||
self._ids: List[int] = []
|
||||
self._cards: List[Tuple] = []
|
||||
self._emptyNotes = False
|
||||
dupeCount = 0
|
||||
dupes = []
|
||||
dupes: List[str] = []
|
||||
for n in notes:
|
||||
for c in range(len(n.fields)):
|
||||
if not self.allowHTML:
|
||||
|
@ -228,7 +227,7 @@ content in the text file to the correct fields."""))
|
|||
self._nextID += 1
|
||||
self._ids.append(id)
|
||||
if not self.processFields(n):
|
||||
return
|
||||
return None
|
||||
# note id for card updates later
|
||||
for ord, c in list(n.cards.items()):
|
||||
self._cards.append((id, ord, c))
|
||||
|
@ -245,7 +244,7 @@ content in the text file to the correct fields."""))
|
|||
def updateData(self, n: ForeignNote, id: int, sflds: List[str]) -> Optional[list]:
|
||||
self._ids.append(id)
|
||||
if not self.processFields(n, sflds):
|
||||
return
|
||||
return None
|
||||
if self._tagsMapped:
|
||||
self.col.tags.register(n.tags)
|
||||
tags = self.col.tags.join(n.tags)
|
||||
|
|
|
@ -6,7 +6,6 @@ import gzip, math, random, time, html
|
|||
import xml.etree.ElementTree as ET
|
||||
from anki.importing.noteimp import NoteImporter, ForeignNote, ForeignCard
|
||||
from anki.stdmodels import addForwardReverse
|
||||
from typing import List
|
||||
|
||||
ONE_DAY = 60*60*24
|
||||
|
||||
|
@ -29,7 +28,7 @@ class PaukerImporter(NoteImporter):
|
|||
'''Pauker is Front/Back'''
|
||||
return 2
|
||||
|
||||
def foreignNotes(self) -> List[ForeignNote]:
|
||||
def foreignNotes(self):
|
||||
'''Build and return a list of notes.'''
|
||||
notes = []
|
||||
|
||||
|
@ -67,7 +66,7 @@ class PaukerImporter(NoteImporter):
|
|||
|
||||
return notes
|
||||
|
||||
def _learnedCard(self, batch, timestamp) -> ForeignCard:
|
||||
def _learnedCard(self, batch, timestamp):
|
||||
ivl = math.exp(batch)
|
||||
now = time.time()
|
||||
due = ivl - (now - timestamp/1000.0)/ONE_DAY
|
||||
|
|
|
@ -276,7 +276,7 @@ def _incGuid(guid) -> str:
|
|||
def joinFields(list: List[str]) -> str:
|
||||
return "\x1f".join(list)
|
||||
|
||||
def splitFields(string: str) -> Any:
|
||||
def splitFields(string: str) -> List[str]:
|
||||
return string.split("\x1f")
|
||||
|
||||
# Checksums
|
||||
|
|
Loading…
Reference in a new issue