diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py
index 2f24babe6..cd21d7018 100644
--- a/pylib/anki/stats.py
+++ b/pylib/anki/stats.py
@@ -6,7 +6,7 @@ from __future__ import annotations
import datetime
import json
import time
-from typing import Any, Dict, List, Optional, Tuple
+from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
import anki
from anki.consts import *
@@ -17,6 +17,7 @@ from anki.utils import ids2str
# Card stats
##########################################################################
+
PERIOD_MONTH = 0
PERIOD_YEAR = 1
PERIOD_LIFE = 2
@@ -71,15 +72,15 @@ class CardStats:
self.txt += ""
return self.txt
- def addLine(self, k, v) -> None:
+ def addLine(self, k: str, v: Union[int, str]) -> None:
self.txt += self.makeLine(k, v)
- def makeLine(self, k, v) -> str:
+ def makeLine(self, k: str, v: Union[str, int]) -> str:
txt = "
"
txt += "%s | %s |
" % (k, v)
return txt
- def date(self, tm) -> str:
+ def date(self, tm: float) -> str:
return time.strftime("%Y-%m-%d", time.localtime(tm))
def time(self, tm: float) -> str:
@@ -114,7 +115,7 @@ class CollectionStats:
self.wholeCollection = False
# assumes jquery & plot are available in document
- def report(self, type=PERIOD_MONTH) -> str:
+ def report(self, type: int = PERIOD_MONTH) -> str:
# 0=month, 1=year, 2=deck life
self.type = type
from .statsbg import bg
@@ -131,7 +132,7 @@ class CollectionStats:
txt += self._section(self.footer())
return "%s" % txt
- def _section(self, txt) -> str:
+ def _section(self, txt: str) -> str:
return "%s
" % txt
css = """
@@ -212,7 +213,7 @@ from revlog where id > ? """
# Due and cumulative due
######################################################################
- def get_start_end_chunk(self, by="review") -> Tuple[int, Optional[int], int]:
+ def get_start_end_chunk(self, by: str = "review") -> Tuple[int, Optional[int], int]:
start = 0
if self.type == PERIOD_MONTH:
end, chunk = 31, 1
@@ -273,7 +274,7 @@ from revlog where id > ? """
txt += self._dueInfo(tot, len(totd) * chunk)
return txt
- def _dueInfo(self, tot, num) -> str:
+ def _dueInfo(self, tot: int, num: int) -> str:
i: List[str] = []
self._line(
i, _("Total"), self.col.tr(TR.STATISTICS_REVIEWS, reviews=tot),
@@ -290,7 +291,9 @@ and due = ?"""
self._line(i, _("Due tomorrow"), tomorrow)
return self._lineTbl(i)
- def _due(self, start=None, end=None, chunk=1) -> Any:
+ def _due(
+ self, start: Optional[int] = None, end: Optional[int] = None, chunk: int = 1
+ ) -> Any:
lim = ""
if start is not None:
lim += " and due-:today >= %d" % start
@@ -414,7 +417,13 @@ group by day order by day"""
return self._section(txt1) + self._section(txt2)
def _ansInfo(
- self, totd, studied, first, unit, convHours=False, total=None
+ self,
+ totd: List[Tuple[int, float]],
+ studied: int,
+ first: int,
+ unit: str,
+ convHours: bool = False,
+ total: Optional[int] = None,
) -> Tuple[str, int]:
assert totd
tot = totd[-1][1]
@@ -460,14 +469,16 @@ group by day order by day"""
)
return self._lineTbl(i), int(tot)
- def _splitRepData(self, data, spec) -> Tuple[List[dict], List[Tuple[Any, Any]]]:
+ def _splitRepData(
+ self, data: List[Tuple[Any, ...]], spec: Sequence[Tuple[int, str, str]],
+ ) -> Tuple[List[Dict[str, Any]], List[Tuple[Any, Any]]]:
sep: Dict[int, Any] = {}
totcnt = {}
totd: Dict[int, Any] = {}
alltot = []
- allcnt = 0
+ allcnt: float = 0
for (n, col, lab) in spec:
- totcnt[n] = 0
+ totcnt[n] = 0.0
totd[n] = []
for row in data:
for (n, col, lab) in spec:
@@ -497,7 +508,7 @@ group by day order by day"""
)
return (ret, alltot)
- def _added(self, num=7, chunk=1) -> Any:
+ def _added(self, num: Optional[int] = 7, chunk: int = 1) -> Any:
lims = []
if num is not None:
lims.append(
@@ -525,7 +536,7 @@ group by day order by day"""
chunk=chunk,
)
- def _done(self, num=7, chunk=1) -> Any:
+ def _done(self, num: Optional[int] = 7, chunk: int = 1) -> Any:
lims = []
if num is not None:
lims.append(
@@ -637,7 +648,7 @@ group by day order by day)"""
)
return txt + self._lineTbl(i)
- def _ivls(self) -> Tuple[list, int]:
+ def _ivls(self) -> Tuple[List[Any], int]:
start, end, chunk = self.get_start_end_chunk()
lim = "and grp <= %d" % end if end else ""
data = [
@@ -712,7 +723,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = {QUEUE
txt += self._easeInfo(eases)
return txt
- def _easeInfo(self, eases) -> str:
+ def _easeInfo(self, eases: List[Tuple[int, int, int]]) -> str:
types = {PERIOD_MONTH: [0, 0], PERIOD_YEAR: [0, 0], PERIOD_LIFE: [0, 0]}
for (type, ease, cnt) in eases:
if ease == 1:
@@ -909,7 +920,9 @@ when you answer "good" on a review."""
)
return txt
- def _line(self, i, a, b, bold=True) -> None:
+ def _line(
+ self, i: List[str], a: str, b: Union[int, str], bold: bool = True
+ ) -> None:
# T: Symbols separating first and second column in a statistics table. Eg in "Total: 3 reviews".
colon = _(":")
if bold:
@@ -923,7 +936,7 @@ when you answer "good" on a review."""
% (a, colon, b)
)
- def _lineTbl(self, i) -> str:
+ def _lineTbl(self, i: List[str]) -> str:
return ""
def _factors(self) -> Any:
@@ -969,7 +982,14 @@ from cards where did in %s"""
######################################################################
def _graph(
- self, id, data, conf=None, type="bars", xunit=1, ylabel=_("Cards"), ylabel2=""
+ self,
+ id: str,
+ data: Any,
+ conf: Optional[Any] = None,
+ type: str = "bars",
+ xunit: int = 1,
+ ylabel: str = _("Cards"),
+ ylabel2: str = "",
) -> str:
if conf is None:
conf = {}
@@ -1088,10 +1108,10 @@ $(function () {
self.col.decks.active()
)
- def _title(self, title, subtitle="") -> str:
+ def _title(self, title: str, subtitle: str = "") -> str:
return "%s
%s" % (title, subtitle)
- def _deckAge(self, by) -> int:
+ def _deckAge(self, by: str) -> int:
lim = self._revlogLimit()
if lim:
lim = " where " + lim
@@ -1112,7 +1132,7 @@ $(function () {
return None
return end * chunk
- def _avgDay(self, tot, num, unit) -> str:
+ def _avgDay(self, tot: float, num: int, unit: str) -> str:
vals = []
try:
vals.append(_("%(a)0.1f %(b)s/day") % dict(a=tot / float(num), b=unit))