add col.weakref() and fix more reference cycles in pylib

This commit is contained in:
Damien Elmes 2020-03-05 09:47:47 +10:00
parent 6b204274c0
commit 862e2b48f0
15 changed files with 29 additions and 22 deletions

View file

@ -36,7 +36,7 @@ class Card:
def __init__( def __init__(
self, col: anki.collection._Collection, id: Optional[int] = None self, col: anki.collection._Collection, id: Optional[int] = None
) -> None: ) -> None:
self.col = col self.col = col.weakref()
self.timerStarted = None self.timerStarted = None
self._render_output: Optional[anki.template.TemplateRenderOutput] = None self._render_output: Optional[anki.template.TemplateRenderOutput] = None
self._note = None self._note = None

View file

@ -1,6 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors # Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import copy import copy
import datetime import datetime
import json import json
@ -12,6 +14,7 @@ import stat
import time import time
import traceback import traceback
import unicodedata import unicodedata
import weakref
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
import anki.find import anki.find
@ -114,6 +117,10 @@ class _Collection:
def tr(self, key: TR, **kwargs: Union[str, int, float]) -> str: def tr(self, key: TR, **kwargs: Union[str, int, float]) -> str:
return self.backend.translate(key, **kwargs) return self.backend.translate(key, **kwargs)
def weakref(self) -> anki.storage._Collection:
"Shortcut to create a weak reference that doesn't break code completion."
return weakref.proxy(self)
# Scheduler # Scheduler
########################################################################## ##########################################################################

View file

@ -7,7 +7,6 @@ import copy
import json import json
import operator import operator
import unicodedata import unicodedata
import weakref
from typing import Any, Dict, List, Optional, Set, Tuple, Union from typing import Any, Dict, List, Optional, Set, Tuple, Union
import anki # pylint: disable=unused-import import anki # pylint: disable=unused-import
@ -102,7 +101,7 @@ class DeckManager:
############################################################# #############################################################
def __init__(self, col: anki.storage._Collection) -> None: def __init__(self, col: anki.storage._Collection) -> None:
self.col = weakref.proxy(col) self.col = col.weakref()
self.decks = {} self.decks = {}
self.dconf = {} self.dconf = {}

View file

@ -27,7 +27,7 @@ class Exporter:
did: Optional[int] = None, did: Optional[int] = None,
cids: Optional[List[int]] = None, cids: Optional[List[int]] = None,
) -> None: ) -> None:
self.col = col self.col = col.weakref()
self.did = did self.did = did
self.cids = cids self.cids = cids

View file

@ -1,5 +1,6 @@
# Copyright: Ankitects Pty Ltd and contributors # Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations from __future__ import annotations
import re import re
@ -28,7 +29,7 @@ if TYPE_CHECKING:
class Finder: class Finder:
def __init__(self, col: Optional[_Collection]) -> None: def __init__(self, col: Optional[_Collection]) -> None:
self.col = col self.col = col.weakref()
self.search = dict( self.search = dict(
added=self._findAdded, added=self._findAdded,
card=self._findTemplate, card=self._findTemplate,

View file

@ -19,7 +19,7 @@ class Importer:
def __init__(self, col: _Collection, file: str) -> None: def __init__(self, col: _Collection, file: str) -> None:
self.file = file self.file = file
self.log: List[str] = [] self.log: List[str] = []
self.col = col self.col = col.weakref()
self.total = 0 self.total = 0
self.dst = None self.dst = None

View file

@ -10,7 +10,6 @@ import time
import urllib.error import urllib.error
import urllib.parse import urllib.parse
import urllib.request import urllib.request
import weakref
from typing import Any, Callable, List, Optional, Tuple, Union from typing import Any, Callable, List, Optional, Tuple, Union
import anki import anki
@ -43,7 +42,7 @@ class MediaManager:
regexps = soundRegexps + imgRegexps regexps = soundRegexps + imgRegexps
def __init__(self, col: anki.storage._Collection, server: bool) -> None: def __init__(self, col: anki.storage._Collection, server: bool) -> None:
self.col = weakref.proxy(col) self.col = col.weakref()
if server: if server:
self._dir = None self._dir = None
return return

View file

@ -7,7 +7,6 @@ import copy
import json import json
import re import re
import time import time
import weakref
from typing import Any, Callable, Dict, List, Optional, Tuple, Union from typing import Any, Callable, Dict, List, Optional, Tuple, Union
import anki # pylint: disable=unused-import import anki # pylint: disable=unused-import
@ -92,7 +91,7 @@ class ModelManager:
############################################################# #############################################################
def __init__(self, col: anki.storage._Collection) -> None: def __init__(self, col: anki.storage._Collection) -> None:
self.col = weakref.proxy(col) self.col = col.weakref()
self.models = {} self.models = {}
self.changed = False self.changed = False

View file

@ -40,7 +40,7 @@ class Note:
id: Optional[int] = None, id: Optional[int] = None,
) -> None: ) -> None:
assert not (model and id) assert not (model and id)
self.col = col self.col = col.weakref()
self.newlyAdded = False self.newlyAdded = False
if id: if id:
self.id = id self.id = id

View file

@ -6,7 +6,6 @@ from __future__ import annotations
import itertools import itertools
import random import random
import time import time
import weakref
from heapq import * from heapq import *
from operator import itemgetter from operator import itemgetter
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, Dict, List, Optional, Tuple, Union
@ -32,7 +31,7 @@ class Scheduler(V2):
def __init__( # pylint: disable=super-init-not-called def __init__( # pylint: disable=super-init-not-called
self, col: anki.storage._Collection self, col: anki.storage._Collection
) -> None: ) -> None:
self.col = weakref.proxy(col) self.col = col.weakref()
self.queueLimit = 50 self.queueLimit = 50
self.reportLimit = 1000 self.reportLimit = 1000
self.dynReportLimit = 99999 self.dynReportLimit = 99999

View file

@ -7,7 +7,6 @@ import datetime
import itertools import itertools
import random import random
import time import time
import weakref
from heapq import * from heapq import *
from operator import itemgetter from operator import itemgetter
@ -38,7 +37,7 @@ class Scheduler:
revCount: int revCount: int
def __init__(self, col: anki.storage._Collection) -> None: def __init__(self, col: anki.storage._Collection) -> None:
self.col = weakref.proxy(col) self.col = col.weakref()
self.queueLimit = 50 self.queueLimit = 50
self.reportLimit = 1000 self.reportLimit = 1000
self.dynReportLimit = 99999 self.dynReportLimit = 99999

View file

@ -25,7 +25,7 @@ PERIOD_LIFE = 2
class CardStats: class CardStats:
def __init__(self, col: anki.storage._Collection, card: anki.cards.Card) -> None: def __init__(self, col: anki.storage._Collection, card: anki.cards.Card) -> None:
self.col = col self.col = col.weakref()
self.card = card self.card = card
self.txt = "" self.txt = ""
@ -107,7 +107,7 @@ colSusp = "#ff0"
class CollectionStats: class CollectionStats:
def __init__(self, col: anki.storage._Collection) -> None: def __init__(self, col: anki.storage._Collection) -> None:
self.col = col self.col = col.weakref()
self._stats = None self._stats = None
self.type = PERIOD_MONTH self.type = PERIOD_MONTH
self.width = 600 self.width = 600

View file

@ -35,7 +35,7 @@ class Syncer:
cursor: Optional[sqlite3.Cursor] cursor: Optional[sqlite3.Cursor]
def __init__(self, col: anki.storage._Collection, server=None) -> None: def __init__(self, col: anki.storage._Collection, server=None) -> None:
self.col = col self.col = col.weakref()
self.server = server self.server = server
# these are set later; provide dummy values for type checking # these are set later; provide dummy values for type checking
@ -638,7 +638,7 @@ class FullSyncer(HttpSyncer):
self.postVars = dict( self.postVars = dict(
k=self.hkey, v="ankidesktop,%s,%s" % (anki.version, platDesc()), k=self.hkey, v="ankidesktop,%s,%s" % (anki.version, platDesc()),
) )
self.col = col self.col = col.weakref()
def download(self) -> Optional[str]: def download(self) -> Optional[str]:
hooks.sync_stage_did_change("download") hooks.sync_stage_did_change("download")

View file

@ -13,7 +13,6 @@ from __future__ import annotations
import json import json
import re import re
import weakref
from typing import Callable, Collection, Dict, List, Optional, Tuple from typing import Callable, Collection, Dict, List, Optional, Tuple
import anki # pylint: disable=unused-import import anki # pylint: disable=unused-import
@ -27,7 +26,7 @@ class TagManager:
############################################################# #############################################################
def __init__(self, col: anki.storage._Collection) -> None: def __init__(self, col: anki.storage._Collection) -> None:
self.col = weakref.proxy(col) self.col = col.weakref()
self.tags: Dict[str, int] = {} self.tags: Dict[str, int] = {}
def load(self, json_: str) -> None: def load(self, json_: str) -> None:

View file

@ -6,8 +6,13 @@ from anki.find import Finder
from tests.shared import getEmptyCol from tests.shared import getEmptyCol
class DummyCollection:
def weakref(self):
return None
def test_parse(): def test_parse():
f = Finder(None) f = Finder(DummyCollection())
assert f._tokenize("hello world") == ["hello", "world"] assert f._tokenize("hello world") == ["hello", "world"]
assert f._tokenize("hello world") == ["hello", "world"] assert f._tokenize("hello world") == ["hello", "world"]
assert f._tokenize("one -two") == ["one", "-", "two"] assert f._tokenize("one -two") == ["one", "-", "two"]