From 1b15069b248a8f86f9bd4b3c66a9bfeab8dfb2b8 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sun, 27 Jun 2021 15:12:22 +1000 Subject: [PATCH] PEP8 collection.py --- pylib/.pylintrc | 3 +- pylib/anki/collection.py | 325 +++++++++++++----------------- pylib/anki/decks.py | 2 +- pylib/anki/exporting.py | 10 +- pylib/anki/importing/anki2.py | 6 +- pylib/anki/models.py | 2 +- pylib/anki/scheduler/v1.py | 1 - pylib/anki/scheduler/v2.py | 2 - pylib/anki/stats.py | 6 +- pylib/tests/test_cards.py | 6 +- pylib/tests/test_collection.py | 4 +- pylib/tests/test_decks.py | 4 +- pylib/tests/test_exporting.py | 5 +- pylib/tests/test_find.py | 220 ++++++++++---------- pylib/tests/test_flags.py | 10 +- pylib/tests/test_importing.py | 14 +- pylib/tests/test_models.py | 14 +- pylib/tests/test_schedv1.py | 4 +- pylib/tests/test_schedv2.py | 2 +- pylib/tests/test_stats.py | 4 +- pylib/tests/test_undo.py | 24 +-- qt/aqt/browser/browser.py | 2 +- qt/aqt/browser/find_duplicates.py | 2 +- qt/aqt/dbcheck.py | 2 +- qt/aqt/deckbrowser.py | 4 +- qt/aqt/deckconf.py | 4 +- qt/aqt/deckoptions.py | 2 +- qt/aqt/filtered_deck.py | 10 +- qt/aqt/importing.py | 2 +- qt/aqt/main.py | 4 +- qt/aqt/overview.py | 2 +- qt/aqt/preferences.py | 2 +- qt/aqt/utils.py | 2 +- 33 files changed, 329 insertions(+), 377 deletions(-) diff --git a/pylib/.pylintrc b/pylib/.pylintrc index 275d49355..0ab9d4fc0 100644 --- a/pylib/.pylintrc +++ b/pylib/.pylintrc @@ -48,4 +48,5 @@ disable= good-names = id, tr, - db, \ No newline at end of file + db, + ok, \ No newline at end of file diff --git a/pylib/anki/collection.py b/pylib/anki/collection.py index a3bc3fcba..7b907d1a3 100644 --- a/pylib/anki/collection.py +++ b/pylib/anki/collection.py @@ -1,6 +1,8 @@ # Copyright: Ankitects Pty Ltd and contributors # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html +# pylint: enable=invalid-name + from __future__ import annotations from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Union, cast @@ -8,6 +10,8 @@ from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Uni import anki._backend.backend_pb2 as _pb # protobuf we publicly export - listed first to avoid circular imports +from anki._legacy import DeprecatedNamesMixin, deprecated + SearchNode = _pb.SearchNode Progress = _pb.Progress EmptyCardsReport = _pb.EmptyCardsReport @@ -24,8 +28,6 @@ BrowserColumns = _pb.BrowserColumns import copy import os -import pprint -import re import sys import time import traceback @@ -52,7 +54,6 @@ from anki.sync import SyncAuth, SyncOutput, SyncStatus from anki.tags import TagManager from anki.types import assert_exhaustive from anki.utils import ( - devMode, from_json_bytes, ids2str, intTime, @@ -81,7 +82,7 @@ class LegacyCheckpoint: LegacyUndoResult = Union[None, LegacyCheckpoint, LegacyReviewUndo] -class Collection: +class Collection(DeprecatedNamesMixin): sched: Union[V1Scheduler, V2Scheduler, V3Scheduler] def __init__( @@ -104,7 +105,7 @@ class Collection: self.decks = DeckManager(self) self.tags = TagManager(self) self.conf = ConfigManager(self) - self._loadScheduler() + self._load_scheduler() def name(self) -> Any: return os.path.splitext(os.path.basename(self.path))[0] @@ -142,17 +143,17 @@ class Collection: ########################################################################## # for backwards compatibility, v3 is represented as 2 - supportedSchedulerVersions = (1, 2) + _supported_scheduler_versions = (1, 2) - def schedVer(self) -> Literal[1, 2]: + def sched_ver(self) -> Literal[1, 2]: ver = self.conf.get("schedVer", 1) - if ver in self.supportedSchedulerVersions: + if ver in self._supported_scheduler_versions: return ver else: raise Exception("Unsupported scheduler version") - def _loadScheduler(self) -> None: - ver = self.schedVer() + def _load_scheduler(self) -> None: + ver = self.sched_ver() if ver == 1: self.sched = V1Scheduler(self) elif ver == 2: @@ -164,17 +165,17 @@ class Collection: def upgrade_to_v2_scheduler(self) -> None: self._backend.upgrade_scheduler() self.clear_python_undo() - self._loadScheduler() + self._load_scheduler() def v3_scheduler(self) -> bool: return self.get_config_bool(Config.Bool.SCHED_2021) def set_v3_scheduler(self, enabled: bool) -> None: if self.v3_scheduler() != enabled: - if enabled and self.schedVer() != 2: + if enabled and self.sched_ver() != 2: raise Exception("must upgrade to v2 scheduler first") self.set_config_bool(Config.Bool.SCHED_2021, enabled) - self._loadScheduler() + self._load_scheduler() # DB-related ########################################################################## @@ -193,14 +194,6 @@ class Collection: def mod(self) -> int: return self.db.scalar("select mod from col") - # legacy - def setMod(self) -> None: - # this is now a no-op, as modifications to things like the config - # will mark the collection modified automatically - pass - - flush = setMod - def modified_by_backend(self) -> bool: # Until we can move away from long-running transactions, the Python # code needs to know if the transaction should be committed, so we need @@ -242,7 +235,6 @@ class Collection: self._backend.close_collection(downgrade_to_schema11=downgrade) self.db = None self.media.close() - self._closeLog() def close_for_full_sync(self) -> None: # save and cleanup, but backend will take care of collection close @@ -251,7 +243,6 @@ class Collection: self._clear_caches() self.db = None self.media.close() - self._closeLog() def rollback(self) -> None: self._clear_caches() @@ -273,7 +264,7 @@ class Collection: log_path = "" should_log = not self.server and self._should_log if should_log: - log_path = self.path.replace(".anki2", "2.log") + log_path = self.path.replace(".anki2", ".log") # connect if not after_full_sync: @@ -288,17 +279,18 @@ class Collection: self.db = DBProxy(weakref.proxy(self._backend)) self.db.begin() - self._openLog() - - def modSchema(self, check: bool) -> None: - "Mark schema modified. Call this first so user can abort if necessary." - if not self.schemaChanged(): - if check and not hooks.schema_will_change(proceed=True): - raise AbortSchemaModification() + def set_schema_modified(self) -> None: self.db.execute("update col set scm=?", intTime(1000)) self.save() - def schemaChanged(self) -> bool: + def mod_schema(self, check: bool) -> None: + "Mark schema modified. GUI catches this and will ask user if required." + if not self.schema_changed(): + if check and not hooks.schema_will_change(proceed=True): + raise AbortSchemaModification() + self.set_schema_modified() + + def schema_changed(self) -> bool: "True if schema changed since last sync." return self.db.scalar("select scm > ls from col") @@ -308,12 +300,6 @@ class Collection: else: return -1 - def beforeUpload(self) -> None: - "Called before a full upload." - self.save(trx=False) - self._backend.before_upload() - self.close(save=False, downgrade=True) - # Object helpers ########################################################################## @@ -341,7 +327,9 @@ class Collection: # Utils ########################################################################## - def nextID(self, type: str, inc: bool = True) -> Any: + def nextID( # pylint: disable=invalid-name + self, type: str, inc: bool = True + ) -> Any: type = f"next{type.capitalize()}" id = self.conf.get(type, 1) if inc: @@ -353,15 +341,6 @@ class Collection: self.autosave() self.sched.reset() - # Deletion logging - ########################################################################## - - def _logRem(self, ids: List[Union[int, NoteId]], type: int) -> None: - self.db.executemany( - "insert into graves values (%d, ?, %d)" % (self.usn(), type), - ([x] for x in ids), - ) - # Notes ########################################################################## @@ -419,32 +398,16 @@ class Collection: or None ) - # legacy - - def noteCount(self) -> int: + def note_count(self) -> int: return self.db.scalar("select count() from notes") - def newNote(self, forDeck: bool = True) -> Note: - "Return a new note with the current model." - return Note(self, self.models.current(forDeck)) - - def addNote(self, note: Note) -> int: - self.add_note(note, note.note_type()["did"]) - return len(note.cards()) - - def remNotes(self, ids: Sequence[NoteId]) -> None: - self.remove_notes(ids) - - def _remNotes(self, ids: List[NoteId]) -> None: - pass - # Cards ########################################################################## - def isEmpty(self) -> bool: + def is_empty(self) -> bool: return not self.db.scalar("select 1 from cards limit 1") - def cardCount(self) -> Any: + def card_count(self) -> Any: return self.db.scalar("select count() from cards") def remove_cards_and_orphaned_notes(self, card_ids: Sequence[CardId]) -> None: @@ -457,36 +420,17 @@ class Collection: def get_empty_cards(self) -> EmptyCardsReport: return self._backend.get_empty_cards() - # legacy - - def remCards(self, ids: List[CardId], notes: bool = True) -> None: - self.remove_cards_and_orphaned_notes(ids) - - def emptyCids(self) -> List[CardId]: - print("emptyCids() will go away") - return [] - # Card generation & field checksums/sort fields ########################################################################## def after_note_updates( self, nids: List[NoteId], mark_modified: bool, generate_cards: bool = True ) -> None: + "If notes modified directly in database, call this afterwards." self._backend.after_note_updates( nids=nids, generate_cards=generate_cards, mark_notes_modified=mark_modified ) - # legacy - - def updateFieldCache(self, nids: List[NoteId]) -> None: - self.after_note_updates(nids, mark_modified=False, generate_cards=False) - - # this also updates field cache - def genCards(self, nids: List[NoteId]) -> List[int]: - self.after_note_updates(nids, mark_modified=False, generate_cards=True) - # previously returned empty cards, no longer does - return [] - # Finding cards ########################################################################## @@ -591,21 +535,21 @@ class Collection: return self._backend.field_names_for_notes(nids) # returns array of ("dupestr", [nids]) - def findDupes(self, fieldName: str, search: str = "") -> List[Tuple[str, list]]: + def find_dupes(self, field_name: str, search: str = "") -> List[Tuple[str, list]]: nids = self.find_notes( - self.build_search_string(search, SearchNode(field_name=fieldName)) + self.build_search_string(search, SearchNode(field_name=field_name)) ) # go through notes vals: Dict[str, List[int]] = {} dupes = [] fields: Dict[int, int] = {} - def ordForMid(mid: NotetypeId) -> int: + def ord_for_mid(mid: NotetypeId) -> int: if mid not in fields: model = self.models.get(mid) - for c, f in enumerate(model["flds"]): - if f["name"].lower() == fieldName.lower(): - fields[mid] = c + for idx, field in enumerate(model["flds"]): + if field["name"].lower() == field_name.lower(): + fields[mid] = idx break return fields[mid] @@ -613,7 +557,7 @@ class Collection: f"select id, mid, flds from notes where id in {ids2str(nids)}" ): flds = splitFields(flds) - ord = ordForMid(mid) + ord = ord_for_mid(mid) if ord is None: continue val = flds[ord] @@ -626,10 +570,6 @@ class Collection: dupes.append((val, vals[val])) return dupes - findCards = find_cards - findNotes = find_notes - findReplace = find_and_replace - # Search Strings ########################################################################## @@ -880,35 +820,6 @@ table.review-log {{ {revlog_style} }} "Don't use this, it will likely go away in the future." return self._backend.congrats_info().SerializeToString() - # legacy - - def cardStats(self, card: Card) -> str: - return self.card_stats(card.id, include_revlog=False) - - # Timeboxing - ########################################################################## - # fixme: there doesn't seem to be a good reason why this code is in main.py - # instead of covered in reviewer, and the reps tracking is covered by both - # the scheduler and reviewer.py. in the future, we should probably move - # reps tracking to reviewer.py, and remove the startTimebox() calls from - # other locations like overview.py. We just need to make sure not to reset - # the count on things like edits, which we probably could do by checking - # the previous state in moveToState. - - def startTimebox(self) -> None: - self._startTime = time.time() - self._startReps = self.sched.reps - - def timeboxReached(self) -> Union[Literal[False], Tuple[Any, int]]: - "Return (elapsedTime, reps) if timebox reached, or False." - if not self.conf["timeLim"]: - # timeboxing disabled - return False - elapsed = time.time() - self._startTime - if elapsed > self.conf["timeLim"]: - return (self.conf["timeLim"], self.sched.reps - self._startReps) - return False - # Undo ########################################################################## @@ -1070,10 +981,10 @@ table.review-log {{ {revlog_style} }} ) # update daily counts - n = card.queue + idx = card.queue if card.queue in (QUEUE_TYPE_DAY_LEARN_RELEARN, QUEUE_TYPE_PREVIEW): - n = QUEUE_TYPE_LRN - type = ("new", "lrn", "rev")[n] + idx = QUEUE_TYPE_LRN + type = ("new", "lrn", "rev")[idx] self.sched._updateStats(card, type, -1) self.sched.reps -= 1 @@ -1082,20 +993,10 @@ table.review-log {{ {revlog_style} }} return entry - # legacy - - clearUndo = clear_python_undo - markReview = save_card_review_undo_info - - def undoName(self) -> Optional[str]: - "Undo menu item name, or None if undo unavailable." - status = self.undo_status() - return status.undo or None - # DB maintenance ########################################################################## - def fixIntegrity(self) -> Tuple[str, bool]: + def fix_integrity(self) -> Tuple[str, bool]: """Fix possible problems and rebuild caches. Returns tuple of (error: str, ok: bool). 'ok' will be true if no @@ -1106,8 +1007,8 @@ table.review-log {{ {revlog_style} }} problems = list(self._backend.check_database()) ok = not problems problems.append(self.tr.database_check_rebuilt()) - except DBError as e: - problems = [str(e.args[0])] + except DBError as err: + problems = [str(err.args[0])] ok = False finally: try: @@ -1123,46 +1024,6 @@ table.review-log {{ {revlog_style} }} self.db.execute("analyze") self.db.begin() - # Logging - ########################################################################## - - def log(self, *args: Any, **kwargs: Any) -> None: - if not self._should_log: - return - - def customRepr(x: Any) -> str: - if isinstance(x, str): - return x - return pprint.pformat(x) - - path, num, fn, y = traceback.extract_stack(limit=2 + kwargs.get("stack", 0))[0] - buf = "[%s] %s:%s(): %s" % ( - intTime(), - os.path.basename(path), - fn, - ", ".join([customRepr(x) for x in args]), - ) - self._logHnd.write(f"{buf}\n") - if devMode: - print(buf) - - def _openLog(self) -> None: - if not self._should_log: - return - lpath = re.sub(r"\.anki2$", ".log", self.path) - if os.path.exists(lpath) and os.path.getsize(lpath) > 10 * 1024 * 1024: - lpath2 = f"{lpath}.old" - if os.path.exists(lpath2): - os.unlink(lpath2) - os.rename(lpath, lpath2) - self._logHnd = open(lpath, "a", encoding="utf8") - - def _closeLog(self) -> None: - if not self._should_log: - return - self._logHnd.close() - self._logHnd = None - ########################################################################## def set_user_flag_for_cards( @@ -1210,6 +1071,104 @@ table.review-log {{ {revlog_style} }} "Not intended for public consumption at this time." return self._backend.render_markdown(markdown=text, sanitize=sanitize) + # Timeboxing + ########################################################################## + # fixme: there doesn't seem to be a good reason why this code is in main.py + # instead of covered in reviewer, and the reps tracking is covered by both + # the scheduler and reviewer.py. in the future, we should probably move + # reps tracking to reviewer.py, and remove the startTimebox() calls from + # other locations like overview.py. We just need to make sure not to reset + # the count on things like edits, which we probably could do by checking + # the previous state in moveToState. + + # pylint: disable=invalid-name + + def startTimebox(self) -> None: + self._startTime = time.time() + self._startReps = self.sched.reps + + def timeboxReached(self) -> Union[Literal[False], Tuple[Any, int]]: + "Return (elapsedTime, reps) if timebox reached, or False." + if not self.conf["timeLim"]: + # timeboxing disabled + return False + elapsed = time.time() - self._startTime + if elapsed > self.conf["timeLim"]: + return (self.conf["timeLim"], self.sched.reps - self._startReps) + return False + + # Legacy + ########################################################################## + + @deprecated(info="no longer used") + def log(self, *args: Any, **kwargs: Any) -> None: + print(args, kwargs) + + @deprecated(replaced_by=undo_status) + def undo_name(self) -> Optional[str]: + "Undo menu item name, or None if undo unavailable." + status = self.undo_status() + return status.undo or None + + # @deprecated(replaced_by=new_note) + def newNote(self, forDeck: bool = True) -> Note: + "Return a new note with the current model." + return Note(self, self.models.current(forDeck)) + + # @deprecated(replaced_by=add_note) + def addNote(self, note: Note) -> int: + self.add_note(note, note.note_type()["did"]) + return len(note.cards()) + + @deprecated(replaced_by=remove_notes) + def remNotes(self, ids: Sequence[NoteId]) -> None: + self.remove_notes(ids) + + @deprecated(replaced_by=remove_notes) + def _remNotes(self, ids: List[NoteId]) -> None: + pass + + @deprecated(replaced_by=card_stats) + def cardStats(self, card: Card) -> str: + return self.card_stats(card.id, include_revlog=False) + + @deprecated(replaced_by=after_note_updates) + def updateFieldCache(self, nids: List[NoteId]) -> None: + self.after_note_updates(nids, mark_modified=False, generate_cards=False) + + @deprecated(replaced_by=after_note_updates) + def genCards(self, nids: List[NoteId]) -> List[int]: + self.after_note_updates(nids, mark_modified=False, generate_cards=True) + # previously returned empty cards, no longer does + return [] + + @deprecated(info="no longer used") + def emptyCids(self) -> List[CardId]: + return [] + + @deprecated(info="handled by backend") + def _logRem(self, ids: List[Union[int, NoteId]], type: int) -> None: + self.db.executemany( + "insert into graves values (%d, ?, %d)" % (self.usn(), type), + ([x] for x in ids), + ) + + @deprecated(info="no longer required") + def setMod(self) -> None: + pass + + @deprecated(info="no longer required") + def flush(self) -> None: + pass + + +Collection.register_deprecated_aliases( + clearUndo=Collection.clear_python_undo, + markReview=Collection.save_card_review_undo_info, + findReplace=Collection.find_and_replace, + remCards=Collection.remove_cards_and_orphaned_notes, +) + # legacy name _Collection = Collection diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index 4bcbd8aaf..bda0c1e2e 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -349,7 +349,7 @@ class DeckManager(DeprecatedNamesMixin): def remove_config(self, id: DeckConfigId) -> None: "Remove a configuration and update all decks using it." - self.col.modSchema(check=True) + self.col.mod_schema(check=True) for deck in self.all(): # ignore cram decks if "conf" not in deck: diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index 5cd2ec0b2..9e41177f5 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -197,7 +197,7 @@ class AnkiExporter(Exporter): def exportInto(self, path: str) -> None: # sched info+v2 scheduler not compatible w/ older clients - self._v2sched = self.col.schedVer() != 1 and self.includeSched + self._v2sched = self.col.sched_ver() != 1 and self.includeSched # create a new collection at the target try: @@ -246,7 +246,7 @@ class AnkiExporter(Exporter): # need to reset card state self.dst.sched.resetCards(cids) # models - start with zero - self.dst.modSchema(check=False) + self.dst.mod_schema(check=False) self.dst.models.remove_all_notetypes() for m in self.src.models.all(): if int(m["id"]) in mids: @@ -298,7 +298,7 @@ class AnkiExporter(Exporter): self.mediaFiles = list(media.keys()) self.dst.crt = self.src.crt # todo: tags? - self.count = self.dst.cardCount() + self.count = self.dst.card_count() self.postExport() self.dst.close(downgrade=True) @@ -426,8 +426,8 @@ class AnkiCollectionPackageExporter(AnkiPackageExporter): def doExport(self, z, path): "Export collection. Caller must re-open afterwards." # close our deck & write it into the zip file - self.count = self.col.cardCount() - v2 = self.col.schedVer() != 1 + self.count = self.col.card_count() + v2 = self.col.sched_ver() != 1 mdir = self.col.media.dir() self.col.close(downgrade=True) if not v2: diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index 019eff9ca..eea31ca62 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -53,11 +53,11 @@ class Anki2Importer(Importer): self.dst = self.col self.src = Collection(self.file) - if not self._importing_v2 and self.col.schedVer() != 1: + if not self._importing_v2 and self.col.sched_ver() != 1: # any scheduling included? if self.src.db.scalar("select 1 from cards where queue != 0 limit 1"): self.source_needs_upgrade = True - elif self._importing_v2 and self.col.schedVer() == 1: + elif self._importing_v2 and self.col.sched_ver() == 1: raise Exception("must upgrade to new scheduler to import this file") def _import(self) -> None: @@ -186,7 +186,7 @@ class Anki2Importer(Importer): self.dst.db.executemany( "insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)", update ) - self.dst.updateFieldCache(dirty) + self.dst.after_note_updates(dirty, mark_modified=False, generate_cards=False) # determine if note is a duplicate, and adjust mid and/or guid as required # returns true if note should be added diff --git a/pylib/anki/models.py b/pylib/anki/models.py index e5678b507..8a3bd13f6 100644 --- a/pylib/anki/models.py +++ b/pylib/anki/models.py @@ -400,7 +400,7 @@ and notes.mid = ? and cards.ord = ?""", cmap: Optional[Dict[int, Optional[int]]], ) -> None: # - maps are ord->ord, and there should not be duplicate targets - self.col.modSchema(check=True) + self.col.mod_schema(check=True) assert fmap field_map = self._convert_legacy_map(fmap, len(newModel["flds"])) if ( diff --git a/pylib/anki/scheduler/v1.py b/pylib/anki/scheduler/v1.py index 878b2b17d..1598a1505 100644 --- a/pylib/anki/scheduler/v1.py +++ b/pylib/anki/scheduler/v1.py @@ -46,7 +46,6 @@ class Scheduler(V2): self._haveQueues = False def answerCard(self, card: Card, ease: int) -> None: - self.col.log() assert 1 <= ease <= 4 self.col.save_card_review_undo_info(card) if self._burySiblingsOnAnswer: diff --git a/pylib/anki/scheduler/v2.py b/pylib/anki/scheduler/v2.py index 53049fad7..713a9e15d 100644 --- a/pylib/anki/scheduler/v2.py +++ b/pylib/anki/scheduler/v2.py @@ -104,7 +104,6 @@ class Scheduler(SchedulerBaseWithLegacy): self.reset() card = self._getCard() if card: - self.col.log(card) if not self._burySiblingsOnAnswer: self._burySiblings(card) card.start_timer() @@ -452,7 +451,6 @@ limit ?""" ########################################################################## def answerCard(self, card: Card, ease: int) -> None: - self.col.log() assert 1 <= ease <= 4 assert 0 <= card.queue <= 4 self.col.save_card_review_undo_info(card) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index 1cd06ef46..9bd302ed2 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -665,7 +665,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = {QUEUE [13, 3], [14, 4], ] - if self.col.schedVer() != 1: + if self.col.sched_ver() != 1: ticks.insert(3, [4, 4]) txt = self._title( "Answer Buttons", "The number of times you have pressed each button." @@ -725,7 +725,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = {QUEUE lim = "where " + " and ".join(lims) else: lim = "" - if self.col.schedVer() == 1: + if self.col.sched_ver() == 1: ease4repl = "3" else: ease4repl = "ease" @@ -815,7 +815,7 @@ order by thetype, ease""" lim = self._revlogLimit() if lim: lim = " and " + lim - if self.col.schedVer() == 1: + if self.col.sched_ver() == 1: sd = datetime.datetime.fromtimestamp(self.col.crt) rolloverHour = sd.hour else: diff --git a/pylib/tests/test_cards.py b/pylib/tests/test_cards.py index 1ab9dc615..b5f3160ad 100644 --- a/pylib/tests/test_cards.py +++ b/pylib/tests/test_cards.py @@ -16,8 +16,8 @@ def test_delete(): col.reset() col.sched.answerCard(col.sched.getCard(), 2) col.remove_cards_and_orphaned_notes([cid]) - assert col.cardCount() == 0 - assert col.noteCount() == 0 + assert col.card_count() == 0 + assert col.note_count() == 0 assert col.db.scalar("select count() from notes") == 0 assert col.db.scalar("select count() from cards") == 0 assert col.db.scalar("select count() from graves") == 2 @@ -72,7 +72,7 @@ def test_gendeck(): note = col.new_note(cloze) note["Text"] = "{{c1::one}}" col.addNote(note) - assert col.cardCount() == 1 + assert col.card_count() == 1 assert note.cards()[0].did == 1 # set the model to a new default col newId = col.decks.id("new") diff --git a/pylib/tests/test_collection.py b/pylib/tests/test_collection.py index cc55fdf49..a2200c734 100644 --- a/pylib/tests/test_collection.py +++ b/pylib/tests/test_collection.py @@ -62,14 +62,14 @@ def test_noteAddDelete(): t["afmt"] = "{{Front}}" mm.add_template(m, t) mm.save(m) - assert col.cardCount() == 2 + assert col.card_count() == 2 # creating new notes should use both cards note = col.newNote() note["Front"] = "three" note["Back"] = "four" n = col.addNote(note) assert n == 2 - assert col.cardCount() == 4 + assert col.card_count() == 4 # check q/a generation c0 = note.cards()[0] assert "three" in c0.question() diff --git a/pylib/tests/test_decks.py b/pylib/tests/test_decks.py index 6b49646ea..25e08e103 100644 --- a/pylib/tests/test_decks.py +++ b/pylib/tests/test_decks.py @@ -57,9 +57,9 @@ def test_remove(): col.addNote(note) c = note.cards()[0] assert c.did == deck1 - assert col.cardCount() == 1 + assert col.card_count() == 1 col.decks.remove([deck1]) - assert col.cardCount() == 0 + assert col.card_count() == 0 # if we try to get it, we get the default assert col.decks.name(c.did) == "[no deck]" diff --git a/pylib/tests/test_exporting.py b/pylib/tests/test_exporting.py index 3d84fbd25..30a3acfd9 100644 --- a/pylib/tests/test_exporting.py +++ b/pylib/tests/test_exporting.py @@ -65,7 +65,7 @@ def test_export_anki(): assert conf["id"] != 1 # connect to new deck col2 = aopen(newname) - assert col2.cardCount() == 2 + assert col2.card_count() == 2 # as scheduling was reset, should also revert decks to default conf did = col2.decks.id("test", create=False) assert did @@ -82,7 +82,7 @@ def test_export_anki(): e.did = 1 e.exportInto(newname) col2 = aopen(newname) - assert col2.cardCount() == 1 + assert col2.card_count() == 1 def test_export_ankipkg(): @@ -109,7 +109,6 @@ def test_export_anki_due(): note["Front"] = "foo" col.addNote(note) col.crt -= 86400 * 10 - col.flush() col.sched.reset() c = col.sched.getCard() col.sched.answerCard(c, 3) diff --git a/pylib/tests/test_find.py b/pylib/tests/test_find.py index 348a26c04..5812627a1 100644 --- a/pylib/tests/test_find.py +++ b/pylib/tests/test_find.py @@ -14,7 +14,7 @@ class DummyCollection: return None -def test_findCards(): +def test_find_cards(): col = getEmptyCol() note = col.newNote() note["Front"] = "dog" @@ -49,84 +49,80 @@ def test_findCards(): col.save() latestCardIds = [c.id for c in note.cards()] # tag searches - assert len(col.findCards("tag:*")) == 5 - assert len(col.findCards("tag:\\*")) == 1 - assert len(col.findCards("tag:%")) == 1 - assert len(col.findCards("tag:sheep_goat")) == 0 - assert len(col.findCards('"tag:sheep goat"')) == 0 - assert len(col.findCards('"tag:* *"')) == 0 - assert len(col.findCards("tag:animal_1")) == 2 - assert len(col.findCards("tag:animal\\_1")) == 1 - assert not col.findCards("tag:donkey") - assert len(col.findCards("tag:sheep")) == 1 - assert len(col.findCards("tag:sheep tag:goat")) == 1 - assert len(col.findCards("tag:sheep tag:monkey")) == 0 - assert len(col.findCards("tag:monkey")) == 1 - assert len(col.findCards("tag:sheep -tag:monkey")) == 1 - assert len(col.findCards("-tag:sheep")) == 4 + assert len(col.find_cards("tag:*")) == 5 + assert len(col.find_cards("tag:\\*")) == 1 + assert len(col.find_cards("tag:%")) == 1 + assert len(col.find_cards("tag:sheep_goat")) == 0 + assert len(col.find_cards('"tag:sheep goat"')) == 0 + assert len(col.find_cards('"tag:* *"')) == 0 + assert len(col.find_cards("tag:animal_1")) == 2 + assert len(col.find_cards("tag:animal\\_1")) == 1 + assert not col.find_cards("tag:donkey") + assert len(col.find_cards("tag:sheep")) == 1 + assert len(col.find_cards("tag:sheep tag:goat")) == 1 + assert len(col.find_cards("tag:sheep tag:monkey")) == 0 + assert len(col.find_cards("tag:monkey")) == 1 + assert len(col.find_cards("tag:sheep -tag:monkey")) == 1 + assert len(col.find_cards("-tag:sheep")) == 4 col.tags.bulk_add(col.db.list("select id from notes"), "foo bar") - assert len(col.findCards("tag:foo")) == len(col.findCards("tag:bar")) == 5 + assert len(col.find_cards("tag:foo")) == len(col.find_cards("tag:bar")) == 5 col.tags.bulkRem(col.db.list("select id from notes"), "foo") - assert len(col.findCards("tag:foo")) == 0 - assert len(col.findCards("tag:bar")) == 5 + assert len(col.find_cards("tag:foo")) == 0 + assert len(col.find_cards("tag:bar")) == 5 # text searches - assert len(col.findCards("cat")) == 2 - assert len(col.findCards("cat -dog")) == 1 - assert len(col.findCards("cat -dog")) == 1 - assert len(col.findCards("are goats")) == 1 - assert len(col.findCards('"are goats"')) == 0 - assert len(col.findCards('"goats are"')) == 1 + assert len(col.find_cards("cat")) == 2 + assert len(col.find_cards("cat -dog")) == 1 + assert len(col.find_cards("cat -dog")) == 1 + assert len(col.find_cards("are goats")) == 1 + assert len(col.find_cards('"are goats"')) == 0 + assert len(col.find_cards('"goats are"')) == 1 # card states c = note.cards()[0] c.queue = c.type = CARD_TYPE_REV - assert col.findCards("is:review") == [] + assert col.find_cards("is:review") == [] c.flush() - assert col.findCards("is:review") == [c.id] - assert col.findCards("is:due") == [] + assert col.find_cards("is:review") == [c.id] + assert col.find_cards("is:due") == [] c.due = 0 c.queue = QUEUE_TYPE_REV c.flush() - assert col.findCards("is:due") == [c.id] - assert len(col.findCards("-is:due")) == 4 + assert col.find_cards("is:due") == [c.id] + assert len(col.find_cards("-is:due")) == 4 c.queue = QUEUE_TYPE_SUSPENDED # ensure this card gets a later mod time c.flush() col.db.execute("update cards set mod = mod + 1 where id = ?", c.id) - assert col.findCards("is:suspended") == [c.id] + assert col.find_cards("is:suspended") == [c.id] # nids - assert col.findCards("nid:54321") == [] - assert len(col.findCards(f"nid:{note.id}")) == 2 - assert len(col.findCards(f"nid:{n1id},{n2id}")) == 2 + assert col.find_cards("nid:54321") == [] + assert len(col.find_cards(f"nid:{note.id}")) == 2 + assert len(col.find_cards(f"nid:{n1id},{n2id}")) == 2 # templates - assert len(col.findCards("card:foo")) == 0 - assert len(col.findCards('"card:card 1"')) == 4 - assert len(col.findCards("card:reverse")) == 1 - assert len(col.findCards("card:1")) == 4 - assert len(col.findCards("card:2")) == 1 + assert len(col.find_cards("card:foo")) == 0 + assert len(col.find_cards('"card:card 1"')) == 4 + assert len(col.find_cards("card:reverse")) == 1 + assert len(col.find_cards("card:1")) == 4 + assert len(col.find_cards("card:2")) == 1 # fields - assert len(col.findCards("front:dog")) == 1 - assert len(col.findCards("-front:dog")) == 4 - assert len(col.findCards("front:sheep")) == 0 - assert len(col.findCards("back:sheep")) == 2 - assert len(col.findCards("-back:sheep")) == 3 - assert len(col.findCards("front:do")) == 0 - assert len(col.findCards("front:*")) == 5 + assert len(col.find_cards("front:dog")) == 1 + assert len(col.find_cards("-front:dog")) == 4 + assert len(col.find_cards("front:sheep")) == 0 + assert len(col.find_cards("back:sheep")) == 2 + assert len(col.find_cards("-back:sheep")) == 3 + assert len(col.find_cards("front:do")) == 0 + assert len(col.find_cards("front:*")) == 5 # ordering col.conf["sortType"] = "noteCrt" - col.flush() - assert col.findCards("front:*", order=True)[-1] in latestCardIds - assert col.findCards("", order=True)[-1] in latestCardIds + assert col.find_cards("front:*", order=True)[-1] in latestCardIds + assert col.find_cards("", order=True)[-1] in latestCardIds col.conf["sortType"] = "noteFld" - col.flush() - assert col.findCards("", order=True)[0] == catCard.id - assert col.findCards("", order=True)[-1] in latestCardIds + assert col.find_cards("", order=True)[0] == catCard.id + assert col.find_cards("", order=True)[-1] in latestCardIds col.conf["sortType"] = "cardMod" - col.flush() - assert col.findCards("", order=True)[-1] in latestCardIds - assert col.findCards("", order=True)[0] == firstCardId + assert col.find_cards("", order=True)[-1] in latestCardIds + assert col.find_cards("", order=True)[0] == firstCardId col.set_config_bool(Config.Bool.BROWSER_SORT_BACKWARDS, True) - col.flush() - assert col.findCards("", order=True)[0] in latestCardIds + assert col.find_cards("", order=True)[0] in latestCardIds assert ( col.find_cards("", order=col.get_browser_column("cardDue"), reverse=False)[0] == firstCardId @@ -136,42 +132,42 @@ def test_findCards(): != firstCardId ) # model - assert len(col.findCards("note:basic")) == 3 - assert len(col.findCards("-note:basic")) == 2 - assert len(col.findCards("-note:foo")) == 5 + assert len(col.find_cards("note:basic")) == 3 + assert len(col.find_cards("-note:basic")) == 2 + assert len(col.find_cards("-note:foo")) == 5 # col - assert len(col.findCards("deck:default")) == 5 - assert len(col.findCards("-deck:default")) == 0 - assert len(col.findCards("-deck:foo")) == 5 - assert len(col.findCards("deck:def*")) == 5 - assert len(col.findCards("deck:*EFAULT")) == 5 - assert len(col.findCards("deck:*cefault")) == 0 + assert len(col.find_cards("deck:default")) == 5 + assert len(col.find_cards("-deck:default")) == 0 + assert len(col.find_cards("-deck:foo")) == 5 + assert len(col.find_cards("deck:def*")) == 5 + assert len(col.find_cards("deck:*EFAULT")) == 5 + assert len(col.find_cards("deck:*cefault")) == 0 # full search note = col.newNote() note["Front"] = "helloworld" note["Back"] = "abc" col.addNote(note) # as it's the sort field, it matches - assert len(col.findCards("helloworld")) == 2 - # assert len(col.findCards("helloworld", full=True)) == 2 + assert len(col.find_cards("helloworld")) == 2 + # assert len(col.find_cards("helloworld", full=True)) == 2 # if we put it on the back, it won't (note["Front"], note["Back"]) = (note["Back"], note["Front"]) note.flush() - assert len(col.findCards("helloworld")) == 0 - # assert len(col.findCards("helloworld", full=True)) == 2 - # assert len(col.findCards("back:helloworld", full=True)) == 2 + assert len(col.find_cards("helloworld")) == 0 + # assert len(col.find_cards("helloworld", full=True)) == 2 + # assert len(col.find_cards("back:helloworld", full=True)) == 2 # searching for an invalid special tag should not error with pytest.raises(Exception): - len(col.findCards("is:invalid")) + len(col.find_cards("is:invalid")) # should be able to limit to parent col, no children id = col.db.scalar("select id from cards limit 1") col.db.execute( "update cards set did = ? where id = ?", col.decks.id("Default::Child"), id ) col.save() - assert len(col.findCards("deck:default")) == 7 - assert len(col.findCards("deck:default::child")) == 1 - assert len(col.findCards("deck:default -deck:default::*")) == 6 + assert len(col.find_cards("deck:default")) == 7 + assert len(col.find_cards("deck:default::child")) == 1 + assert len(col.find_cards("deck:default -deck:default::*")) == 6 # properties id = col.db.scalar("select id from cards limit 1") col.db.execute( @@ -179,61 +175,61 @@ def test_findCards(): "where id = ?", id, ) - assert len(col.findCards("prop:ivl>5")) == 1 - assert len(col.findCards("prop:ivl<5")) > 1 - assert len(col.findCards("prop:ivl>=5")) == 1 - assert len(col.findCards("prop:ivl=9")) == 0 - assert len(col.findCards("prop:ivl=10")) == 1 - assert len(col.findCards("prop:ivl!=10")) > 1 - assert len(col.findCards("prop:due>0")) == 1 + assert len(col.find_cards("prop:ivl>5")) == 1 + assert len(col.find_cards("prop:ivl<5")) > 1 + assert len(col.find_cards("prop:ivl>=5")) == 1 + assert len(col.find_cards("prop:ivl=9")) == 0 + assert len(col.find_cards("prop:ivl=10")) == 1 + assert len(col.find_cards("prop:ivl!=10")) > 1 + assert len(col.find_cards("prop:due>0")) == 1 # due dates should work - assert len(col.findCards("prop:due=29")) == 0 - assert len(col.findCards("prop:due=30")) == 1 + assert len(col.find_cards("prop:due=29")) == 0 + assert len(col.find_cards("prop:due=30")) == 1 # ease factors - assert len(col.findCards("prop:ease=2.3")) == 0 - assert len(col.findCards("prop:ease=2.2")) == 1 - assert len(col.findCards("prop:ease>2")) == 1 - assert len(col.findCards("-prop:ease>2")) > 1 + assert len(col.find_cards("prop:ease=2.3")) == 0 + assert len(col.find_cards("prop:ease=2.2")) == 1 + assert len(col.find_cards("prop:ease>2")) == 1 + assert len(col.find_cards("-prop:ease>2")) > 1 # recently failed if not isNearCutoff(): # rated - assert len(col.findCards("rated:1:1")) == 0 - assert len(col.findCards("rated:1:2")) == 0 + assert len(col.find_cards("rated:1:1")) == 0 + assert len(col.find_cards("rated:1:2")) == 0 c = col.sched.getCard() col.sched.answerCard(c, 2) - assert len(col.findCards("rated:1:1")) == 0 - assert len(col.findCards("rated:1:2")) == 1 + assert len(col.find_cards("rated:1:1")) == 0 + assert len(col.find_cards("rated:1:2")) == 1 c = col.sched.getCard() col.sched.answerCard(c, 1) - assert len(col.findCards("rated:1:1")) == 1 - assert len(col.findCards("rated:1:2")) == 1 - assert len(col.findCards("rated:1")) == 2 - assert len(col.findCards("rated:2:2")) == 1 - assert len(col.findCards("rated:0")) == len(col.findCards("rated:1")) + assert len(col.find_cards("rated:1:1")) == 1 + assert len(col.find_cards("rated:1:2")) == 1 + assert len(col.find_cards("rated:1")) == 2 + assert len(col.find_cards("rated:2:2")) == 1 + assert len(col.find_cards("rated:0")) == len(col.find_cards("rated:1")) # added col.db.execute("update cards set id = id - 86400*1000 where id = ?", id) - assert len(col.findCards("added:1")) == col.cardCount() - 1 - assert len(col.findCards("added:2")) == col.cardCount() - assert len(col.findCards("added:0")) == len(col.findCards("added:1")) + assert len(col.find_cards("added:1")) == col.card_count() - 1 + assert len(col.find_cards("added:2")) == col.card_count() + assert len(col.find_cards("added:0")) == len(col.find_cards("added:1")) else: print("some find tests disabled near cutoff") # empty field - assert len(col.findCards("front:")) == 0 + assert len(col.find_cards("front:")) == 0 note = col.newNote() note["Front"] = "" note["Back"] = "abc2" assert col.addNote(note) == 1 - assert len(col.findCards("front:")) == 1 + assert len(col.find_cards("front:")) == 1 # OR searches and nesting - assert len(col.findCards("tag:monkey or tag:sheep")) == 2 - assert len(col.findCards("(tag:monkey OR tag:sheep)")) == 2 - assert len(col.findCards("-(tag:monkey OR tag:sheep)")) == 6 - assert len(col.findCards("tag:monkey or (tag:sheep sheep)")) == 2 - assert len(col.findCards("tag:monkey or (tag:sheep octopus)")) == 1 + assert len(col.find_cards("tag:monkey or tag:sheep")) == 2 + assert len(col.find_cards("(tag:monkey OR tag:sheep)")) == 2 + assert len(col.find_cards("-(tag:monkey OR tag:sheep)")) == 6 + assert len(col.find_cards("tag:monkey or (tag:sheep sheep)")) == 2 + assert len(col.find_cards("tag:monkey or (tag:sheep octopus)")) == 1 # flag with pytest.raises(Exception): - col.findCards("flag:12") + col.find_cards("flag:12") def test_findReplace(): @@ -304,15 +300,15 @@ def test_findDupes(): note4["Front"] = "quuux" note4["Back"] = "nope" col.addNote(note4) - r = col.findDupes("Back") + r = col.find_dupes("Back") assert r[0][0] == "bar" assert len(r[0][1]) == 3 # valid search - r = col.findDupes("Back", "bar") + r = col.find_dupes("Back", "bar") assert r[0][0] == "bar" assert len(r[0][1]) == 3 # excludes everything - r = col.findDupes("Back", "invalid") + r = col.find_dupes("Back", "invalid") assert not r # front isn't dupe - assert col.findDupes("Front") == [] + assert col.find_dupes("Front") == [] diff --git a/pylib/tests/test_flags.py b/pylib/tests/test_flags.py index 9408b7099..8d4779be5 100644 --- a/pylib/tests/test_flags.py +++ b/pylib/tests/test_flags.py @@ -17,16 +17,16 @@ def test_flags(): c.flush() # no flags to start with assert c.user_flag() == 0 - assert len(col.findCards("flag:0")) == 1 - assert len(col.findCards("flag:1")) == 0 + assert len(col.find_cards("flag:0")) == 1 + assert len(col.find_cards("flag:1")) == 0 # set flag 2 col.set_user_flag_for_cards(2, [c.id]) c.load() assert c.user_flag() == 2 assert c.flags & origBits == origBits - assert len(col.findCards("flag:0")) == 0 - assert len(col.findCards("flag:2")) == 1 - assert len(col.findCards("flag:3")) == 0 + assert len(col.find_cards("flag:0")) == 0 + assert len(col.find_cards("flag:2")) == 1 + assert len(col.find_cards("flag:3")) == 0 # change to 3 col.set_user_flag_for_cards(3, [c.id]) c.load() diff --git a/pylib/tests/test_importing.py b/pylib/tests/test_importing.py index 71f39cc16..40dc4d7c5 100644 --- a/pylib/tests/test_importing.py +++ b/pylib/tests/test_importing.py @@ -115,9 +115,9 @@ def test_anki2_diffmodel_templates(): imp.dupeOnSchemaChange = True imp.run() # collection should contain the note we imported - assert dst.noteCount() == 1 + assert dst.note_count() == 1 # the front template should contain the text added in the 2nd package - tcid = dst.findCards("")[0] # only 1 note in collection + tcid = dst.find_cards("")[0] # only 1 note in collection tnote = dst.getCard(tcid).note() assert "Changed Front Template" in tnote.cards()[0].template()["qfmt"] @@ -138,7 +138,7 @@ def test_anki2_updates(): assert imp.added == 0 assert imp.updated == 0 # importing a newer note should update - assert dst.noteCount() == 1 + assert dst.note_count() == 1 assert dst.db.scalar("select flds from notes").startswith("hello") col = getUpgradeDeckPath("update2.apkg") imp = AnkiPackageImporter(dst, col) @@ -146,7 +146,7 @@ def test_anki2_updates(): assert imp.dupes == 0 assert imp.added == 0 assert imp.updated == 1 - assert dst.noteCount() == 1 + assert dst.note_count() == 1 assert dst.db.scalar("select flds from notes").startswith("goodbye") @@ -176,12 +176,12 @@ def test_csv(): i.run() assert i.total == 0 # and if dupes mode, will reimport everything - assert col.cardCount() == 5 + assert col.card_count() == 5 i.importMode = 2 i.run() # includes repeated field assert i.total == 6 - assert col.cardCount() == 11 + assert col.card_count() == 11 col.close() @@ -330,7 +330,7 @@ def test_mnemo(): file = str(os.path.join(testDir, "support", "mnemo.db")) i = MnemosyneImporter(col, file) i.run() - assert col.cardCount() == 7 + assert col.card_count() == 7 assert "a_longer_tag" in col.tags.all() assert col.db.scalar(f"select count() from cards where type = {CARD_TYPE_NEW}") == 1 col.close() diff --git a/pylib/tests/test_models.py b/pylib/tests/test_models.py index 25f06dd07..f201ae47c 100644 --- a/pylib/tests/test_models.py +++ b/pylib/tests/test_models.py @@ -16,9 +16,9 @@ def test_modelDelete(): note["Front"] = "1" note["Back"] = "2" col.addNote(note) - assert col.cardCount() == 1 + assert col.card_count() == 1 col.models.remove(col.models.current()["id"]) - assert col.cardCount() == 0 + assert col.card_count() == 0 def test_modelCopy(): @@ -95,7 +95,7 @@ def test_templates(): note["Front"] = "1" note["Back"] = "2" col.addNote(note) - assert col.cardCount() == 2 + assert col.card_count() == 2 (c, c2) = note.cards() # first card should have first ord assert c.ord == 0 @@ -110,7 +110,7 @@ def test_templates(): # removing a template should delete its cards col.models.remove_template(m, m["tmpls"][0]) col.models.update(m) - assert col.cardCount() == 1 + assert col.card_count() == 1 # and should have updated the other cards' ordinals c = note.cards()[0] assert c.ord == 0 @@ -146,7 +146,7 @@ def test_cloze_ordinals(): note = col.newNote() note["Text"] = "{{c1::firstQ::firstA}}{{c2::secondQ::secondA}}" col.addNote(note) - assert col.cardCount() == 2 + assert col.card_count() == 2 (c, c2) = note.cards() # first card should have first ord assert c.ord == 0 @@ -202,10 +202,10 @@ def test_cloze(): note.cards()[0].answer() ) # if we add another cloze, a card should be generated - cnt = col.cardCount() + cnt = col.card_count() note["Text"] = "{{c2::hello}} {{c1::foo}}" note.flush() - assert col.cardCount() == cnt + 1 + assert col.card_count() == cnt + 1 # 0 or negative indices are not supported note["Text"] += "{{c0::zero}} {{c-1:foo}}" note.flush() diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index 38f02b299..ef5073fb2 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -15,7 +15,7 @@ def getEmptyCol() -> Collection: col = getEmptyColOrig() # only safe in test environment col.set_config("schedVer", 1) - col._loadScheduler() + col._load_scheduler() return col @@ -820,7 +820,7 @@ def test_ordcycle(): note["Front"] = "1" note["Back"] = "1" col.addNote(note) - assert col.cardCount() == 3 + assert col.card_count() == 3 col.reset() # ordinals should arrive in order assert col.sched.getCard().ord == 0 diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index 5254b82c6..b18d51690 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -894,7 +894,7 @@ def test_ordcycle(): note["Front"] = "1" note["Back"] = "1" col.addNote(note) - assert col.cardCount() == 3 + assert col.card_count() == 3 conf = col.decks.get_config(1) conf["new"]["bury"] = False diff --git a/pylib/tests/test_stats.py b/pylib/tests/test_stats.py index c79777044..e6179f968 100644 --- a/pylib/tests/test_stats.py +++ b/pylib/tests/test_stats.py @@ -14,12 +14,12 @@ def test_stats(): col.addNote(note) c = note.cards()[0] # card stats - assert col.cardStats(c) + assert col.card_stats(c.id, include_revlog=True) col.reset() c = col.sched.getCard() col.sched.answerCard(c, 3) col.sched.answerCard(c, 2) - assert col.cardStats(c) + assert col.card_stats(c.id, include_revlog=True) def test_graphs_empty(): diff --git a/pylib/tests/test_undo.py b/pylib/tests/test_undo.py index 9bef9190a..6988adc8a 100644 --- a/pylib/tests/test_undo.py +++ b/pylib/tests/test_undo.py @@ -16,33 +16,33 @@ def getEmptyCol(): def test_op(): col = getEmptyCol() # should have no undo by default - assert not col.undoName() + assert not col.undo_status().undo # let's adjust a study option col.save("studyopts") col.conf["abc"] = 5 # it should be listed as undoable - assert col.undoName() == "studyopts" + assert col.undo_status().undo == "studyopts" # with about 5 minutes until it's clobbered assert time.time() - col._last_checkpoint_at < 1 # undoing should restore the old value col.undo_legacy() - assert not col.undoName() + assert not col.undo_status().undo assert "abc" not in col.conf # an (auto)save will clear the undo col.save("foo") - assert col.undoName() == "foo" + assert col.undo_status().undo == "foo" col.save() - assert not col.undoName() + assert not col.undo_status().undo # and a review will, too col.save("add") note = col.newNote() note["Front"] = "one" col.addNote(note) col.reset() - assert "add" in col.undoName().lower() + assert "add" in col.undo_status().undo.lower() c = col.sched.getCard() col.sched.answerCard(c, 2) - assert col.undoName() == "Review" + assert col.undo_status().undo == "Review" def test_review(): @@ -64,14 +64,14 @@ def test_review(): assert col.sched.counts() == (1, 1, 0) assert c.queue == QUEUE_TYPE_LRN # undo - assert col.undoName() + assert col.undo_status().undo col.undo_legacy() col.reset() assert col.sched.counts() == (2, 0, 0) c.load() assert c.queue == QUEUE_TYPE_NEW assert c.left % 1000 != 1 - assert not col.undoName() + assert not col.undo_status().undo # we should be able to undo multiple answers too c = col.sched.getCard() col.sched.answerCard(c, 3) @@ -87,8 +87,8 @@ def test_review(): # performing a normal op will clear the review queue c = col.sched.getCard() col.sched.answerCard(c, 3) - assert col.undoName() == "Review" + assert col.undo_status().undo == "Review" col.save("foo") - assert col.undoName() == "foo" + assert col.undo_status().undo == "foo" col.undo_legacy() - assert not col.undoName() + assert not col.undo_status().undo diff --git a/qt/aqt/browser/browser.py b/qt/aqt/browser/browser.py index f284cf22d..6d6c91b9b 100644 --- a/qt/aqt/browser/browser.py +++ b/qt/aqt/browser/browser.py @@ -521,7 +521,7 @@ class Browser(QMainWindow): def createFilteredDeck(self) -> None: search = self.current_search() - if self.mw.col.schedVer() != 1 and KeyboardModifiersPressed().alt: + if self.mw.col.sched_ver() != 1 and KeyboardModifiersPressed().alt: aqt.dialogs.open("FilteredDeckConfigDialog", self.mw, search_2=search) else: aqt.dialogs.open("FilteredDeckConfigDialog", self.mw, search=search) diff --git a/qt/aqt/browser/find_duplicates.py b/qt/aqt/browser/find_duplicates.py index 9703a9ce7..69b1c7420 100644 --- a/qt/aqt/browser/find_duplicates.py +++ b/qt/aqt/browser/find_duplicates.py @@ -65,7 +65,7 @@ class FindDuplicatesDialog(QDialog): field = fields[form.fields.currentIndex()] QueryOp( parent=self.browser, - op=lambda col: col.findDupes(field, search_text), + op=lambda col: col.find_dupes(field, search_text), success=self.show_duplicates_report, ).run_in_background() diff --git a/qt/aqt/dbcheck.py b/qt/aqt/dbcheck.py index 44d43a9a7..00e70adbd 100644 --- a/qt/aqt/dbcheck.py +++ b/qt/aqt/dbcheck.py @@ -53,4 +53,4 @@ def check_db(mw: aqt.AnkiQt) -> None: n += 1 continue - mw.taskman.with_progress(mw.col.fixIntegrity, on_future_done) + mw.taskman.with_progress(mw.col.fix_integrity, on_future_done) diff --git a/qt/aqt/deckbrowser.py b/qt/aqt/deckbrowser.py index cb392a495..008dae830 100644 --- a/qt/aqt/deckbrowser.py +++ b/qt/aqt/deckbrowser.py @@ -349,7 +349,7 @@ class DeckBrowser: ###################################################################### def _v1_upgrade_message(self) -> str: - if self.mw.col.schedVer() == 2: + if self.mw.col.sched_ver() == 2: return "" return f""" @@ -371,7 +371,7 @@ class DeckBrowser: """ def _confirm_upgrade(self) -> None: - self.mw.col.modSchema(check=True) + self.mw.col.mod_schema(check=True) self.mw.col.upgrade_to_v2_scheduler() showInfo(tr.scheduling_update_done()) diff --git a/qt/aqt/deckconf.py b/qt/aqt/deckconf.py index 592f7e298..c5cf42e5d 100644 --- a/qt/aqt/deckconf.py +++ b/qt/aqt/deckconf.py @@ -144,7 +144,7 @@ class DeckConf(QDialog): showInfo(tr.scheduling_the_default_configuration_cant_be_removed(), self) else: gui_hooks.deck_conf_will_remove_config(self, self.deck, self.conf) - self.mw.col.modSchema(check=True) + self.mw.col.mod_schema(check=True) self.mw.col.decks.remove_config(self.conf["id"]) self.conf = None self.deck["conf"] = 1 @@ -220,7 +220,7 @@ class DeckConf(QDialog): f.revplim.setText(self.parentLimText("rev")) f.buryRev.setChecked(c.get("bury", True)) f.hardFactor.setValue(int(c.get("hardFactor", 1.2) * 100)) - if self.mw.col.schedVer() == 1: + if self.mw.col.sched_ver() == 1: f.hardFactor.setVisible(False) f.hardFactorLabel.setVisible(False) # lapse diff --git a/qt/aqt/deckoptions.py b/qt/aqt/deckoptions.py index 937d949fd..3e87cfcda 100644 --- a/qt/aqt/deckoptions.py +++ b/qt/aqt/deckoptions.py @@ -106,7 +106,7 @@ def display_options_for_deck_id(deck_id: DeckId) -> None: def display_options_for_deck(deck: DeckDict) -> None: if not deck["dyn"]: - if KeyboardModifiersPressed().shift or aqt.mw.col.schedVer() == 1: + if KeyboardModifiersPressed().shift or aqt.mw.col.sched_ver() == 1: deck_legacy = aqt.mw.col.decks.get(DeckId(deck["id"])) aqt.deckconf.DeckConf(aqt.mw, deck_legacy) else: diff --git a/qt/aqt/filtered_deck.py b/qt/aqt/filtered_deck.py index 8875d658e..d62922d98 100644 --- a/qt/aqt/filtered_deck.py +++ b/qt/aqt/filtered_deck.py @@ -95,7 +95,7 @@ class FilteredDeckConfigDialog(QDialog): self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.FILTERED_DECK) ) - if self.col.schedVer() == 1: + if self.col.sched_ver() == 1: self.form.secondFilter.setVisible(False) restoreGeom(self, self.GEOMETRY_KEY) @@ -127,7 +127,7 @@ class FilteredDeckConfigDialog(QDialog): form.order.setCurrentIndex(term1.order) form.limit.setValue(term1.limit) - if self.col.schedVer() == 1: + if self.col.sched_ver() == 1: if config.delays: form.steps.setText(self.listToUser(list(config.delays))) form.stepsOn.setChecked(True) @@ -227,7 +227,7 @@ class FilteredDeckConfigDialog(QDialog): """Return a search node that matches learning cards if the old scheduler is enabled. If it's a rebuild, exclude cards from this filtered deck as those will be reset. """ - if self.col.schedVer() == 1: + if self.col.sched_ver() == 1: if self.deck.id: return ( self.col.group_searches( @@ -252,7 +252,7 @@ class FilteredDeckConfigDialog(QDialog): def _onReschedToggled(self, _state: int) -> None: self.form.previewDelayWidget.setVisible( - not self.form.resched.isChecked() and self.col.schedVer() > 1 + not self.form.resched.isChecked() and self.col.sched_ver() > 1 ) def _update_deck(self) -> bool: @@ -266,7 +266,7 @@ class FilteredDeckConfigDialog(QDialog): config.reschedule = form.resched.isChecked() del config.delays[:] - if self.col.schedVer() == 1 and form.stepsOn.isChecked(): + if self.col.sched_ver() == 1 and form.stepsOn.isChecked(): if (delays := self.userToList(form.steps)) is None: return False config.delays.extend(delays) diff --git a/qt/aqt/importing.py b/qt/aqt/importing.py index c1af62f81..4d3e62a8a 100644 --- a/qt/aqt/importing.py +++ b/qt/aqt/importing.py @@ -499,7 +499,7 @@ def _replaceWithApkg(mw: aqt.AnkiQt, filename: str, backup: bool) -> None: if not mw.loadCollection(): return if backup: - mw.col.modSchema(check=False) + mw.col.mod_schema(check=False) tooltip(tr.importing_importing_complete()) diff --git a/qt/aqt/main.py b/qt/aqt/main.py index c993abe6e..4eac01f5e 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -527,7 +527,7 @@ class AnkiQt(QMainWindow): def _loadCollection(self) -> None: cpath = self.pm.collectionPath() - self.col = Collection(cpath, backend=self.backend, log=True) + self.col = Collection(cpath, backend=self.backend) self.setEnabled(True) def reopen(self) -> None: @@ -1358,7 +1358,7 @@ title="%s" %s>%s""" % ( def confirm_schema_modification(self) -> bool: """If schema unmodified, ask user to confirm change. True if confirmed or already modified.""" - if self.col.schemaChanged(): + if self.col.schema_changed(): return True return askUser(tr.qt_misc_the_requested_change_will_require_a()) diff --git a/qt/aqt/overview.py b/qt/aqt/overview.py index af1131834..43210ad73 100644 --- a/qt/aqt/overview.py +++ b/qt/aqt/overview.py @@ -143,7 +143,7 @@ class Overview: def on_unbury(self) -> None: mode = UnburyDeck.Mode.ALL - if self.mw.col.schedVer() != 1: + if self.mw.col.sched_ver() != 1: info = self.mw.col.sched.congratulations_info() if info.have_sched_buried and info.have_user_buried: opts = [ diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py index 1a41315e7..d1cbdbc39 100644 --- a/qt/aqt/preferences.py +++ b/qt/aqt/preferences.py @@ -203,7 +203,7 @@ for you than the default driver, please let us know on the Anki forums.""" self.form.autoSyncMedia.isChecked() and 15 or 0 ) if self.form.fullSync.isChecked(): - self.mw.col.modSchema(check=False) + self.mw.col.mod_schema(check=False) # Profile: backup ###################################################################### diff --git a/qt/aqt/utils.py b/qt/aqt/utils.py index 3ee2c65e6..83484eb56 100644 --- a/qt/aqt/utils.py +++ b/qt/aqt/utils.py @@ -891,7 +891,7 @@ def supportText() -> str: def schedVer() -> str: try: - return str(mw.col.schedVer()) + return str(mw.col.sched_ver()) except: return "?"