genanki2 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- genanki2/__init__.py +136 -0
- genanki2/_default_rows.py +94 -0
- genanki2/_dummy_collection.anki2 +0 -0
- genanki2/_proto/__init__.py +94 -0
- genanki2/_proto/descriptors.binpb +0 -0
- genanki2/_schema.py +167 -0
- genanki2/_typed_schema.py +145 -0
- genanki2/_unicode_ages.py +54 -0
- genanki2/api.py +271 -0
- genanki2/builtins.py +213 -0
- genanki2/datetime.py +103 -0
- genanki2/errors.py +35 -0
- genanki2/freezable.py +238 -0
- genanki2/idgen.py +123 -0
- genanki2/io_utils.py +230 -0
- genanki2/models/__init__.py +0 -0
- genanki2/models/_card_maker.py +248 -0
- genanki2/models/annotations.py +154 -0
- genanki2/models/base.py +737 -0
- genanki2/models/card.py +995 -0
- genanki2/models/collection.py +2124 -0
- genanki2/models/collection_metadata.py +154 -0
- genanki2/models/config.py +131 -0
- genanki2/models/deck.py +679 -0
- genanki2/models/deck_config.py +647 -0
- genanki2/models/field.py +175 -0
- genanki2/models/grave.py +103 -0
- genanki2/models/media_entries.py +623 -0
- genanki2/models/note.py +601 -0
- genanki2/models/notetype.py +1080 -0
- genanki2/models/package.py +1337 -0
- genanki2/models/package_metadata.py +172 -0
- genanki2/models/review.py +285 -0
- genanki2/models/serialization_context.py +33 -0
- genanki2/models/tag.py +61 -0
- genanki2/models/template.py +371 -0
- genanki2/py.typed +0 -0
- genanki2/settings.py +159 -0
- genanki2/sqlite.py +299 -0
- genanki2/text.py +1109 -0
- genanki2/time.py +19 -0
- genanki2/utils.py +90 -0
- genanki2-0.1.0.dist-info/METADATA +474 -0
- genanki2-0.1.0.dist-info/RECORD +48 -0
- genanki2-0.1.0.dist-info/WHEEL +4 -0
- genanki2-0.1.0.dist-info/licenses/LICENSE +7 -0
- genanki2-0.1.0.dist-info/licenses/LICENSES/AGPL-3.0-or-later.txt +661 -0
- genanki2-0.1.0.dist-info/licenses/LICENSES/UNICODE-LICENSE-V3.txt +39 -0
genanki2/__init__.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import importlib.metadata
|
|
2
|
+
|
|
3
|
+
from .api import (
|
|
4
|
+
deck,
|
|
5
|
+
deck_config,
|
|
6
|
+
field,
|
|
7
|
+
filtered_deck,
|
|
8
|
+
note,
|
|
9
|
+
notetype,
|
|
10
|
+
package,
|
|
11
|
+
template,
|
|
12
|
+
)
|
|
13
|
+
from .builtins import (
|
|
14
|
+
BASIC_AND_REVERSED_NOTETYPE,
|
|
15
|
+
BASIC_NOTETYPE,
|
|
16
|
+
BASIC_OPTIONAL_REVERSED_NOTETYPE,
|
|
17
|
+
BASIC_TYPE_IN_THE_ANSWER_NOTETYPE,
|
|
18
|
+
BUILTIN_NOTETYPES,
|
|
19
|
+
CLOZE_NOTETYPE,
|
|
20
|
+
DEFAULT_DECK,
|
|
21
|
+
DEFAULT_DECK_CONFIG,
|
|
22
|
+
IMAGE_OCCLUSION_NOTETYPE,
|
|
23
|
+
builtin_notetype,
|
|
24
|
+
default_collection_metadata,
|
|
25
|
+
default_config_entries,
|
|
26
|
+
default_deck,
|
|
27
|
+
default_deck_config,
|
|
28
|
+
)
|
|
29
|
+
from .errors import (
|
|
30
|
+
CollectionReadError,
|
|
31
|
+
Genanki2Error,
|
|
32
|
+
Genanki2Warning,
|
|
33
|
+
PackageReadError,
|
|
34
|
+
)
|
|
35
|
+
from .idgen import guid, guid_for, monotonic_id
|
|
36
|
+
from .models.card import Card, CardData, CardFlag, CardQueue, CardType
|
|
37
|
+
from .models.collection import Collection
|
|
38
|
+
from .models.collection_metadata import CollectionMetadata
|
|
39
|
+
from .models.config import ConfigEntry
|
|
40
|
+
from .models.deck import Deck, DeckCommon, DeckFilteredKind, DeckNormalKind
|
|
41
|
+
from .models.deck_config import DeckConfig, DeckConfigInner
|
|
42
|
+
from .models.field import Field, FieldConfig
|
|
43
|
+
from .models.grave import Grave, GraveType
|
|
44
|
+
from .models.media_entries import MediaEntries, MediaEntry
|
|
45
|
+
from .models.note import Note
|
|
46
|
+
from .models.notetype import Notetype, NotetypeConfig
|
|
47
|
+
from .models.package import CollectionPackage, Package
|
|
48
|
+
from .models.package_metadata import PackageMetadata
|
|
49
|
+
from .models.review import Review, ReviewRating, ReviewType
|
|
50
|
+
from .models.tag import Tag
|
|
51
|
+
from .models.template import Template, TemplateConfig
|
|
52
|
+
from .settings import (
|
|
53
|
+
checks_disabled,
|
|
54
|
+
checks_enabled,
|
|
55
|
+
dbcheck_repairs_disabled,
|
|
56
|
+
dbcheck_repairs_enabled,
|
|
57
|
+
timestamping_disabled,
|
|
58
|
+
timestamping_enabled,
|
|
59
|
+
warnings_disabled,
|
|
60
|
+
warnings_enabled,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
__version__: str = importlib.metadata.version("genanki2")
|
|
64
|
+
|
|
65
|
+
__all__ = [
|
|
66
|
+
"BASIC_AND_REVERSED_NOTETYPE",
|
|
67
|
+
"BASIC_NOTETYPE",
|
|
68
|
+
"BASIC_OPTIONAL_REVERSED_NOTETYPE",
|
|
69
|
+
"BASIC_TYPE_IN_THE_ANSWER_NOTETYPE",
|
|
70
|
+
"BUILTIN_NOTETYPES",
|
|
71
|
+
"CLOZE_NOTETYPE",
|
|
72
|
+
"DEFAULT_DECK",
|
|
73
|
+
"DEFAULT_DECK_CONFIG",
|
|
74
|
+
"IMAGE_OCCLUSION_NOTETYPE",
|
|
75
|
+
"Card",
|
|
76
|
+
"CardData",
|
|
77
|
+
"CardFlag",
|
|
78
|
+
"CardQueue",
|
|
79
|
+
"CardType",
|
|
80
|
+
"Collection",
|
|
81
|
+
"CollectionMetadata",
|
|
82
|
+
"CollectionPackage",
|
|
83
|
+
"CollectionReadError",
|
|
84
|
+
"ConfigEntry",
|
|
85
|
+
"Deck",
|
|
86
|
+
"DeckCommon",
|
|
87
|
+
"DeckConfig",
|
|
88
|
+
"DeckConfigInner",
|
|
89
|
+
"DeckFilteredKind",
|
|
90
|
+
"DeckNormalKind",
|
|
91
|
+
"Field",
|
|
92
|
+
"FieldConfig",
|
|
93
|
+
"Genanki2Error",
|
|
94
|
+
"Genanki2Warning",
|
|
95
|
+
"Grave",
|
|
96
|
+
"GraveType",
|
|
97
|
+
"MediaEntries",
|
|
98
|
+
"MediaEntry",
|
|
99
|
+
"Note",
|
|
100
|
+
"Notetype",
|
|
101
|
+
"NotetypeConfig",
|
|
102
|
+
"Package",
|
|
103
|
+
"PackageMetadata",
|
|
104
|
+
"PackageReadError",
|
|
105
|
+
"Review",
|
|
106
|
+
"ReviewRating",
|
|
107
|
+
"ReviewType",
|
|
108
|
+
"Tag",
|
|
109
|
+
"Template",
|
|
110
|
+
"TemplateConfig",
|
|
111
|
+
"__version__",
|
|
112
|
+
"builtin_notetype",
|
|
113
|
+
"checks_disabled",
|
|
114
|
+
"checks_enabled",
|
|
115
|
+
"dbcheck_repairs_disabled",
|
|
116
|
+
"dbcheck_repairs_enabled",
|
|
117
|
+
"deck",
|
|
118
|
+
"deck_config",
|
|
119
|
+
"default_collection_metadata",
|
|
120
|
+
"default_config_entries",
|
|
121
|
+
"default_deck",
|
|
122
|
+
"default_deck_config",
|
|
123
|
+
"field",
|
|
124
|
+
"filtered_deck",
|
|
125
|
+
"guid",
|
|
126
|
+
"guid_for",
|
|
127
|
+
"monotonic_id",
|
|
128
|
+
"note",
|
|
129
|
+
"notetype",
|
|
130
|
+
"package",
|
|
131
|
+
"template",
|
|
132
|
+
"timestamping_disabled",
|
|
133
|
+
"timestamping_enabled",
|
|
134
|
+
"warnings_disabled",
|
|
135
|
+
"warnings_enabled",
|
|
136
|
+
]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Generated by scripts/dump_empty_collection_rows.py, do not edit.
|
|
2
|
+
# anki 26.08.1, collection schema version 18
|
|
3
|
+
|
|
4
|
+
# ========= TABLE col =========
|
|
5
|
+
table_col = [
|
|
6
|
+
{'id': 1, 'crt': 0, 'mod': 0, 'scm': 0, 'ver': 18, 'dty': 0, 'usn': 0, 'ls': 0, 'conf': '', 'models': '', 'decks': '', 'dconf': '', 'tags': ''},
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
# ========= TABLE notes =========
|
|
10
|
+
table_notes = []
|
|
11
|
+
|
|
12
|
+
# ========= TABLE cards =========
|
|
13
|
+
table_cards = []
|
|
14
|
+
|
|
15
|
+
# ========= TABLE revlog =========
|
|
16
|
+
table_revlog = []
|
|
17
|
+
|
|
18
|
+
# ========= TABLE deck_config =========
|
|
19
|
+
table_deck_config = [
|
|
20
|
+
{'id': 1, 'name': 'Default', 'mtime_secs': 0, 'usn': 0, 'config': b'\n\x08\x00\x00\x80?\x00\x00 A\x12\x04\x00\x00 A"\x1c\x00\x00\x80?\x00\x00\x80?\x00\x00\x80?\x00\x00\x80?\x00\x00\x80?\x00\x00\x80?\x00\x00\x80?H\x14P\xc8\x01]\x00\x00 @eff\xa6?m\x9a\x99\x99?}\x00\x00\x80?\x80\x01\x94\x9d\x02\x88\x01\x01\x90\x01\x01\x98\x01\x04\xa8\x01\x01\xb0\x01\x08\xc0\x01<\xad\x02fff?\xc5\x02fff?\xe0\x02\x01'},
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
# ========= TABLE config =========
|
|
24
|
+
table_config = [
|
|
25
|
+
{'KEY': 'activeDecks', 'usn': 0, 'mtime_secs': 0, 'val': b'[1]'},
|
|
26
|
+
{'KEY': 'addToCur', 'usn': 0, 'mtime_secs': 0, 'val': b'true'},
|
|
27
|
+
{'KEY': 'collapseTime', 'usn': 0, 'mtime_secs': 0, 'val': b'1200'},
|
|
28
|
+
{'KEY': 'creationOffset', 'usn': 0, 'mtime_secs': 0, 'val': b'0'},
|
|
29
|
+
{'KEY': 'curDeck', 'usn': 0, 'mtime_secs': 0, 'val': b'1'},
|
|
30
|
+
{'KEY': 'curModel', 'usn': -1, 'mtime_secs': 0, 'val': b'1'},
|
|
31
|
+
{'KEY': 'dayLearnFirst', 'usn': 0, 'mtime_secs': 0, 'val': b'false'},
|
|
32
|
+
{'KEY': 'dueCounts', 'usn': 0, 'mtime_secs': 0, 'val': b'true'},
|
|
33
|
+
{'KEY': 'estTimes', 'usn': 0, 'mtime_secs': 0, 'val': b'true'},
|
|
34
|
+
{'KEY': 'newSpread', 'usn': 0, 'mtime_secs': 0, 'val': b'0'},
|
|
35
|
+
{'KEY': 'nextPos', 'usn': 0, 'mtime_secs': 0, 'val': b'1'},
|
|
36
|
+
{'KEY': 'sched2021', 'usn': 0, 'mtime_secs': 0, 'val': b'true'},
|
|
37
|
+
{'KEY': 'schedVer', 'usn': 0, 'mtime_secs': 0, 'val': b'2'},
|
|
38
|
+
{'KEY': 'sortBackwards', 'usn': 0, 'mtime_secs': 0, 'val': b'false'},
|
|
39
|
+
{'KEY': 'sortType', 'usn': 0, 'mtime_secs': 0, 'val': b'"noteFld"'},
|
|
40
|
+
{'KEY': 'timeLim', 'usn': 0, 'mtime_secs': 0, 'val': b'0'},
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# ========= TABLE fields =========
|
|
44
|
+
table_fields = [
|
|
45
|
+
{'ntid': 1, 'ord': 0, 'name': 'Front', 'config': b'\x1a\x05Arial \x14'},
|
|
46
|
+
{'ntid': 1, 'ord': 1, 'name': 'Back', 'config': b'\x1a\x05Arial \x14'},
|
|
47
|
+
{'ntid': 2, 'ord': 0, 'name': 'Front', 'config': b'\x1a\x05Arial \x14'},
|
|
48
|
+
{'ntid': 2, 'ord': 1, 'name': 'Back', 'config': b'\x1a\x05Arial \x14'},
|
|
49
|
+
{'ntid': 3, 'ord': 0, 'name': 'Front', 'config': b'\x1a\x05Arial \x14'},
|
|
50
|
+
{'ntid': 3, 'ord': 1, 'name': 'Back', 'config': b'\x1a\x05Arial \x14'},
|
|
51
|
+
{'ntid': 3, 'ord': 2, 'name': 'Add Reverse', 'config': b'\x1a\x05Arial \x14'},
|
|
52
|
+
{'ntid': 4, 'ord': 0, 'name': 'Front', 'config': b'\x1a\x05Arial \x14'},
|
|
53
|
+
{'ntid': 4, 'ord': 1, 'name': 'Back', 'config': b'\x1a\x05Arial \x14'},
|
|
54
|
+
{'ntid': 5, 'ord': 0, 'name': 'Text', 'config': b'\x1a\x05Arial \x14P\x00X\x01'},
|
|
55
|
+
{'ntid': 5, 'ord': 1, 'name': 'Back Extra', 'config': b'\x1a\x05Arial \x14P\x01'},
|
|
56
|
+
{'ntid': 6, 'ord': 0, 'name': 'Occlusion', 'config': b'\x1a\x05Arial \x14P\x00X\x01'},
|
|
57
|
+
{'ntid': 6, 'ord': 1, 'name': 'Image', 'config': b'\x1a\x05Arial \x14P\x01X\x01'},
|
|
58
|
+
{'ntid': 6, 'ord': 2, 'name': 'Header', 'config': b'\x1a\x05Arial \x14P\x02X\x01'},
|
|
59
|
+
{'ntid': 6, 'ord': 3, 'name': 'Back Extra', 'config': b'\x1a\x05Arial \x14P\x03X\x01'},
|
|
60
|
+
{'ntid': 6, 'ord': 4, 'name': 'Comments', 'config': b'\x1a\x05Arial \x14P\x04'},
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
# ========= TABLE templates =========
|
|
64
|
+
table_templates = [
|
|
65
|
+
{'ntid': 1, 'ord': 0, 'name': 'Card 1', 'mtime_secs': 0, 'usn': 0, 'config': b"\n\t{{Front}}\x12'{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}"},
|
|
66
|
+
{'ntid': 2, 'ord': 0, 'name': 'Card 1', 'mtime_secs': 0, 'usn': 0, 'config': b"\n\t{{Front}}\x12'{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}"},
|
|
67
|
+
{'ntid': 2, 'ord': 1, 'name': 'Card 2', 'mtime_secs': 0, 'usn': 0, 'config': b'\n\x08{{Back}}\x12({{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}'},
|
|
68
|
+
{'ntid': 3, 'ord': 0, 'name': 'Card 1', 'mtime_secs': 0, 'usn': 0, 'config': b"\n\t{{Front}}\x12'{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}"},
|
|
69
|
+
{'ntid': 3, 'ord': 1, 'name': 'Card 2', 'mtime_secs': 0, 'usn': 0, 'config': b'\n({{#Add Reverse}}{{Back}}{{/Add Reverse}}\x12({{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}'},
|
|
70
|
+
{'ntid': 4, 'ord': 0, 'name': 'Card 1', 'mtime_secs': 0, 'usn': 0, 'config': b'\n\x18{{Front}}\n\n{{type:Back}}\x12({{Front}}\n\n<hr id=answer>\n\n{{type:Back}}'},
|
|
71
|
+
{'ntid': 5, 'ord': 0, 'name': 'Cloze', 'mtime_secs': 0, 'usn': 0, 'config': b'\n\x0e{{cloze:Text}}\x12!{{cloze:Text}}<br>\n{{Back Extra}}'},
|
|
72
|
+
{'ntid': 6, 'ord': 0, 'name': 'Image Occlusion', 'mtime_secs': 0, 'usn': 0, 'config': b'\n\xae\x03{{#Header}}<div>{{Header}}</div>{{/Header}}\n<div style="display: none">{{cloze:Occlusion}}</div>\n<div id="err"></div>\n<div id="image-occlusion-container">\n {{Image}}\n <canvas id="image-occlusion-canvas"></canvas>\n</div>\n<script>\ntry {\n anki.imageOcclusion.setup();\n} catch (exc) {\n document.getElementById("err").innerHTML = `Error loading image occlusion. Is your Anki version up to date?<br><br>${exc}`;\n}\n</script>\n\x12\x9c\x04{{#Header}}<div>{{Header}}</div>{{/Header}}\n<div style="display: none">{{cloze:Occlusion}}</div>\n<div id="err"></div>\n<div id="image-occlusion-container">\n {{Image}}\n <canvas id="image-occlusion-canvas"></canvas>\n</div>\n<script>\ntry {\n anki.imageOcclusion.setup();\n} catch (exc) {\n document.getElementById("err").innerHTML = `Error loading image occlusion. Is your Anki version up to date?<br><br>${exc}`;\n}\n</script>\n\n<div><button id="toggle">Toggle Masks</button></div>\n{{#Back Extra}}<div>{{Back Extra}}</div>{{/Back Extra}}\n'},
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
# ========= TABLE notetypes =========
|
|
76
|
+
table_notetypes = [
|
|
77
|
+
{'id': 1, 'name': 'Basic (genanki2)', 'mtime_secs': 0, 'usn': 0, 'config': b'\x1a\x94\x01.card {\n font-family: arial;\n font-size: 20px;\n line-height: 1.5;\n text-align: center;\n color: black;\n background-color: white;\n}\n*\xb2\x01\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n2\x0e\\end{document}B\x05\x10\x01\x1a\x01\x00H\x01'},
|
|
78
|
+
{'id': 2, 'name': 'Basic (and reversed card) (genanki2)', 'mtime_secs': 0, 'usn': 0, 'config': b'\x1a\x94\x01.card {\n font-family: arial;\n font-size: 20px;\n line-height: 1.5;\n text-align: center;\n color: black;\n background-color: white;\n}\n*\xb2\x01\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n2\x0e\\end{document}B\x05\x10\x01\x1a\x01\x00B\x07\x08\x01\x10\x01\x1a\x01\x01H\x02'},
|
|
79
|
+
{'id': 3, 'name': 'Basic (optional reversed card) (genanki2)', 'mtime_secs': 0, 'usn': 0, 'config': b'\x1a\x94\x01.card {\n font-family: arial;\n font-size: 20px;\n line-height: 1.5;\n text-align: center;\n color: black;\n background-color: white;\n}\n*\xb2\x01\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n2\x0e\\end{document}B\x05\x10\x01\x1a\x01\x00B\x08\x08\x01\x10\x02\x1a\x02\x01\x02H\x03'},
|
|
80
|
+
{'id': 4, 'name': 'Basic (type in the answer) (genanki2)', 'mtime_secs': 0, 'usn': 0, 'config': b'\x1a\x94\x01.card {\n font-family: arial;\n font-size: 20px;\n line-height: 1.5;\n text-align: center;\n color: black;\n background-color: white;\n}\n*\xb2\x01\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n2\x0e\\end{document}B\x06\x10\x01\x1a\x02\x00\x01H\x04'},
|
|
81
|
+
{'id': 5, 'name': 'Cloze (genanki2)', 'mtime_secs': 0, 'usn': 0, 'config': b'\x08\x01\x1a\xf3\x01.card {\n font-family: arial;\n font-size: 20px;\n line-height: 1.5;\n text-align: center;\n color: black;\n background-color: white;\n}\n.cloze {\n font-weight: bold;\n color: blue;\n}\n.nightMode .cloze {\n color: lightblue;\n}\n*\xb2\x01\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n2\x0e\\end{document}B\x05\x10\x01\x1a\x01\x00H\x05'},
|
|
82
|
+
{'id': 6, 'name': 'Image Occlusion (genanki2)', 'mtime_secs': 0, 'usn': 0, 'config': b'\x08\x01\x1a\x88\x03#image-occlusion-canvas {\n --inactive-shape-color: #ffeba2;\n --active-shape-color: #ff8e8e;\n --inactive-shape-border: 1px #212121;\n --active-shape-border: 1px #212121;\n --highlight-shape-color: #ff8e8e00;\n --highlight-shape-border: 1px #ff8e8e;\n}\n\n.card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n*\xb2\x01\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n2\x0e\\end{document}B\x07\x10\x01\x1a\x03\x00\x01\x02H\x06'},
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
# ========= TABLE decks =========
|
|
86
|
+
table_decks = [
|
|
87
|
+
{'id': 1, 'name': 'Default', 'mtime_secs': 0, 'usn': 0, 'common': b'\x08\x01\x10\x01', 'kind': b'\n\x02\x08\x01'},
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
# ========= TABLE tags =========
|
|
91
|
+
table_tags = []
|
|
92
|
+
|
|
93
|
+
# ========= TABLE graves =========
|
|
94
|
+
table_graves = []
|
|
Binary file
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Anki's protobuf definitions, as message classes.
|
|
2
|
+
|
|
3
|
+
A v18 collection stores several columns as serialized protobuf: the three notetype
|
|
4
|
+
configurations, a deck's `common` and `kind`, and a deck preset's `config`. A package
|
|
5
|
+
adds two more, the `meta` entry and the media map.
|
|
6
|
+
|
|
7
|
+
The definitions come from `descriptors.binpb`, written by
|
|
8
|
+
scripts/dump_proto_descriptors.py, and are loaded into a private descriptor pool.
|
|
9
|
+
The pool is private because protobuf's default one is process-wide and keyed by
|
|
10
|
+
proto file name: a second registration of `anki/notetypes.proto` is aliased to the
|
|
11
|
+
first, so with the `anki` package installed as a test oracle, whichever import ran
|
|
12
|
+
first would decide which definitions everything else sees.
|
|
13
|
+
|
|
14
|
+
The definitions are Anki's, Copyright Ankitects Pty Ltd and contributors, licensed
|
|
15
|
+
under the GNU AGPL, version 3 or later.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from importlib import resources
|
|
19
|
+
|
|
20
|
+
from google.protobuf.descriptor import Descriptor
|
|
21
|
+
from google.protobuf.descriptor_pb2 import FileDescriptorSet
|
|
22
|
+
from google.protobuf.descriptor_pool import DescriptorPool
|
|
23
|
+
from google.protobuf.message import Message
|
|
24
|
+
from google.protobuf.message_factory import GetMessageClass
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"CardRequirement",
|
|
28
|
+
"DayLimit",
|
|
29
|
+
"DeckCommon",
|
|
30
|
+
"DeckConfigConfig",
|
|
31
|
+
"DeckFiltered",
|
|
32
|
+
"DeckKindContainer",
|
|
33
|
+
"DeckNormal",
|
|
34
|
+
"FieldConfig",
|
|
35
|
+
"MediaEntries",
|
|
36
|
+
"MediaEntry",
|
|
37
|
+
"NotetypeConfig",
|
|
38
|
+
"PackageMetadata",
|
|
39
|
+
"SearchTerm",
|
|
40
|
+
"TemplateConfig",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _descriptor_set() -> FileDescriptorSet:
|
|
45
|
+
"""Parse the vendored `descriptors.binpb`."""
|
|
46
|
+
descriptors_path = resources.files(__name__).joinpath("descriptors.binpb")
|
|
47
|
+
return FileDescriptorSet.FromString(descriptors_path.read_bytes())
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _pool() -> DescriptorPool:
|
|
51
|
+
"""Return a descriptor pool holding the vendored definitions.
|
|
52
|
+
|
|
53
|
+
Files are added in the order the dump wrote them, which is imports first, because a
|
|
54
|
+
pool refuses a file whose imports it has not been given yet.
|
|
55
|
+
"""
|
|
56
|
+
pool: DescriptorPool = DescriptorPool()
|
|
57
|
+
for file_descriptor in _descriptor_set().file:
|
|
58
|
+
pool.Add(file_descriptor)
|
|
59
|
+
return pool
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _set_module(descriptor: Descriptor) -> None:
|
|
63
|
+
"""Set `__module__` on the Message type and on any nested type.
|
|
64
|
+
|
|
65
|
+
Pydantic `BaseModel.model_validate(..., from_attributes=True)` fails without
|
|
66
|
+
`__module__` set.
|
|
67
|
+
"""
|
|
68
|
+
GetMessageClass(descriptor).__module__ = __name__
|
|
69
|
+
for nested in descriptor.nested_types:
|
|
70
|
+
_set_module(nested)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _message(name: str) -> type[Message]:
|
|
74
|
+
"""Return the message class registered under `name`."""
|
|
75
|
+
message = GetMessageClass(_POOL.FindMessageTypeByName(name))
|
|
76
|
+
_set_module(message.DESCRIPTOR) # pyright: ignore[reportArgumentType]
|
|
77
|
+
return message
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
_POOL = _pool()
|
|
81
|
+
FieldConfig = _message("anki.notetypes.Notetype.Field.Config")
|
|
82
|
+
TemplateConfig = _message("anki.notetypes.Notetype.Template.Config")
|
|
83
|
+
NotetypeConfig = _message("anki.notetypes.Notetype.Config")
|
|
84
|
+
CardRequirement = _message("anki.notetypes.Notetype.Config.CardRequirement")
|
|
85
|
+
DeckConfigConfig = _message("anki.deck_config.DeckConfig.Config")
|
|
86
|
+
DeckCommon = _message("anki.decks.Deck.Common")
|
|
87
|
+
DeckKindContainer = _message("anki.decks.Deck.KindContainer")
|
|
88
|
+
DeckNormal = _message("anki.decks.Deck.Normal")
|
|
89
|
+
DayLimit = _message("anki.decks.Deck.Normal.DayLimit")
|
|
90
|
+
DeckFiltered = _message("anki.decks.Deck.Filtered")
|
|
91
|
+
SearchTerm = _message("anki.decks.Deck.Filtered.SearchTerm")
|
|
92
|
+
MediaEntries = _message("anki.import_export.MediaEntries")
|
|
93
|
+
MediaEntry = _message("anki.import_export.MediaEntries.MediaEntry")
|
|
94
|
+
PackageMetadata = _message("anki.import_export.PackageMetadata")
|
|
Binary file
|
genanki2/_schema.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Generated by scripts/dump_anki_schema.py, do not edit.
|
|
2
|
+
# anki 26.08, collection schema version 18
|
|
3
|
+
|
|
4
|
+
SCHEMA = """
|
|
5
|
+
CREATE TABLE cards (
|
|
6
|
+
id integer PRIMARY KEY,
|
|
7
|
+
nid integer NOT NULL,
|
|
8
|
+
did integer NOT NULL,
|
|
9
|
+
ord integer NOT NULL,
|
|
10
|
+
mod integer NOT NULL,
|
|
11
|
+
usn integer NOT NULL,
|
|
12
|
+
type integer NOT NULL,
|
|
13
|
+
queue integer NOT NULL,
|
|
14
|
+
due integer NOT NULL,
|
|
15
|
+
ivl integer NOT NULL,
|
|
16
|
+
factor integer NOT NULL,
|
|
17
|
+
reps integer NOT NULL,
|
|
18
|
+
lapses integer NOT NULL,
|
|
19
|
+
left integer NOT NULL,
|
|
20
|
+
odue integer NOT NULL,
|
|
21
|
+
odid integer NOT NULL,
|
|
22
|
+
flags integer NOT NULL,
|
|
23
|
+
data text NOT NULL
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
CREATE TABLE col (
|
|
27
|
+
id integer PRIMARY KEY,
|
|
28
|
+
crt integer NOT NULL,
|
|
29
|
+
mod integer NOT NULL,
|
|
30
|
+
scm integer NOT NULL,
|
|
31
|
+
ver integer NOT NULL,
|
|
32
|
+
dty integer NOT NULL,
|
|
33
|
+
usn integer NOT NULL,
|
|
34
|
+
ls integer NOT NULL,
|
|
35
|
+
conf text NOT NULL,
|
|
36
|
+
models text NOT NULL,
|
|
37
|
+
decks text NOT NULL,
|
|
38
|
+
dconf text NOT NULL,
|
|
39
|
+
tags text NOT NULL
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
CREATE TABLE config (
|
|
43
|
+
KEY text NOT NULL PRIMARY KEY,
|
|
44
|
+
usn integer NOT NULL,
|
|
45
|
+
mtime_secs integer NOT NULL,
|
|
46
|
+
val blob NOT NULL
|
|
47
|
+
) without rowid;
|
|
48
|
+
|
|
49
|
+
CREATE TABLE deck_config (
|
|
50
|
+
id integer PRIMARY KEY NOT NULL,
|
|
51
|
+
name text NOT NULL COLLATE unicase,
|
|
52
|
+
mtime_secs integer NOT NULL,
|
|
53
|
+
usn integer NOT NULL,
|
|
54
|
+
config blob NOT NULL
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
CREATE TABLE decks (
|
|
58
|
+
id integer PRIMARY KEY NOT NULL,
|
|
59
|
+
name text NOT NULL COLLATE unicase,
|
|
60
|
+
mtime_secs integer NOT NULL,
|
|
61
|
+
usn integer NOT NULL,
|
|
62
|
+
common blob NOT NULL,
|
|
63
|
+
kind blob NOT NULL
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
CREATE TABLE fields (
|
|
67
|
+
ntid integer NOT NULL,
|
|
68
|
+
ord integer NOT NULL,
|
|
69
|
+
name text NOT NULL COLLATE unicase,
|
|
70
|
+
config blob NOT NULL,
|
|
71
|
+
PRIMARY KEY (ntid, ord)
|
|
72
|
+
) without rowid;
|
|
73
|
+
|
|
74
|
+
CREATE TABLE graves (
|
|
75
|
+
oid integer NOT NULL,
|
|
76
|
+
type integer NOT NULL,
|
|
77
|
+
usn integer NOT NULL,
|
|
78
|
+
PRIMARY KEY (oid, type)
|
|
79
|
+
) WITHOUT ROWID;
|
|
80
|
+
|
|
81
|
+
CREATE TABLE notes (
|
|
82
|
+
id integer PRIMARY KEY,
|
|
83
|
+
guid text NOT NULL,
|
|
84
|
+
mid integer NOT NULL,
|
|
85
|
+
mod integer NOT NULL,
|
|
86
|
+
usn integer NOT NULL,
|
|
87
|
+
tags text NOT NULL,
|
|
88
|
+
flds text NOT NULL,
|
|
89
|
+
-- The use of type integer for sfld is deliberate, because it means that integer values in this
|
|
90
|
+
-- field will sort numerically.
|
|
91
|
+
sfld integer NOT NULL,
|
|
92
|
+
csum integer NOT NULL,
|
|
93
|
+
flags integer NOT NULL,
|
|
94
|
+
data text NOT NULL
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
CREATE TABLE notetypes (
|
|
98
|
+
id integer NOT NULL PRIMARY KEY,
|
|
99
|
+
name text NOT NULL COLLATE unicase,
|
|
100
|
+
mtime_secs integer NOT NULL,
|
|
101
|
+
usn integer NOT NULL,
|
|
102
|
+
config blob NOT NULL
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
CREATE TABLE revlog (
|
|
106
|
+
id integer PRIMARY KEY,
|
|
107
|
+
cid integer NOT NULL,
|
|
108
|
+
usn integer NOT NULL,
|
|
109
|
+
ease integer NOT NULL,
|
|
110
|
+
ivl integer NOT NULL,
|
|
111
|
+
lastIvl integer NOT NULL,
|
|
112
|
+
factor integer NOT NULL,
|
|
113
|
+
time integer NOT NULL,
|
|
114
|
+
type integer NOT NULL
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
CREATE TABLE tags (
|
|
118
|
+
tag text NOT NULL PRIMARY KEY COLLATE unicase,
|
|
119
|
+
usn integer NOT NULL,
|
|
120
|
+
collapsed boolean NOT NULL,
|
|
121
|
+
config blob NULL
|
|
122
|
+
) without rowid;
|
|
123
|
+
|
|
124
|
+
CREATE TABLE templates (
|
|
125
|
+
ntid integer NOT NULL,
|
|
126
|
+
ord integer NOT NULL,
|
|
127
|
+
name text NOT NULL COLLATE unicase,
|
|
128
|
+
mtime_secs integer NOT NULL,
|
|
129
|
+
usn integer NOT NULL,
|
|
130
|
+
config blob NOT NULL,
|
|
131
|
+
PRIMARY KEY (ntid, ord)
|
|
132
|
+
) without rowid;
|
|
133
|
+
|
|
134
|
+
CREATE INDEX idx_cards_odid ON cards (odid)
|
|
135
|
+
WHERE odid != 0;
|
|
136
|
+
|
|
137
|
+
CREATE UNIQUE INDEX idx_decks_name ON decks (name);
|
|
138
|
+
|
|
139
|
+
CREATE UNIQUE INDEX idx_fields_name_ntid ON fields (name, ntid);
|
|
140
|
+
|
|
141
|
+
CREATE INDEX idx_graves_pending ON graves (usn);
|
|
142
|
+
|
|
143
|
+
CREATE INDEX idx_notes_mid ON notes (mid);
|
|
144
|
+
|
|
145
|
+
CREATE UNIQUE INDEX idx_notetypes_name ON notetypes (name);
|
|
146
|
+
|
|
147
|
+
CREATE INDEX idx_notetypes_usn ON notetypes (usn);
|
|
148
|
+
|
|
149
|
+
CREATE UNIQUE INDEX idx_templates_name_ntid ON templates (name, ntid);
|
|
150
|
+
|
|
151
|
+
CREATE INDEX idx_templates_usn ON templates (usn);
|
|
152
|
+
|
|
153
|
+
CREATE INDEX ix_cards_nid ON cards (nid);
|
|
154
|
+
|
|
155
|
+
CREATE INDEX ix_cards_sched ON cards (did, queue, due);
|
|
156
|
+
|
|
157
|
+
CREATE INDEX ix_cards_usn ON cards (usn);
|
|
158
|
+
|
|
159
|
+
CREATE INDEX ix_notes_csum ON notes (csum);
|
|
160
|
+
|
|
161
|
+
CREATE INDEX ix_notes_usn ON notes (usn);
|
|
162
|
+
|
|
163
|
+
CREATE INDEX ix_revlog_cid ON revlog (cid);
|
|
164
|
+
|
|
165
|
+
CREATE INDEX ix_revlog_usn ON revlog (usn);
|
|
166
|
+
|
|
167
|
+
"""
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Generated by scripts/dump_anki_schema_as_typed_dicts.py, do not edit.
|
|
2
|
+
# anki 26.09.2, collection schema version 18
|
|
3
|
+
|
|
4
|
+
from collections.abc import Sequence
|
|
5
|
+
from typing import TypeAlias
|
|
6
|
+
|
|
7
|
+
from typing_extensions import TypedDict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ColRow(TypedDict):
|
|
11
|
+
id: int
|
|
12
|
+
crt: int
|
|
13
|
+
mod: int
|
|
14
|
+
scm: int
|
|
15
|
+
ver: int
|
|
16
|
+
dty: int
|
|
17
|
+
usn: int
|
|
18
|
+
ls: int
|
|
19
|
+
conf: str
|
|
20
|
+
models: str
|
|
21
|
+
decks: str
|
|
22
|
+
dconf: str
|
|
23
|
+
tags: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NoteRow(TypedDict):
|
|
27
|
+
id: int
|
|
28
|
+
guid: str
|
|
29
|
+
mid: int
|
|
30
|
+
mod: int
|
|
31
|
+
usn: int
|
|
32
|
+
tags: str
|
|
33
|
+
flds: str
|
|
34
|
+
sfld: str
|
|
35
|
+
csum: int
|
|
36
|
+
flags: int
|
|
37
|
+
data: str
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class CardRow(TypedDict):
|
|
41
|
+
id: int
|
|
42
|
+
nid: int
|
|
43
|
+
did: int
|
|
44
|
+
ord: int
|
|
45
|
+
mod: int
|
|
46
|
+
usn: int
|
|
47
|
+
type: int
|
|
48
|
+
queue: int
|
|
49
|
+
due: int
|
|
50
|
+
ivl: int
|
|
51
|
+
factor: int
|
|
52
|
+
reps: int
|
|
53
|
+
lapses: int
|
|
54
|
+
left: int
|
|
55
|
+
odue: int
|
|
56
|
+
odid: int
|
|
57
|
+
flags: int
|
|
58
|
+
data: str
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class RevlogRow(TypedDict):
|
|
62
|
+
id: int
|
|
63
|
+
cid: int
|
|
64
|
+
usn: int
|
|
65
|
+
ease: int
|
|
66
|
+
ivl: int
|
|
67
|
+
lastIvl: int
|
|
68
|
+
factor: int
|
|
69
|
+
time: int
|
|
70
|
+
type: int
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class DeckConfigRow(TypedDict):
|
|
74
|
+
id: int
|
|
75
|
+
name: str
|
|
76
|
+
mtime_secs: int
|
|
77
|
+
usn: int
|
|
78
|
+
config: bytes
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ConfigRow(TypedDict):
|
|
82
|
+
KEY: str
|
|
83
|
+
usn: int
|
|
84
|
+
mtime_secs: int
|
|
85
|
+
val: bytes
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class FieldRow(TypedDict):
|
|
89
|
+
ntid: int
|
|
90
|
+
ord: int
|
|
91
|
+
name: str
|
|
92
|
+
config: bytes
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class TemplateRow(TypedDict):
|
|
96
|
+
ntid: int
|
|
97
|
+
ord: int
|
|
98
|
+
name: str
|
|
99
|
+
mtime_secs: int
|
|
100
|
+
usn: int
|
|
101
|
+
config: bytes
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class NotetypeRow(TypedDict):
|
|
105
|
+
id: int
|
|
106
|
+
name: str
|
|
107
|
+
mtime_secs: int
|
|
108
|
+
usn: int
|
|
109
|
+
config: bytes
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class DeckRow(TypedDict):
|
|
113
|
+
id: int
|
|
114
|
+
name: str
|
|
115
|
+
mtime_secs: int
|
|
116
|
+
usn: int
|
|
117
|
+
common: bytes
|
|
118
|
+
kind: bytes
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class TagRow(TypedDict):
|
|
122
|
+
tag: str
|
|
123
|
+
usn: int
|
|
124
|
+
collapsed: int
|
|
125
|
+
config: bytes | None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class GraveRow(TypedDict):
|
|
129
|
+
oid: int
|
|
130
|
+
type: int
|
|
131
|
+
usn: int
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
ColRows: TypeAlias = Sequence[ColRow]
|
|
135
|
+
NoteRows: TypeAlias = Sequence[NoteRow]
|
|
136
|
+
CardRows: TypeAlias = Sequence[CardRow]
|
|
137
|
+
RevlogRows: TypeAlias = Sequence[RevlogRow]
|
|
138
|
+
DeckConfigRows: TypeAlias = Sequence[DeckConfigRow]
|
|
139
|
+
ConfigRows: TypeAlias = Sequence[ConfigRow]
|
|
140
|
+
FieldRows: TypeAlias = Sequence[FieldRow]
|
|
141
|
+
TemplateRows: TypeAlias = Sequence[TemplateRow]
|
|
142
|
+
NotetypeRows: TypeAlias = Sequence[NotetypeRow]
|
|
143
|
+
DeckRows: TypeAlias = Sequence[DeckRow]
|
|
144
|
+
TagRows: TypeAlias = Sequence[TagRow]
|
|
145
|
+
GraveRows: TypeAlias = Sequence[GraveRow]
|