diff --git a/Makefile b/Makefile index 5545721..699bd83 100644 --- a/Makefile +++ b/Makefile @@ -23,3 +23,6 @@ test: mypy src python -m doctest src/settings.py black --check . + +develop: + ln -s ${PWD}/src ~/.local/share/Anki2/addons21/$$(basename ${PWD})_develop diff --git a/README.md b/README.md index 6993a4d..8a8492c 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,8 @@ On linux, with my Anki installation, this can be done by ```sh git clone git@github.com:AlexRiina/anki_cousins.git -ln -s `pwd`/src ~/.local/share/Anki2/addons21/beta_cousins +cd anki_cousins +make develop ``` To avoid overwriting your main settings while working on this plugin, you can diff --git a/setup.cfg b/setup.cfg index 9ecba7c..74cfd46 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,5 @@ [flake8] select = F,E9 + +[mypy-PyQt5.*] +ignore_missing_imports = True diff --git a/setup.py b/setup.py index 1176f4c..22afe6e 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="anki_cousins", - version="0.3", + version="0.4", tests_require=["PyQt5-stubs" "anki", "black", "flake8", "isort", "mypy"], packages=["src"], ) diff --git a/src/interface.py b/src/interface.py index 1431bb9..ecba271 100644 --- a/src/interface.py +++ b/src/interface.py @@ -32,7 +32,7 @@ def show_settings_dialog() -> None: dialog_layout = QVBoxLayout() dialog.setLayout(dialog_layout) - note_types = list(col.models.models.values()) + note_types = col.models.all() append = QPushButton("Add rule") @@ -108,11 +108,9 @@ def setFieldNames(note_field_input: QComboBox, new_text): for index in range(note_field_input.count()): note_field_input.removeItem(0) - print("setting field names for", new_text) for note_type in note_types: if note_type["name"] == new_text: for field in note_type["flds"]: - print("adding", field["name"]) note_field_input.addItem(field["name"]) self._my_note_field = QComboBox() @@ -173,7 +171,6 @@ def set_values(self, rule: MatchRule) -> None: if rule.cousin_field: self._other_note_field.setCurrentText(rule.cousin_field) - print("loaded cousin field", rule.cousin_field) if rule.comparison: self._matcher.setCurrentIndex(self._matcher.findData(rule.comparison)) diff --git a/src/main.py b/src/main.py index 96d89b9..4ac8f6f 100644 --- a/src/main.py +++ b/src/main.py @@ -8,7 +8,6 @@ QUEUE_TYPE_REV, QUEUE_TYPE_SIBLING_BURIED, ) -from anki.models import NoteType from anki.notes import Note from anki.sched import Scheduler from anki.schedv2 import Scheduler as SchedulerV2 @@ -25,7 +24,7 @@ def buryCousins(self: SomeScheduler, card: "Card") -> None: - """ bury related cards that aren't marked as siblings + """bury related cards that aren't marked as siblings Same as Anki: always delete from current rehearsal and if bury new / bury review are set in deck options, bury until tomorrow @@ -39,8 +38,9 @@ def buryCousins(self: SomeScheduler, card: "Card") -> None: my_note = card.note() def field_value(note, field_name) -> str: - note_type = self.col.models.get(note.mid) - field_number = self.col.models.fieldMap(note_type)[field_name][0] + model = self.col.models.get(note.mid) + assert model + field_number = self.col.models.fieldMap(model)[field_name][0] return note.fields[field_number] @@ -188,7 +188,9 @@ def findDupes( def extract_field(model_id, field_name) -> Iterable[Tuple[int, str]]: # type works better in future anki - model: NoteType = self.models.get(model_id) + model = self.models.get(model_id) + assert model # type is optional, but None should never come back + note_ids = self.findNotes(" ".join(search_filters + [f'note:{model["name"]}'])) field_ord: int = next( diff --git a/src/settings.py b/src/settings.py index 4524e87..85e5dce 100644 --- a/src/settings.py +++ b/src/settings.py @@ -68,18 +68,21 @@ def __init__(self, col): self.col = col def load(self) -> List[MatchRule]: - return [self._deserialize_rule(row) for row in self.col.conf.get(self.key, [])] + return [ + self._deserialize_rule(row) for row in self.col.get_config(self.key, []) + ] def save(self, match_rules: Iterable[MatchRule]): - self.col.conf[self.key] = sorted( - [ - list(self._serialize_rule(match_rule).values()) - for match_rule in match_rules - ] + self.col.set_config( + self.key, + sorted( + [ + list(self._serialize_rule(match_rule).values()) + for match_rule in match_rules + ] + ), ) - self.col.setMod() - @staticmethod def _deserialize_rule(stored: List[Serializeable]) -> MatchRule: rule_dict = dict(zip(MatchRule._fields, stored)) @@ -204,7 +207,7 @@ def _contains(a: List[str], b: List[str], threshold: float): class _cloze_contained_by: - """ terms in cloze deletion a contained anywhere in b + """terms in cloze deletion a contained anywhere in b >>> bool(_cloze_contained_by()(['{{c1::hello}}'], ['test hello test'], 1)) True