Last active
November 28, 2019 09:19
-
-
Save sloria/2fac357710f13e855a5b9cf8f05a4da0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Unknown field handling" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## DRF\n", | |
"\n", | |
"Default: ignore\n", | |
"\n", | |
"Not configurable" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from django.conf import settings\n", | |
"\n", | |
"import django\n", | |
"try:\n", | |
" settings.configure(\n", | |
" INSTALLED_APPS=['rest_framework'],\n", | |
" USE_I18N=True,\n", | |
" USE_L10N=True,\n", | |
" )\n", | |
" django.setup()\n", | |
"except:\n", | |
" pass\n", | |
"\n", | |
"from rest_framework import serializers as drfs\n", | |
"\n", | |
"\n", | |
"class AlbumSerializer(drfs.Serializer):\n", | |
" title = drfs.CharField()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"result = AlbumSerializer(data={'title': 'valid', 'unknown': 1})" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"result.is_valid()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"ReturnDict([('title', 'valid')])" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"result.data" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Colander\n", | |
"\n", | |
"Default: ignore\n", | |
"\n", | |
"Configured by `unknown` param, which may be: `raise`, `ignore`, or `preserve`.\n", | |
"\n", | |
"When using `raise`, reports all unknown keys." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "UnsupportedFields", | |
"evalue": "{'': 'Unrecognized keys in mapping: \"{\\'unknown\\': 1, \\'unknown2\\': 2}\"'}", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mUnsupportedFields\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-19-8d1993fb8078>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mAlbum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdeserialize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'title'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'valid'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown2'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/colander/__init__.py\u001b[0m in \u001b[0;36mdeserialize\u001b[0;34m(self, cstruct)\u001b[0m\n\u001b[1;32m 2071\u001b[0m \u001b[0mdefaults\u001b[0m \u001b[0mto\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0mattr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mcolander\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnull\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2072\u001b[0m \"\"\"\n\u001b[0;32m-> 2073\u001b[0;31m \u001b[0mappstruct\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtyp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdeserialize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcstruct\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2074\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2075\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpreparer\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/colander/__init__.py\u001b[0m in \u001b[0;36mdeserialize\u001b[0;34m(self, node, cstruct)\u001b[0m\n\u001b[1;32m 722\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msubnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdeserialize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubcstruct\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 723\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 724\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_impl\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcstruct\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcallback\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 725\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 726\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mflatten\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mappstruct\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprefix\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlistitem\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/colander/__init__.py\u001b[0m in \u001b[0;36m_impl\u001b[0;34m(self, node, value, callback)\u001b[0m\n\u001b[1;32m 696\u001b[0m \u001b[0mnode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 697\u001b[0m msg=_('Unrecognized keys in mapping: \"${val}\"',\n\u001b[0;32m--> 698\u001b[0;31m mapping={'val': value}))\n\u001b[0m\u001b[1;32m 699\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 700\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munknown\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'preserve'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mUnsupportedFields\u001b[0m: {'': 'Unrecognized keys in mapping: \"{\\'unknown\\': 1, \\'unknown2\\': 2}\"'}" | |
] | |
} | |
], | |
"source": [ | |
"import colander as col\n", | |
"\n", | |
"class Album(col.MappingSchema):\n", | |
" title = col.SchemaNode(col.String())\n", | |
" \n", | |
" # https://github.com/Pylons/colander/issues/116\n", | |
" def schema_type(self, **kw):\n", | |
" return col.Mapping(unknown='raise')\n", | |
" \n", | |
" \n", | |
"Album().deserialize({'title': 'valid', 'unknown': 1, 'unknown2': 2})" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Voluptuous\n", | |
"\n", | |
"Default: raise (reports first unknown key)\n", | |
"\n", | |
"Configurable with `extra` parameter, which may be: `ALLOW_EXTRA` and `REMOVE_EXTRA`\n", | |
"\n", | |
"https://github.com/alecthomas/voluptuous#extra-dictionary-keys" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import voluptuous as vol\n", | |
"\n", | |
"schema = vol.Schema({'title': str})" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "MultipleInvalid", | |
"evalue": "extra keys not allowed @ data['unknown']", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mMultipleInvalid\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-21-4e5142820c14>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mschema\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'title'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'valid'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/voluptuous/schema_builder.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 265\u001b[0m \u001b[0;34m\"\"\"Validate data against this schema.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 266\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 267\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compiled\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 268\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMultipleInvalid\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 269\u001b[0m \u001b[0;32mraise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/voluptuous/schema_builder.py\u001b[0m in \u001b[0;36mvalidate_dict\u001b[0;34m(path, data)\u001b[0m\n\u001b[1;32m 585\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 586\u001b[0m \u001b[0mout\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 587\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mbase_validate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miteritems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 588\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 589\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalidate_dict\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/voluptuous/schema_builder.py\u001b[0m in \u001b[0;36mvalidate_mapping\u001b[0;34m(path, iterable, out)\u001b[0m\n\u001b[1;32m 423\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mRequiredFieldInvalid\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpath\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 424\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 425\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMultipleInvalid\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merrors\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 426\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 427\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mMultipleInvalid\u001b[0m: extra keys not allowed @ data['unknown']" | |
] | |
} | |
], | |
"source": [ | |
"schema({'title': 'valid', 'unknown': 1})" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"It only seems to report on the first unknown field." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "MultipleInvalid", | |
"evalue": "extra keys not allowed @ data['unknown']", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mMultipleInvalid\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-10-64f87578de51>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mschema\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'title'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'valid'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown2'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# unknown2 is not in error message\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/voluptuous/schema_builder.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 265\u001b[0m \u001b[0;34m\"\"\"Validate data against this schema.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 266\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 267\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compiled\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 268\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMultipleInvalid\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 269\u001b[0m \u001b[0;32mraise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/voluptuous/schema_builder.py\u001b[0m in \u001b[0;36mvalidate_dict\u001b[0;34m(path, data)\u001b[0m\n\u001b[1;32m 585\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 586\u001b[0m \u001b[0mout\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 587\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mbase_validate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miteritems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 588\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 589\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvalidate_dict\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/voluptuous/schema_builder.py\u001b[0m in \u001b[0;36mvalidate_mapping\u001b[0;34m(path, iterable, out)\u001b[0m\n\u001b[1;32m 423\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mRequiredFieldInvalid\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpath\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 424\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 425\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMultipleInvalid\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merrors\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 426\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 427\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mMultipleInvalid\u001b[0m: extra keys not allowed @ data['unknown']" | |
] | |
} | |
], | |
"source": [ | |
"schema({'title': 'valid', 'unknown': 1, 'unknown2': 2}) # unknown2 is not in error message" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'title': 'valid', 'unknown': 1}" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"allow_schema = vol.Schema({'title': str}, extra=vol.ALLOW_EXTRA)\n", | |
"\n", | |
"allow_schema({'title': 'valid', 'unknown': 1})" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## schema\n", | |
"\n", | |
"Default: raise (reports all unknown keys)\n", | |
"\n", | |
"Configured by a `ignore_extra_keys` (boolean). Possible to preserve extra keys by using `object: object` as one of the items." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "SchemaWrongKeyError", | |
"evalue": "Wrong keys 'unknown', 'unknown2' in {'title': 'valid', 'unknown': 1, 'unknown2': 2}", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mSchemaWrongKeyError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-12-81b4bd225264>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0malbum\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mschema\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSchema\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'title'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0malbum\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'title'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'valid'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown2'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/schema.py\u001b[0m in \u001b[0;36mvalidate\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 296\u001b[0m SchemaWrongKeyError(\n\u001b[1;32m 297\u001b[0m \u001b[0;34m'Wrong keys %s in %r'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0ms_wrong_keys\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 298\u001b[0;31m e.format(data) if e else None)\n\u001b[0m\u001b[1;32m 299\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 300\u001b[0m \u001b[0;31m# Apply default-having optionals that haven't been used:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mSchemaWrongKeyError\u001b[0m: Wrong keys 'unknown', 'unknown2' in {'title': 'valid', 'unknown': 1, 'unknown2': 2}" | |
] | |
} | |
], | |
"source": [ | |
"import schema\n", | |
"\n", | |
"album = schema.Schema({'title': str})\n", | |
"album.validate({'title': 'valid', 'unknown': 1, 'unknown2': 2})" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'title': 'valid'}" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ignore_schema = schema.Schema({'title': str}, ignore_extra_keys=True)\n", | |
"ignore_schema.validate({'title': 'valid', 'unknown': 1})" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'title': 'valid', 'unknown': 1}" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"allow_schema = schema.Schema({'title': str, object: object})\n", | |
"allow_schema.validate({'title': 'valid', 'unknown': 1})" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Cerberus\n", | |
"\n", | |
"Default: raise (reports all unknown keys)\n", | |
"\n", | |
"Configurable with a `allow_unknown` parameter.\n", | |
"\n", | |
"http://docs.python-cerberus.org/en/stable/usage.html#allowing-the-unknown" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 15, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import cerberus as cer\n", | |
"\n", | |
"v = cer.Validator()\n", | |
"schema = {\n", | |
" 'title': {'type': 'string'},\n", | |
"}\n", | |
"v.validate({'title': 'valid', 'unknown': 1, 'unknown2': 2}, schema)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'unknown': ['unknown field'], 'unknown2': ['unknown field']}" | |
] | |
}, | |
"execution_count": 16, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"v.errors" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 19, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"allow_validator = cer.Validator(allow_unknown=True)\n", | |
"allow_validator.validate({'title': 'valid', 'unknown': 1}, schema)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Schematics\n", | |
"\n", | |
"default: raise (reports all unknown fields)\n", | |
"\n", | |
"Not configurable" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import schematics as sch\n", | |
"\n", | |
"class Album(sch.Model):\n", | |
" title = sch.types.StringType()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "DataError", | |
"evalue": "{\"unknown2\": \"Rogue field\", \"unknown\": \"Rogue field\"}", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mDataError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-23-2e6b79c8315c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mAlbum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'title'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'valid'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'unknown2'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/schematics/models.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, raw_data, trusted_data, deserialize_mapping, init, partial, strict, validate, app_data, lazy, **kwargs)\u001b[0m\n\u001b[1;32m 229\u001b[0m \u001b[0mtrusted_data\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtrusted_data\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmapping\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdeserialize_mapping\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 230\u001b[0m \u001b[0mpartial\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mpartial\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstrict\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstrict\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalidate\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidate\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 231\u001b[0;31m app_data=app_data, **kwargs)\n\u001b[0m\u001b[1;32m 232\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_data\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconverted\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 233\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalidate\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/schematics/models.py\u001b[0m in \u001b[0;36m_convert\u001b[0;34m(self, raw_data, context, **kwargs)\u001b[0m\n\u001b[1;32m 293\u001b[0m \u001b[0mshould_validate\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcontext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'validate'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'validate'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 294\u001b[0m \u001b[0mfunc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalidate\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mshould_validate\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0mconvert\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 295\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_schema\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraw_data\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mraw_data\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moo\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcontext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 296\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 297\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mexport\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfield_converter\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrole\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mapp_data\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/schematics/transforms.py\u001b[0m in \u001b[0;36mconvert\u001b[0;34m(cls, mutable, raw_data, **kwargs)\u001b[0m\n\u001b[1;32m 427\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 428\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mconvert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmutable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraw_data\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 429\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mimport_loop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmutable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraw_data\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mimport_converter\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 430\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 431\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/.local/share/virtualenvs/marshmallow/lib/python3.6/site-packages/schematics/transforms.py\u001b[0m in \u001b[0;36mimport_loop\u001b[0;34m(schema, mutable, raw_data, field_converter, trusted_data, mapping, partial, strict, init_values, apply_defaults, convert, validate, new, oo, recursive, app_data, context)\u001b[0m\n\u001b[1;32m 174\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 175\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 176\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mDataError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merrors\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 177\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 178\u001b[0m \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfield_converter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpost\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mschema\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mDataError\u001b[0m: {\"unknown2\": \"Rogue field\", \"unknown\": \"Rogue field\"}" | |
] | |
} | |
], | |
"source": [ | |
"Album({'title': 'valid', 'unknown': 1, 'unknown2': 2}).validate()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.6.4" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment