From 6118d01de11a8d9e098c35b76f494c015ec3f881 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 5 Jan 2020 11:42:59 -0800 Subject: [PATCH] Remove support for Anki 2.0 and Python 2 --- plugin/__init__.py | 190 +++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 129 deletions(-) diff --git a/plugin/__init__.py b/plugin/__init__.py index a243996..3afe6b8 100644 --- a/plugin/__init__.py +++ b/plugin/__init__.py @@ -47,48 +47,24 @@ TICK_INTERVAL = 25 URL_TIMEOUT = 10 URL_UPGRADE = 'https://raw.githubusercontent.com/FooSoft/anki-connect/master/AnkiConnect.py' -ANKI21 = anki.version.startswith('2.1') - config = aqt.mw.addonManager.getConfig('AnkiConnect') # # Helpers # -if sys.version_info[0] < 3: - import urllib2 - def download(url): - contents = None - resp = urllib2.urlopen(url, timeout=URL_TIMEOUT) - if resp.code == 200: - contents = resp.read() - return (resp.code, contents) +from anki.sync import AnkiRequestsClient +def download(url): + contents = None + client = AnkiRequestsClient() + client.timeout = URL_TIMEOUT + resp = client.get(url) + if resp.status_code == 200: + contents = client.streamContent(resp) + return (resp.status_code, contents) - from PyQt4.QtCore import QTimer - from PyQt4.QtGui import QMessageBox -else: - unicode = str - - from anki.sync import AnkiRequestsClient - def download(url): - contents = None - client = AnkiRequestsClient() - client.timeout = URL_TIMEOUT - resp = client.get(url) - if resp.status_code == 200: - contents = client.streamContent(resp) - return (resp.status_code, contents) - - from PyQt5.QtCore import QTimer - from PyQt5.QtWidgets import QMessageBox - - -def makeBytes(data): - return data.encode('utf-8') - - -def makeStr(data): - return data.decode('utf-8') +from PyQt5.QtCore import QTimer +from PyQt5.QtWidgets import QMessageBox def api(*versions): @@ -162,17 +138,17 @@ class WebClient: def parseRequest(self, data): - parts = data.split(makeBytes('\r\n\r\n'), 1) + parts = data.split('\r\n\r\n'.encode('utf-8'), 1) if len(parts) == 1: return None, 0 headers = {} - for line in parts[0].split(makeBytes('\r\n')): - pair = line.split(makeBytes(': ')) + for line in parts[0].split('\r\n'.encode('utf-8')): + pair = line.split(': '.encode('utf-8')) headers[pair[0].lower()] = pair[1] if len(pair) > 1 else None headerLength = len(parts[0]) + 4 - bodyLength = int(headers.get(makeBytes('content-length'), 0)) + bodyLength = int(headers.get('content-length'.encode('utf-8'), 0)) totalLength = headerLength + bodyLength if totalLength > len(data): @@ -248,13 +224,13 @@ class WebServer: def handlerWrapper(self, req): if len(req.body) == 0: - body = makeBytes('AnkiConnect v.{}'.format(API_VERSION)) + body = 'AnkiConnect v.{}'.format(API_VERSION).encode('utf-8') else: try: - params = json.loads(makeStr(req.body)) - body = makeBytes(json.dumps(self.handler(params))) + params = json.loads(req.body.decode('utf-8')) + body = json.dumps(self.handler(params)).encode('utf-8') except ValueError: - body = makeBytes(json.dumps(None)) + body = json.dumps(None).encode('utf-8') resp = bytes() @@ -263,11 +239,11 @@ class WebServer: for key, value in headers: if value is None: - resp += makeBytes('{}\r\n'.format(key)) + resp += '{}\r\n'.format(key).encode('utf-8') else: - resp += makeBytes('{}: {}\r\n'.format(key, value)) + resp += '{}: {}\r\n'.format(key, value).encode('utf-8') - resp += makeBytes('\r\n') + resp += '\r\n'.encode('utf-8') resp += body return resp @@ -498,7 +474,7 @@ class AnkiConnect: data = self.download(URL_UPGRADE) path = os.path.splitext(__file__)[0] + '.py' with open(path, 'w') as fp: - fp.write(makeStr(data)) + fp.write(data.decode('utf-8')) QMessageBox.information( self.window(), 'AnkiConnect', @@ -1168,85 +1144,47 @@ class AnkiConnect: randomString = ''.join(choice(ascii_letters) for _ in range(10)) windowName = 'AddCardsAndClose' + randomString - if ANKI21: - class AddCardsAndClose(aqt.addcards.AddCards): + class AddCardsAndClose(aqt.addcards.AddCards): - def __init__(self, mw): - # the window must only reset if - # * function `onModelChange` has been called prior - # * window was newly opened + def __init__(self, mw): + # the window must only reset if + # * function `onModelChange` has been called prior + # * window was newly opened + self.modelHasChanged = True + super().__init__(mw) + + self.addButton.setText("Add and Close") + self.addButton.setShortcut(aqt.qt.QKeySequence("Ctrl+Return")) + + def _addCards(self): + super()._addCards() + + # if adding was successful it must mean it was added to the history of the window + if len(self.history): + self.reject() + + def onModelChange(self): + if self.isActiveWindow(): + super().onModelChange() self.modelHasChanged = True - super().__init__(mw) - self.addButton.setText("Add and Close") - self.addButton.setShortcut(aqt.qt.QKeySequence("Ctrl+Return")) + def onReset(self, model=None, keep=False): + if self.isActiveWindow() or self.modelHasChanged: + super().onReset(model, keep) + self.modelHasChanged = False - def _addCards(self): - super()._addCards() + else: + # modelchoosers text is changed by a reset hook + # therefore we need to change it back manually + self.modelChooser.models.setText(self.editor.note.model()['name']) + self.modelHasChanged = False - # if adding was successful it must mean it was added to the history of the window - if len(self.history): - self.reject() - - def onModelChange(self): - if self.isActiveWindow(): - super().onModelChange() - self.modelHasChanged = True - - def onReset(self, model=None, keep=False): - if self.isActiveWindow() or self.modelHasChanged: - super().onReset(model, keep) - self.modelHasChanged = False - - else: - # modelchoosers text is changed by a reset hook - # therefore we need to change it back manually - self.modelChooser.models.setText(self.editor.note.model()['name']) - self.modelHasChanged = False - - def _reject(self): - savedMarkClosed = aqt.dialogs.markClosed - aqt.dialogs.markClosed = lambda _: savedMarkClosed(windowName) - super()._reject() - aqt.dialogs.markClosed = savedMarkClosed - - else: - class AddCardsAndClose(aqt.addcards.AddCards): - - def __init__(self, mw): - self.modelHasChanged = True - super(AddCardsAndClose, self).__init__(mw) - - self.addButton.setText("Add and Close") - self.addButton.setShortcut(aqt.qt.QKeySequence("Ctrl+Return")) - - def addCards(self): - super(AddCardsAndClose, self).addCards() - - # if adding was successful it must mean it was added to the history of the window - if len(self.history): - self.reject() - - def onModelChange(self): - if self.isActiveWindow(): - super(AddCardsAndClose, self).onModelChange() - self.modelHasChanged = True - - def onReset(self, model=None, keep=False): - if self.isActiveWindow() or self.modelHasChanged: - super(AddCardsAndClose, self).onReset(model, keep) - self.modelHasChanged = False - - else: - self.modelChooser.models.setText(self.editor.note.model()['name']) - self.modelHasChanged = False - - def reject(self): - savedClose = aqt.dialogs.close - aqt.dialogs.close = lambda _: savedClose(windowName) - super(AddCardsAndClose, self).reject() - aqt.dialogs.close = savedClose + def _reject(self): + savedMarkClosed = aqt.dialogs.markClosed + aqt.dialogs.markClosed = lambda _: savedMarkClosed(windowName) + super()._reject() + aqt.dialogs.markClosed = savedMarkClosed aqt.dialogs._dialogs[windowName] = [AddCardsAndClose, None] addCards = aqt.dialogs.open(windowName, self.window()) @@ -1270,8 +1208,7 @@ class AnkiConnect: # if Anki does not Focus, the window will not notice that the # fields are actually filled aqt.dialogs.open(windowName, self.window()) - if ANKI21: - addCards.setAndFocusNote(editor.note) + addCards.setAndFocusNote(editor.note) elif note is not None: currentWindow = aqt.dialogs._dialogs['AddCards'][1] @@ -1300,15 +1237,10 @@ class AnkiConnect: addCards.activateWindow() aqt.dialogs.open('AddCards', self.window()) - if ANKI21: - addCards.setAndFocusNote(editor.note) + addCards.setAndFocusNote(editor.note) if currentWindow is not None: - if ANKI21: - currentWindow.closeWithCallback(openNewWindow) - else: - currentWindow.reject() - openNewWindow() + currentWindow.closeWithCallback(openNewWindow) else: openNewWindow()