bump version, improvements to api

This commit is contained in:
Alex Yatskov 2017-08-30 20:47:08 -07:00
parent 8f9b69ede6
commit 337261245b

View File

@ -35,7 +35,7 @@ from unicodedata import normalize
# Constants # Constants
# #
API_VERSION = 4 API_VERSION = 5
TICK_INTERVAL = 25 TICK_INTERVAL = 25
URL_TIMEOUT = 10 URL_TIMEOUT = 10
URL_UPGRADE = 'https://raw.githubusercontent.com/FooSoft/anki-connect/master/AnkiConnect.py' URL_UPGRADE = 'https://raw.githubusercontent.com/FooSoft/anki-connect/master/AnkiConnect.py'
@ -68,21 +68,15 @@ else:
# Helpers # Helpers
# #
def webapi(*versions): def webApi(*versions):
def decorator(func): def decorator(func):
def method(*args, **kwargs): method = lambda *args, **kwargs: func(*args, **kwargs)
return func(*args, **kwargs)
setattr(method, 'versions', versions) setattr(method, 'versions', versions)
setattr(method, 'api', True) setattr(method, 'api', True)
return method return method
return decorator return decorator
def webApi(func):
func.webApi = True
return func
def makeBytes(data): def makeBytes(data):
return data.encode('utf-8') return data.encode('utf-8')
@ -896,130 +890,127 @@ class AnkiConnect:
def handler(self, request): def handler(self, request):
action = request.get('action', '') name = request.get('action', '')
if hasattr(self, action): version = request.get('version', 4)
handler = getattr(self, action) params = request.get('params', {})
if callable(handler) and hasattr(handler, 'webApi') and getattr(handler, 'webApi'): reply = {'result': None, 'error': None}
spec = inspect.getargspec(handler)
argsAll = spec.args[1:]
argsReq = argsAll
argsDef = spec.defaults try:
if argsDef is not None: method = None
argsReq = argsAll[:-len(argsDef)]
params = request.get('params', {}) for methodName, methodInst in inspect.getmembers(self, predicate=inspect.ismethod):
for argReq in argsReq: apiVersionLast = 0
if argReq not in params: apiNameLast = None
return
for param in params:
if param not in argsAll:
return
return handler(**params) if getattr(methodInst, 'api', False):
for apiVersion, apiName in getattr(methodInst, 'versions', []):
if apiVersionLast < apiVersion <= version:
apiVersionLast = apiVersion
apiNameLast = apiName
if apiNameLast is None and apiVersionLast == 0:
apiNameLast = methodName
if apiNameLast is not None and apiNameLast == name:
method = methodInst
break
if method is None:
raise Exception('unsupported action')
else:
reply['result'] = methodInst(**params)
except Exception as e:
reply['error'] = str(e)
if version > 4:
return reply
else:
return reply['result']
def invoke(self, version, name, *args, **kwargs): @webApi()
for method_name, method_body in inspect.getmembers(self, predicate=inspect.ismethod):
api_version_last = 0
api_name_last = None
if getattr(method_body, 'api', False):
for api_version, api_name in getattr(method_body, 'versions', []):
if api_version_last < api_version <= version:
api_version_last = api_version
api_name_last = api_name
if api_name_last is None and api_version_last == 0:
api_name_last = method_name
if api_name_last is not None and api_name_last == name:
method_body(*args, **kwargs)
@webApi
def multi(self, actions): def multi(self, actions):
return self.anki.multi(actions) return self.anki.multi(actions)
@webApi @webApi()
def storeMediaFile(self, filename, data): def storeMediaFile(self, filename, data):
return self.anki.storeMediaFile(filename, data) return self.anki.storeMediaFile(filename, data)
@webApi @webApi()
def retrieveMediaFile(self, filename): def retrieveMediaFile(self, filename):
return self.anki.retrieveMediaFile(filename) return self.anki.retrieveMediaFile(filename)
@webApi @webApi()
def deleteMediaFile(self, filename): def deleteMediaFile(self, filename):
return self.anki.deleteMediaFile(filename) return self.anki.deleteMediaFile(filename)
@webApi @webApi()
def deckNames(self): def deckNames(self):
return self.anki.deckNames() return self.anki.deckNames()
@webApi @webApi()
def deckNamesAndIds(self): def deckNamesAndIds(self):
return self.anki.deckNamesAndIds() return self.anki.deckNamesAndIds()
@webApi @webApi()
def modelNames(self): def modelNames(self):
return self.anki.modelNames() return self.anki.modelNames()
@webApi @webApi()
def modelNamesAndIds(self): def modelNamesAndIds(self):
return self.anki.modelNamesAndIds() return self.anki.modelNamesAndIds()
@webApi @webApi()
def modelFieldNames(self, modelName): def modelFieldNames(self, modelName):
return self.anki.modelFieldNames(modelName) return self.anki.modelFieldNames(modelName)
@webApi @webApi()
def modelFieldsOnTemplates(self, modelName): def modelFieldsOnTemplates(self, modelName):
return self.anki.modelFieldsOnTemplates(modelName) return self.anki.modelFieldsOnTemplates(modelName)
@webApi @webApi()
def getDeckConfig(self, deck): def getDeckConfig(self, deck):
return self.anki.getDeckConfig(deck) return self.anki.getDeckConfig(deck)
@webApi @webApi()
def saveDeckConfig(self, config): def saveDeckConfig(self, config):
return self.anki.saveDeckConfig(config) return self.anki.saveDeckConfig(config)
@webApi @webApi()
def setDeckConfigId(self, decks, configId): def setDeckConfigId(self, decks, configId):
return self.anki.setDeckConfigId(decks, configId) return self.anki.setDeckConfigId(decks, configId)
@webApi @webApi()
def cloneDeckConfigId(self, name, cloneFrom=1): def cloneDeckConfigId(self, name, cloneFrom=1):
return self.anki.cloneDeckConfigId(name, cloneFrom) return self.anki.cloneDeckConfigId(name, cloneFrom)
@webApi @webApi()
def removeDeckConfigId(self, configId): def removeDeckConfigId(self, configId):
return self.anki.removeDeckConfigId(configId) return self.anki.removeDeckConfigId(configId)
@webApi @webApi()
def addNote(self, note): def addNote(self, note):
params = AnkiNoteParams(note) params = AnkiNoteParams(note)
if params.validate(): if params.validate():
return self.anki.addNote(params) return self.anki.addNote(params)
@webApi @webApi()
def addNotes(self, notes): def addNotes(self, notes):
results = [] results = []
for note in notes: for note in notes:
@ -1032,7 +1023,7 @@ class AnkiConnect:
return results return results
@webApi @webApi()
def canAddNotes(self, notes): def canAddNotes(self, notes):
results = [] results = []
for note in notes: for note in notes:
@ -1042,42 +1033,42 @@ class AnkiConnect:
return results return results
@webApi @webApi()
def addTags(self, notes, tags, add=True): def addTags(self, notes, tags, add=True):
return self.anki.addTags(notes, tags, add) return self.anki.addTags(notes, tags, add)
@webApi @webApi()
def removeTags(self, notes, tags): def removeTags(self, notes, tags):
return self.anki.addTags(notes, tags, False) return self.anki.addTags(notes, tags, False)
@webApi @webApi()
def suspend(self, cards, suspend=True): def suspend(self, cards, suspend=True):
return self.anki.suspend(cards, suspend) return self.anki.suspend(cards, suspend)
@webApi @webApi()
def unsuspend(self, cards): def unsuspend(self, cards):
return self.anki.suspend(cards, False) return self.anki.suspend(cards, False)
@webApi @webApi()
def areSuspended(self, cards): def areSuspended(self, cards):
return self.anki.areSuspended(cards) return self.anki.areSuspended(cards)
@webApi @webApi()
def areDue(self, cards): def areDue(self, cards):
return self.anki.areDue(cards) return self.anki.areDue(cards)
@webApi @webApi()
def getIntervals(self, cards, complete=False): def getIntervals(self, cards, complete=False):
return self.anki.getIntervals(cards, complete) return self.anki.getIntervals(cards, complete)
@webApi @webApi()
def upgrade(self): def upgrade(self):
response = QMessageBox.question( response = QMessageBox.question(
self.anki.window(), self.anki.window(),
@ -1100,91 +1091,92 @@ class AnkiConnect:
return False return False
@webApi @webApi()
def version(self): def version(self):
return API_VERSION return API_VERSION
@webApi @webApi()
def findNotes(self, query=None): def findNotes(self, query=None):
return self.anki.findNotes(query) return self.anki.findNotes(query)
@webApi @webApi()
def findCards(self, query=None): def findCards(self, query=None):
return self.anki.findCards(query) return self.anki.findCards(query)
@webApi @webApi()
def getDecks(self, cards): def getDecks(self, cards):
return self.anki.getDecks(cards) return self.anki.getDecks(cards)
@webApi @webApi()
def changeDeck(self, cards, deck): def changeDeck(self, cards, deck):
return self.anki.changeDeck(cards, deck) return self.anki.changeDeck(cards, deck)
@webApi @webApi()
def deleteDecks(self, decks, cardsToo=False): def deleteDecks(self, decks, cardsToo=False):
return self.anki.deleteDecks(decks, cardsToo) return self.anki.deleteDecks(decks, cardsToo)
@webApi @webApi()
def cardsToNotes(self, cards): def cardsToNotes(self, cards):
return self.anki.cardsToNotes(cards) return self.anki.cardsToNotes(cards)
@webApi @webApi()
def guiBrowse(self, query=None): def guiBrowse(self, query=None):
return self.anki.guiBrowse(query) return self.anki.guiBrowse(query)
@webApi @webApi()
def guiAddCards(self): def guiAddCards(self):
return self.anki.guiAddCards() return self.anki.guiAddCards()
@webApi @webApi()
def guiCurrentCard(self): def guiCurrentCard(self):
return self.anki.guiCurrentCard() return self.anki.guiCurrentCard()
@webApi @webApi()
def guiStartCardTimer(self): def guiStartCardTimer(self):
return self.anki.guiStartCardTimer() return self.anki.guiStartCardTimer()
@webApi @webApi()
def guiAnswerCard(self, ease): def guiAnswerCard(self, ease):
return self.anki.guiAnswerCard(ease) return self.anki.guiAnswerCard(ease)
@webApi @webApi()
def guiShowQuestion(self): def guiShowQuestion(self):
return self.anki.guiShowQuestion() return self.anki.guiShowQuestion()
@webApi @webApi()
def guiShowAnswer(self): def guiShowAnswer(self):
return self.anki.guiShowAnswer() return self.anki.guiShowAnswer()
@webApi @webApi()
def guiDeckOverview(self, name): def guiDeckOverview(self, name):
return self.anki.guiDeckOverview(name) return self.anki.guiDeckOverview(name)
@webApi @webApi()
def guiDeckBrowser(self): def guiDeckBrowser(self):
return self.anki.guiDeckBrowser() return self.anki.guiDeckBrowser()
@webApi @webApi()
def guiDeckReview(self, name): def guiDeckReview(self, name):
return self.anki.guiDeckReview(name) return self.anki.guiDeckReview(name)
@webApi
@webApi()
def guiExitAnki(self): def guiExitAnki(self):
return self.anki.guiExitAnki() return self.anki.guiExitAnki()