Fix handling of errors in several methods (#238)
* Fix error message in updateNoteFields method * Fix error handling in cardsInfo, notesInfo methods * Add more tests for updateNoteFields, notesInfo * Fix error handling in several methods Also fixed obvious bugs in replaceTags and replaceTagsInAllNotes methods. * Add more tests for cards methods * Add more tests for notes methods * Update documentation on cards methods
This commit is contained in:
parent
a4d723de3e
commit
b8a7151ed0
@ -94,18 +94,18 @@
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
* **suspended**
|
||||
|
||||
* **areSuspended**
|
||||
|
||||
Returns an array indicating whether each of the given cards is suspended (in the same order).
|
||||
|
||||
Check if card is suspended by its ID. Returns `true` if suspended, `false` otherwise.
|
||||
|
||||
*Sample request*:
|
||||
```json
|
||||
{
|
||||
"action": "areSuspended",
|
||||
"action": "suspended",
|
||||
"version": 6,
|
||||
"params": {
|
||||
"cards": [1483959291685, 1483959293217]
|
||||
"card": 1483959293217
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -113,7 +113,31 @@
|
||||
*Sample result*:
|
||||
```json
|
||||
{
|
||||
"result": [false, true],
|
||||
"result": true,
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
* **areSuspended**
|
||||
|
||||
Returns an array indicating whether each of the given cards is suspended (in the same order). If card doesn't
|
||||
exist returns `null`.
|
||||
|
||||
*Sample request*:
|
||||
```json
|
||||
{
|
||||
"action": "areSuspended",
|
||||
"version": 6,
|
||||
"params": {
|
||||
"cards": [1483959291685, 1483959293217, 1234567891234]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Sample result*:
|
||||
```json
|
||||
{
|
||||
"result": [false, true, null],
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
@ -32,9 +32,12 @@ import anki
|
||||
import anki.exporting
|
||||
import anki.storage
|
||||
import aqt
|
||||
from anki.cards import Card
|
||||
|
||||
from anki.exporting import AnkiPackageExporter
|
||||
from anki.importing import AnkiPackageImporter
|
||||
from anki.notes import Note
|
||||
from anki.rsbackend import NotFoundError
|
||||
from anki.utils import joinFields, intTime, guid64, fieldChecksum
|
||||
|
||||
from . import web, util
|
||||
@ -280,6 +283,17 @@ class AnkiConnect:
|
||||
|
||||
return 0
|
||||
|
||||
def getCard(self, card_id: int) -> Card:
|
||||
try:
|
||||
return self.collection().getCard(card_id)
|
||||
except NotFoundError:
|
||||
raise NotFoundError('Card was not found: {}'.format(card_id))
|
||||
|
||||
def getNote(self, note_id: int) -> Note:
|
||||
try:
|
||||
return self.collection().getNote(note_id)
|
||||
except NotFoundError:
|
||||
raise NotFoundError('Note was not found: {}'.format(note_id))
|
||||
|
||||
#
|
||||
# Miscellaneous
|
||||
@ -599,9 +613,7 @@ class AnkiConnect:
|
||||
|
||||
@util.api()
|
||||
def updateNoteFields(self, note):
|
||||
ankiNote = self.collection().getNote(note['id'])
|
||||
if ankiNote is None:
|
||||
raise Exception('note was not found: {}'.format(note['id']))
|
||||
ankiNote = self.getNote(note['id'])
|
||||
|
||||
for name, value in note['fields'].items():
|
||||
if name in ankiNote:
|
||||
@ -646,10 +658,14 @@ class AnkiConnect:
|
||||
self.window().progress.start()
|
||||
|
||||
for nid in notes:
|
||||
note = self.collection().getNote(nid)
|
||||
try:
|
||||
note = self.getNote(nid)
|
||||
except NotFoundError:
|
||||
continue
|
||||
|
||||
if note.hasTag(tag_to_replace):
|
||||
note.delTag(tag_to_replace)
|
||||
note.addtag(replace_with_tag)
|
||||
note.addTag(replace_with_tag)
|
||||
note.flush()
|
||||
|
||||
self.window().requireReset()
|
||||
@ -661,11 +677,12 @@ class AnkiConnect:
|
||||
def replaceTagsInAllNotes(self, tag_to_replace, replace_with_tag):
|
||||
self.window().progress.start()
|
||||
|
||||
collection = self.collection()
|
||||
for nid in collection.db.list('select id from notes'):
|
||||
note = collection.getNote(nid)
|
||||
note = self.getNote(nid)
|
||||
if note.hasTag(tag_to_replace):
|
||||
note.delTag(tag_to_replace)
|
||||
note.addtag(replace_with_tag)
|
||||
note.addTag(replace_with_tag)
|
||||
note.flush()
|
||||
|
||||
self.window().requireReset()
|
||||
@ -677,12 +694,13 @@ class AnkiConnect:
|
||||
def setEaseFactors(self, cards, easeFactors):
|
||||
couldSetEaseFactors = []
|
||||
for i, card in enumerate(cards):
|
||||
ankiCard = self.collection().getCard(card)
|
||||
if ankiCard is None:
|
||||
try:
|
||||
ankiCard = self.getCard(card)
|
||||
except NotFoundError:
|
||||
couldSetEaseFactors.append(False)
|
||||
else:
|
||||
couldSetEaseFactors.append(True)
|
||||
continue
|
||||
|
||||
couldSetEaseFactors.append(True)
|
||||
ankiCard.factor = easeFactors[i]
|
||||
ankiCard.flush()
|
||||
|
||||
@ -693,7 +711,12 @@ class AnkiConnect:
|
||||
def getEaseFactors(self, cards):
|
||||
easeFactors = []
|
||||
for card in cards:
|
||||
ankiCard = self.collection().getCard(card)
|
||||
try:
|
||||
ankiCard = self.getCard(card)
|
||||
except NotFoundError:
|
||||
easeFactors.append(None)
|
||||
continue
|
||||
|
||||
easeFactors.append(ankiCard.factor)
|
||||
|
||||
return easeFactors
|
||||
@ -726,7 +749,7 @@ class AnkiConnect:
|
||||
|
||||
@util.api()
|
||||
def suspended(self, card):
|
||||
card = self.collection().getCard(card)
|
||||
card = self.getCard(card)
|
||||
return card.queue == -1
|
||||
|
||||
|
||||
@ -734,7 +757,10 @@ class AnkiConnect:
|
||||
def areSuspended(self, cards):
|
||||
suspended = []
|
||||
for card in cards:
|
||||
suspended.append(self.suspended(card))
|
||||
try:
|
||||
suspended.append(self.suspended(card))
|
||||
except NotFoundError:
|
||||
suspended.append(None)
|
||||
|
||||
return suspended
|
||||
|
||||
@ -994,7 +1020,7 @@ class AnkiConnect:
|
||||
result = []
|
||||
for cid in cards:
|
||||
try:
|
||||
card = self.collection().getCard(cid)
|
||||
card = self.getCard(cid)
|
||||
model = card.model()
|
||||
note = card.note()
|
||||
fields = {}
|
||||
@ -1025,8 +1051,8 @@ class AnkiConnect:
|
||||
'lapses': card.lapses,
|
||||
'left': card.left,
|
||||
})
|
||||
except TypeError as e:
|
||||
# Anki will give a TypeError if the card ID does not exist.
|
||||
except NotFoundError:
|
||||
# Anki will give a NotFoundError if the card ID does not exist.
|
||||
# Best behavior is probably to add an 'empty card' to the
|
||||
# returned result, so that the items of the input and return
|
||||
# lists correspond.
|
||||
@ -1127,7 +1153,7 @@ class AnkiConnect:
|
||||
result = []
|
||||
for nid in notes:
|
||||
try:
|
||||
note = self.collection().getNote(nid)
|
||||
note = self.getNote(nid)
|
||||
model = note.model()
|
||||
|
||||
fields = {}
|
||||
@ -1143,8 +1169,8 @@ class AnkiConnect:
|
||||
'modelName': model['name'],
|
||||
'cards': self.collection().db.list('select id from cards where nid = ? order by ord', note.id)
|
||||
})
|
||||
except TypeError as e:
|
||||
# Anki will give a TypeError if the note ID does not exist.
|
||||
except NotFoundError:
|
||||
# Anki will give a NotFoundError if the note ID does not exist.
|
||||
# Best behavior is probably to add an 'empty card' to the
|
||||
# returned result, so that the items of the input and return
|
||||
# lists correspond.
|
||||
|
@ -24,6 +24,8 @@ class TestCards(unittest.TestCase):
|
||||
|
||||
|
||||
def runTest(self):
|
||||
incorrectId = 1234
|
||||
|
||||
# findCards
|
||||
cardIds = util.invoke('findCards', query='deck:test')
|
||||
self.assertEqual(len(cardIds), 1)
|
||||
@ -33,18 +35,24 @@ class TestCards(unittest.TestCase):
|
||||
easeFactors = [EASE_TO_TRY for card in cardIds]
|
||||
couldGetEaseFactors = util.invoke('setEaseFactors', cards=cardIds, easeFactors=easeFactors)
|
||||
self.assertEqual([True for card in cardIds], couldGetEaseFactors)
|
||||
couldGetEaseFactors = util.invoke('setEaseFactors', cards=[incorrectId], easeFactors=[EASE_TO_TRY])
|
||||
self.assertEqual([False], couldGetEaseFactors)
|
||||
|
||||
# getEaseFactors
|
||||
easeFactorsFound = util.invoke('getEaseFactors', cards=cardIds)
|
||||
self.assertEqual(easeFactors, easeFactorsFound)
|
||||
easeFactorsFound = util.invoke('getEaseFactors', cards=[incorrectId])
|
||||
self.assertEqual([None], easeFactorsFound)
|
||||
|
||||
# suspend
|
||||
util.invoke('suspend', cards=cardIds)
|
||||
self.assertRaises(Exception, lambda: util.invoke('suspend', cards=[incorrectId]))
|
||||
|
||||
# areSuspended (part 1)
|
||||
suspendedStates = util.invoke('areSuspended', cards=cardIds)
|
||||
self.assertEqual(len(cardIds), len(suspendedStates))
|
||||
self.assertNotIn(False, suspendedStates)
|
||||
self.assertEqual([None], util.invoke('areSuspended', cards=[incorrectId]))
|
||||
|
||||
# unsuspend
|
||||
util.invoke('unsuspend', cards=cardIds)
|
||||
@ -73,6 +81,9 @@ class TestCards(unittest.TestCase):
|
||||
self.assertEqual(len(cardsInfo), len(cardIds))
|
||||
for i, cardInfo in enumerate(cardsInfo):
|
||||
self.assertEqual(cardInfo['cardId'], cardIds[i])
|
||||
cardsInfo = util.invoke('cardsInfo', cards=[incorrectId])
|
||||
self.assertEqual(len(cardsInfo), 1)
|
||||
self.assertDictEqual(cardsInfo[0], dict())
|
||||
|
||||
# forgetCards
|
||||
util.invoke('forgetCards', cards=cardIds)
|
||||
|
@ -91,15 +91,22 @@ class TestNotes(unittest.TestCase):
|
||||
util.invoke('removeTags', notes=[noteId], tags='tag2')
|
||||
|
||||
# updateNoteFields
|
||||
incorrectId = 1234
|
||||
noteUpdateIncorrectId = {'id': incorrectId, 'fields': {'Front': 'front2', 'Back': 'back2'}}
|
||||
self.assertRaises(Exception, lambda: util.invoke('updateNoteFields', note=noteUpdateIncorrectId))
|
||||
noteUpdate = {'id': noteId, 'fields': {'Front': 'front2', 'Back': 'back2'}}
|
||||
util.invoke('updateNoteFields', note=noteUpdate)
|
||||
|
||||
# replaceTags
|
||||
util.invoke('replaceTags', notes=[noteId, incorrectId], tag_to_replace='tag1', replace_with_tag='new_tag')
|
||||
|
||||
# notesInfo (part 2)
|
||||
noteInfos = util.invoke('notesInfo', notes=[noteId])
|
||||
self.assertEqual(len(noteInfos), 1)
|
||||
noteInfos = util.invoke('notesInfo', notes=[noteId, incorrectId])
|
||||
self.assertEqual(len(noteInfos), 2)
|
||||
self.assertDictEqual(noteInfos[1], dict()) # Test that returns empty dict if incorrect id was passed
|
||||
noteInfo = noteInfos[0]
|
||||
self.assertSetEqual(set(noteInfo['tags']), {'tag1'})
|
||||
self.assertIn('tag1', noteInfo['tags'])
|
||||
self.assertSetEqual(set(noteInfo['tags']), {'new_tag'})
|
||||
self.assertIn('new_tag', noteInfo['tags'])
|
||||
self.assertNotIn('tag2', noteInfo['tags'])
|
||||
self.assertEqual(noteInfo['fields']['Front']['value'], 'front2')
|
||||
self.assertEqual(noteInfo['fields']['Back']['value'], 'back2')
|
||||
@ -115,6 +122,15 @@ class TestNotes(unittest.TestCase):
|
||||
for noteId in noteIds:
|
||||
self.assertNotEqual(noteId, None)
|
||||
|
||||
# replaceTagsInAllNotes
|
||||
currentTag = notes1[0]['tags'][0]
|
||||
new_tag = 'new_tag'
|
||||
util.invoke('replaceTagsInAllNotes', tag_to_replace=currentTag, replace_with_tag=new_tag)
|
||||
noteInfos = util.invoke('notesInfo', notes=noteIds)
|
||||
for noteInfo in noteInfos:
|
||||
self.assertIn(new_tag, noteInfo['tags'])
|
||||
self.assertNotIn(currentTag, noteInfo['tags'])
|
||||
|
||||
# canAddNotes (part 2)
|
||||
noteStates = util.invoke('canAddNotes', notes=notes2)
|
||||
self.assertNotIn(True, noteStates)
|
||||
|
Loading…
Reference in New Issue
Block a user