From ebdca1db6bc0b7061732e7b4c3283871c45862e4 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Tue, 16 Aug 2022 19:23:09 -0600 Subject: [PATCH 1/5] Added model field name api points and skeleton documentation to README --- README.md | 115 +++++++++++++++++++++++++++++++++++++++++++ plugin/__init__.py | 100 +++++++++++++++++++++++++++++++++++++ tests/test_models.py | 96 ++++++++++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+) diff --git a/README.md b/README.md index dbe169f..aee8d60 100644 --- a/README.md +++ b/README.md @@ -2099,6 +2099,121 @@ corresponding to when the API was available for use. } ``` +* **modelFieldRename** + + TODO + + *Sample Request*: + ```json + { + "action": "modelFieldRename", + "version": 6, + "params": { + } + } + } + ``` + + *Sample result*: + ```json + { + "result": null, + "error": null + } + ``` + +* **modelFieldReposition** + + TODO + + *Sample Request*: + ```json + { + "action": "modelFieldReposition", + "version": 6, + "params": { + } + } + } + ``` + + *Sample result*: + ```json + { + "result": null, + "error": null + } + ``` + +* **modelFieldAdd** + + TODO + + *Sample Request*: + ```json + { + "action": "modelFieldAdd", + "version": 6, + "params": { + } + } + } + ``` + + *Sample result*: + ```json + { + "result": null, + "error": null + } + ``` + +* **modelFieldRemove** + + TODO + + *Sample Request*: + ```json + { + "action": "modelFieldRemove", + "version": 6, + "params": { + } + } + } + ``` + + *Sample result*: + ```json + { + "result": null, + "error": null + } + ``` + +* **editFieldNames** + + TODO + + *Sample Request*: + ```json + { + "action": "editFieldNames", + "version": 6, + "params": { + } + } + } + ``` + + *Sample result*: + ```json + { + "result": null, + "error": null + } + ``` + #### Note Actions * **addNote** diff --git a/plugin/__init__.py b/plugin/__init__.py index 93c92d0..6799486 100644 --- a/plugin/__init__.py +++ b/plugin/__init__.py @@ -1185,6 +1185,106 @@ class AnkiConnect: return updatedModels + @util.api() + def modelFieldRename(self, modelName, oldFieldName, newFieldName): + #self.startEditing() + + mm = self.collection().models + model = mm.byName(modelName) + if model is None: + raise Exception('model was not found: {}'.format(modelName)) + + fieldMap = mm.fieldMap(model) + if oldFieldName not in fieldMap: + raise Exception('field was not found in {}: {}'.format(modelName, oldFieldName)) + field = fieldMap[oldFieldName][1] + + mm.renameField(model, field, newFieldName) + + self.save_model(mm, model) + #self.stopEditing() + + + @util.api() + def modelFieldReposition(self, modelName, fieldName, index): + mm = self.collection().models + model = mm.byName(modelName) + if model is None: + raise Exception('model was not found: {}'.format(modelName)) + + fieldMap = mm.fieldMap(model) + if fieldName not in fieldMap: + raise Exception('field was not found in {}: {}'.format(modelName, fieldName)) + field = fieldMap[fieldName][1] + + mm.repositionField(model, field, index) + + self.save_model(mm, model) + + + @util.api() + def modelFieldAdd(self, modelName, fieldName, index=None): + #self.startEditing() + + mm = self.collection().models + model = mm.byName(modelName) + if model is None: + raise Exception('model was not found: {}'.format(modelName)) + + # only adds the field if it doesn't already exist + fieldMap = mm.fieldMap(model) + if fieldName not in fieldMap: + field = mm.newField(fieldName) + mm.addField(model, field) + + # repositions, even if the field already exists + if index is not None: + fieldMap = mm.fieldMap(model) + newField = fieldMap[fieldName][1] + mm.repositionField(model, newField, index) + + self.save_model(mm, model) + #self.stopEditing() + + + @util.api() + def modelFieldRemove(self, modelName, fieldName): + #self.startEditing() + + mm = self.collection().models + model = mm.byName(modelName) + if model is None: + raise Exception('model was not found: {}'.format(modelName)) + + fieldMap = mm.fieldMap(model) + if fieldName not in fieldMap: + raise Exception('field was not found in {}: {}'.format(modelName, fieldName)) + field = fieldMap[fieldName][1] + + mm.removeField(model, field) + + self.save_model(mm, model) + #self.stopEditing() + + + @util.api() + def editFieldNames(self, modelName, actions): + actionToFuncMap = { + 'rename': self.modelFieldRename, + 'reposition': self.modelFieldReposition, + 'add': self.modelFieldAdd, + 'remove': self.modelFieldRemove, + } + + for actionDict in actions: + action = actionDict['action'] + if action not in actionToFuncMap: + raise Exception('invalid edit field name action: {}'.format(action)) + func = actionToFuncMap[action] + args = {k: v for k, v in actionDict.items() if k != 'action'} + func(modelName=modelName, **args) + + @util.api() def deckNameFromId(self, deckId): deck = self.collection().decks.get(deckId) diff --git a/tests/test_models.py b/tests/test_models.py index f7e9131..df8e0fa 100755 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -110,3 +110,99 @@ def test_findAndReplaceInModels(setup): assert ac.modelStyling(modelName="test_model") == { "css": "* {color: blue;}" } + + +class TestModelFieldNames: + def test_modelFieldRename(self, setup): + ac.modelFieldRename( + modelName="test_model", + oldFieldName="field1", + newFieldName="foo", + ) + + result = ac.modelFieldNames(modelName="test_model") + assert result == ["foo", "field2"] + + def test_modelFieldReposition(self, setup): + ac.modelFieldReposition( + modelName="test_model", + fieldName="field1", + index=2, + ) + + result = ac.modelFieldNames(modelName="test_model") + assert result == ["field2", "field1"] + + def test_modelFieldAdd(self, setup): + ac.modelFieldAdd( + modelName="test_model", + fieldName="Foo", + ) + + result = ac.modelFieldNames(modelName="test_model") + assert result == ["field1", "field2", "Foo"] + + def test_modelFieldAddIndex(self, setup): + ac.modelFieldAdd( + modelName="test_model", + fieldName="Foo", + index=1, + ) + + result = ac.modelFieldNames(modelName="test_model") + assert result == ["field1", "Foo", "field2"] + + def test_modelFieldRemove(self, setup): + # makes sure that the front template always has a field, + # and makes sure that the front template of the cards are not the same + ac.updateModelTemplates(model={ + "name": "test_model", + "templates": {"Card 1": {"Front": "{{field2}} {{field2}}", "Back": "foo"}} + }) + + ac.modelFieldRemove( + modelName="test_model", + fieldName="field1", + ) + + result = ac.modelFieldNames(modelName="test_model") + assert result == ["field2"] + + def test_editFieldNames(self, setup): + editFieldNames_kwargs = { + "modelName": "test_model", + "actions": [ + { + "action": "add", + "fieldName": "field3", + }, + { + "action": "add", + "fieldName": "field4", + "index": 1, + }, + { + "action": "add", + "fieldName": "field5", + }, + { + "action": "reposition", + "fieldName": "field3", + "index": 0, + }, + { + "action": "rename", + "oldFieldName": "field3", + "newFieldName": "renamed_field3", + }, + { + "action": "remove", + "fieldName": "field5", + }, + ] + } + + ac.editFieldNames(**editFieldNames_kwargs) + + result = ac.modelFieldNames(modelName="test_model") + assert result == ["renamed_field3", "field1", "field4", "field2"] From cb52e144977e8dc0ac0559865df0396017b641e5 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Tue, 16 Aug 2022 19:30:36 -0600 Subject: [PATCH 2/5] Added sample requests to field name actions --- README.md | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index aee8d60..2cbe616 100644 --- a/README.md +++ b/README.md @@ -2109,7 +2109,9 @@ corresponding to when the API was available for use. "action": "modelFieldRename", "version": 6, "params": { - } + "modelName": "Basic", + "oldFieldName": "Front", + "newFieldName": "FrontRenamed" } } ``` @@ -2132,7 +2134,9 @@ corresponding to when the API was available for use. "action": "modelFieldReposition", "version": 6, "params": { - } + "modelName": "Basic", + "fieldName": "Front", + "index": 1 } } ``` @@ -2148,6 +2152,7 @@ corresponding to when the API was available for use. * **modelFieldAdd** TODO + (optional index, defaults to adding the field to the very end of the list) *Sample Request*: ```json @@ -2155,7 +2160,8 @@ corresponding to when the API was available for use. "action": "modelFieldAdd", "version": 6, "params": { - } + "modelName": "Basic", + "fieldName": "NewField" } } ``` @@ -2178,7 +2184,8 @@ corresponding to when the API was available for use. "action": "modelFieldRemove", "version": 6, "params": { - } + "modelName": "Basic", + "fieldName": "Front" } } ``` @@ -2194,6 +2201,7 @@ corresponding to when the API was available for use. * **editFieldNames** TODO + Bulk version of the above 4 actions. *Sample Request*: ```json @@ -2201,7 +2209,28 @@ corresponding to when the API was available for use. "action": "editFieldNames", "version": 6, "params": { - } + "modelName": "Basic", + "actions": [ + { + "action": "add", + "fieldName": "field3", + "index": 0 + }, + { + "action": "reposition", + "fieldName": "field3", + "index": 2 + }, + { + "action": "rename", + "oldFieldName": "field3", + "newFieldName": "renamed_field3" + }, + { + "action": "remove", + "fieldName": "field3" + } + ] } } ``` From 8ec078393a5643c88508614363596de00f6cbcb7 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Tue, 16 Aug 2022 19:35:32 -0600 Subject: [PATCH 3/5] removed the bulk action in favor of the already existing 'multi' action --- README.md | 45 -------------------------------------------- plugin/__init__.py | 27 -------------------------- tests/test_models.py | 39 -------------------------------------- 3 files changed, 111 deletions(-) diff --git a/README.md b/README.md index 2cbe616..9acfb62 100644 --- a/README.md +++ b/README.md @@ -2198,51 +2198,6 @@ corresponding to when the API was available for use. } ``` -* **editFieldNames** - - TODO - Bulk version of the above 4 actions. - - *Sample Request*: - ```json - { - "action": "editFieldNames", - "version": 6, - "params": { - "modelName": "Basic", - "actions": [ - { - "action": "add", - "fieldName": "field3", - "index": 0 - }, - { - "action": "reposition", - "fieldName": "field3", - "index": 2 - }, - { - "action": "rename", - "oldFieldName": "field3", - "newFieldName": "renamed_field3" - }, - { - "action": "remove", - "fieldName": "field3" - } - ] - } - } - ``` - - *Sample result*: - ```json - { - "result": null, - "error": null - } - ``` - #### Note Actions * **addNote** diff --git a/plugin/__init__.py b/plugin/__init__.py index 6799486..4ff486b 100644 --- a/plugin/__init__.py +++ b/plugin/__init__.py @@ -1187,8 +1187,6 @@ class AnkiConnect: @util.api() def modelFieldRename(self, modelName, oldFieldName, newFieldName): - #self.startEditing() - mm = self.collection().models model = mm.byName(modelName) if model is None: @@ -1202,7 +1200,6 @@ class AnkiConnect: mm.renameField(model, field, newFieldName) self.save_model(mm, model) - #self.stopEditing() @util.api() @@ -1224,8 +1221,6 @@ class AnkiConnect: @util.api() def modelFieldAdd(self, modelName, fieldName, index=None): - #self.startEditing() - mm = self.collection().models model = mm.byName(modelName) if model is None: @@ -1244,13 +1239,10 @@ class AnkiConnect: mm.repositionField(model, newField, index) self.save_model(mm, model) - #self.stopEditing() @util.api() def modelFieldRemove(self, modelName, fieldName): - #self.startEditing() - mm = self.collection().models model = mm.byName(modelName) if model is None: @@ -1264,25 +1256,6 @@ class AnkiConnect: mm.removeField(model, field) self.save_model(mm, model) - #self.stopEditing() - - - @util.api() - def editFieldNames(self, modelName, actions): - actionToFuncMap = { - 'rename': self.modelFieldRename, - 'reposition': self.modelFieldReposition, - 'add': self.modelFieldAdd, - 'remove': self.modelFieldRemove, - } - - for actionDict in actions: - action = actionDict['action'] - if action not in actionToFuncMap: - raise Exception('invalid edit field name action: {}'.format(action)) - func = actionToFuncMap[action] - args = {k: v for k, v in actionDict.items() if k != 'action'} - func(modelName=modelName, **args) @util.api() diff --git a/tests/test_models.py b/tests/test_models.py index df8e0fa..72b6da8 100755 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -167,42 +167,3 @@ class TestModelFieldNames: result = ac.modelFieldNames(modelName="test_model") assert result == ["field2"] - - def test_editFieldNames(self, setup): - editFieldNames_kwargs = { - "modelName": "test_model", - "actions": [ - { - "action": "add", - "fieldName": "field3", - }, - { - "action": "add", - "fieldName": "field4", - "index": 1, - }, - { - "action": "add", - "fieldName": "field5", - }, - { - "action": "reposition", - "fieldName": "field3", - "index": 0, - }, - { - "action": "rename", - "oldFieldName": "field3", - "newFieldName": "renamed_field3", - }, - { - "action": "remove", - "fieldName": "field5", - }, - ] - } - - ac.editFieldNames(**editFieldNames_kwargs) - - result = ac.modelFieldNames(modelName="test_model") - assert result == ["renamed_field3", "field1", "field4", "field2"] From 83cc55769bd905c3c74e22b70a1c746ee8a93608 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Tue, 16 Aug 2022 20:11:44 -0600 Subject: [PATCH 4/5] fixed function styling issue in test case --- tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 72b6da8..7c5dbb7 100755 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -142,7 +142,7 @@ class TestModelFieldNames: result = ac.modelFieldNames(modelName="test_model") assert result == ["field1", "field2", "Foo"] - def test_modelFieldAddIndex(self, setup): + def test_modelFieldAdd_with_index(self, setup): ac.modelFieldAdd( modelName="test_model", fieldName="Foo", From db2e7f2e95809309df9f03c81618073666b02d55 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Wed, 17 Aug 2022 12:50:22 -0600 Subject: [PATCH 5/5] added documentation --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9acfb62..2cd6651 100644 --- a/README.md +++ b/README.md @@ -2101,7 +2101,7 @@ corresponding to when the API was available for use. * **modelFieldRename** - TODO + Rename the field name of a given model. *Sample Request*: ```json @@ -2126,7 +2126,9 @@ corresponding to when the API was available for use. * **modelFieldReposition** - TODO + Reposition the field within the field list of a given model. + + The value of `index` starts at 0. For example, an index of `0` puts the field in the first position, and an index of `2` puts the field in the third position. *Sample Request*: ```json @@ -2135,8 +2137,8 @@ corresponding to when the API was available for use. "version": 6, "params": { "modelName": "Basic", - "fieldName": "Front", - "index": 1 + "fieldName": "Back", + "index": 0 } } ``` @@ -2151,8 +2153,9 @@ corresponding to when the API was available for use. * **modelFieldAdd** - TODO - (optional index, defaults to adding the field to the very end of the list) + Creates a new field within a given model. + + Optionally, the `index` value can be provided, which works exactly the same as the index in `modelFieldReposition`. By default, the field is added to the end of the field list. *Sample Request*: ```json @@ -2161,7 +2164,8 @@ corresponding to when the API was available for use. "version": 6, "params": { "modelName": "Basic", - "fieldName": "NewField" + "fieldName": "NewField", + "index": 0 } } ``` @@ -2176,7 +2180,7 @@ corresponding to when the API was available for use. * **modelFieldRemove** - TODO + Deletes a field within a given model. *Sample Request*: ```json