pyArango icon indicating copy to clipboard operation
pyArango copied to clipboard

Document creation - nested fields - Validation error

Open Jacobgoss30 opened this issue 6 years ago • 3 comments

Hello!

When we try to insert a document into an ArangoDB collection and that document has nested fields (fields populated with a dictionary) we get this error:

TypeError: argument of type 'Field' is not iterable

which is thrown by

if (not self.collection._validation['allow_foreign_fields']) and (field not in self.validators) and (field not in self.collection.arangoPrivates):

and that seems to happen because self.validators in DocumentStore.set is equal to

<Field, validators: ''>

Are we doing the insertion the wrong way or is there a bug in the library?

P.S. We have

_validation = { 'on_save': True, 'on_set': True, 'on_load': False, 'allow_foreign_fields': False }

for this collection.

Jacobgoss30 avatar Dec 18 '17 11:12 Jacobgoss30

Could you post the class definition please?

tariqdaouda avatar Jan 06 '18 05:01 tariqdaouda

Hi,

I Add a similar issue, after looking closely to the class definition I've inadvertently put a ',' after the last field declaration of the _fields dictionary.

Removing it, updating to the latest version and recreating all collections solved the issue for me.

Hope this helps.

logan169 avatar Apr 13 '18 16:04 logan169

I ran into this error as well. The problem for me was that pyArango implicitly expects nested fields to be validated as well. In the DocumentStore you find the following lines in the set() and __setitem__ methods:

if isinstance(value, dict) :
    if field in self.validators:
        vals = self.validators[field]
    else :
        vals = {}
    self.store[field] = DocumentStore(self.collection, validators = vals, initDct = value, patch =         
    self.patching, subStore=True, validateInit=self.validateInit)      

These lines check if the current value of the field is a dictionary and if that is the case, the validators of this fields are redirected into the sup DataStore. This is problematic if your field definition looks like this:

_fields = {
    "nested_something": Field()
}

If you now set nested_something to a some nested data, the value of the Field nested_somethingis a dict and the validators vals (from the code snippet above) has the value of a Field object. Unfortunately, the DataStoreexpects to get a dictionary mapping field name to Fieldobject, which results in the error message.

TypeError: argument of type 'Field' is not iterable

This code makes perfect sense if your field definition looks like this:

_fields = {
    "nested_string": {
        "some_string": Field([VAL.String()])
    }
}

In this case, the value of the validatorsvals, which get into the DataStore is a dictionary mapping field name to Fieldobject and the nested fields are getting validated as expected. But in our definition 1, we don't want to validate the subfields.

So the fix is to check if the field definition is actually a dict to and only then redirect the validators to the sub DataStore.

if field in self.validators and isinstance(self.validators[field], dict):

This way the validation runs as expected and if you allow allow_foreign_fields for your Collection you can use arbitrary nested data.

I fixed this and submitted a pull request: #117

thekie avatar Sep 21 '18 13:09 thekie