{ "info": { "author": "Krzysztof Stachlewski", "author_email": "stach@stachlewski.info", "bugtrack_url": null, "classifiers": [], "description": "# Validate JSON data using a schema written in Python\n\n# Examples\n\n```\nfrom okschema import validate, ValidationError, SchemaError\n\ntry:\n validated_data = validate(schema, data)\nexcept ValidationError as e:\n print(e.js) # {'code': ValidationCode.}\n```\n\n## Validation of a simple form\n```\nfrom okschema import validate, fmt_uuid\n\ndef val_email(v):\n return v\n\nschema = {\n 'my_password': {'@t': 'string', '@lteq': 100},\n 'user_id': {'@t': 'string', '@regexp': fmt_uuid},\n 'new_email': {'@t': 'string', '@val': val_email},\n 'new_password': {'@t': 'string', '@lteq': 100},\n}\ndata = {\n 'my_password': 'abc',\n 'user_id': 'dbc8911c-92e8-4cdb-85b8-47a7a6a82db1',\n 'new_email': 'abc@example.com',\n 'new_password': 'abc'\n}\nvalidated_data = validate(schema, data)\n```\n\n## Potential use in request handling\n\n```\n@api_request(schema=lambda m: {\n 'email': {'@t': 'string', '@lteq': m.user.c.email.ui_len},\n 'password': {'@t': 'string', '@lteq': m.user.c.password.ui_len},\n 'key': {'@t': 'string', '@lteq': 10240},\n 'permission_level': {'@t': 'int', '@in': [PermissionE.ADMIN, PermissionE.USER]},\n})\nasync def add_user_account(request, m):\n ...\n```\n\n## Nested structure - error handling\n```\nschemaA = {\n 'outer': {\n 'a': 'int',\n 'b': {'@t': 'str', '@lt': 2, '@optional': True, '@null': True, '@blank': True},\n 'c': [{'@t': 'str', '@in': ['x', 'y', 'z']}]\n },\n 'is_ok': {'@type': 'bool', '@default': True}\n}\ndata1 = {\n}\ndata2 = {\n 'outer': {\n 'a': 'xxx',\n 'b': '3333',\n 'c': ['a', 'x', 12]\n },\n 'is_ok': True\n}\n```\n\n```\n>>> validate(schemaA, data1)\nValidationError: ({\n 'outer': {'code': ValidationCode.MISSING},\n 'is_ok': {'code': ValidationCode.MISSING}\n}, schemaA)\n```\n\n```\n>>> validate(schemaA, data2)\nValidationError: ({\n 'outer': {\n 'a': {'code': ValidationCode.BAD_TYPE},\n 'b': {'code': ValidationCode.NOT_LT, 'details': 2},\n 'c': [\n {'code': ValidationCode.NOT_IN},\n None, # no error here\n {'code': ValidationCode.BAD_TYPE}\n ]\n },\n 'is_ok': {'code': ValidationCode.BAD_TYPE}\n), schemaA)\n```\n\n## Custom validators - error handling\n\n```\ndef bad_val1_cont(x):\n raise NotValidButContinueError(ValidationCode.BAD_VALUE, 1)\n\ndef bad_val2_cont(x):\n raise NotValidButContinueError(ValidationCode.BAD_VALUE, 5)\n\ndef bad_val3(x):\n raise NotValidError(ValidationCode.BAD_VALUE)\n\nschemaA = {\n 'b': {'@t': 'int', '@val': [bad_val1_cont, bad_val2_cont]}\n}\nschemaB = {\n 'b': {'@t': 'int', '@val': [bad_val1_cont, bad_val2_cont, bad_val3]}\n}\ndata1 = {'b': 12}\n```\n\n```\n>>> validate(schemaA, data1)\nValidationError: ({\n 'b': {\n 'code': ValidationCode.MANY_ERRORS, 'details': [\n {'code': ValidationCode.BAD_VALUE, 'details': 1},\n {'code': ValidationCode.BAD_VALUE, 'details': 5}\n ]\n }\n}, schemaA)\n\n>>> validate(schemaB, data1)\nValidationError: ({\n 'b': {\n 'code': ValidationCode.MANY_ERRORS, 'details': [\n {'code': ValidationCode.BAD_VALUE, 'details': 1},\n {'code': ValidationCode.BAD_VALUE, 'details': 5},\n {'code': ValidationCode.BAD_VALUE}\n ]\n }\n}, schemaA)\n```\n\n# ValidationCode enum\n\n BAD_TYPE = 1\n NOT_IN = 2\n NULL = 3\n MISSING = 4\n OUT_OF_BOUNDS = 5 # for use by validators\n REGEXP = 6\n MANY_ERRORS = 8 # list of errors for a single field\n NOT_GT = 9\n NOT_GTEQ = 10\n NOT_LT = 11\n NOT_LTEQ = 12\n NOT_EQ = 13\n\n# Field description\n```\n\"field: \"type\"\n\"field\": { extended field description }\n```\n\n# Extended field description\nBy default all fields are required and strings must be non-empty. Extra fields in input data are discarded.\n```\n{\n \"@t\": \"type\", # default type is dict\n \n # -- validators --\n \n # Checks that regexp matches - called before other validators.\n \"@regexp\": \"regexp\",\n \n # Validator function.\n \"@val\": val_fun,\n \"@val: [val_fun, val_fun2, ...],\n \n # -- options --\n \n # If True and value is missing, it will not be present in result unless\n # default is defined. Makes sense for subfields in dicts.\n \"@optional\": bool,\n \n # Allows empty strings.\n \"@blank\": bool,\n \n # Used when value is not present.\n # Default value is never passed to validators.\n \"@default\": value,\n \n # Allow nulls (None). By default null is not allowed.\n \"@null\": bool, \n \n # -- limits --\n # Checked before validators are called.\n # They work for string lengths too.\n # TODO: They work for list lengths too.\n \n \"@in\": [value1, value2, ...],\n \"@gt\": value,\n \"@gteq\": value,\n \"@lt\": value,\n \"@lteq\": value,\n \"@neq\": value,\n \n # Extra fields if type is dict.\n \"field1\": field description or extended field description,\n ...\n}\n```\n\n# Lists.\n\n```\n\"field\": [field description]\n\"field\": [{extended field description}]\n```\n\n## TODO: Optional lists.\n\n## TODO: List length limits.\n```\n\"field\": [\n {\n # field description\n }, {\n # list parameters\n \"@optional\": True,\n \"@gt\": val,\n }\n]\n```\n\n# Available types\n## scalar\n - string (str)\n - int\n - decimal\n - float\n - bool\n\n## composite\n - dict\n\n## TODO: Type \"any\" handles any type of subjson withot further validation\n\n# Validator functions\n\n```\ndef fun(val):\n return val + 1\n```\n\nShould either return validated value or raise NotValidError(code, details).\nMay also raise NotValidButContinueError to store the error but call the next validator, constructing a list\nof errors. \n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/okcode-eu/okschema", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "okschema", "package_url": "https://pypi.org/project/okschema/", "platform": "", "project_url": "https://pypi.org/project/okschema/", "project_urls": { "Homepage": "https://github.com/okcode-eu/okschema" }, "release_url": "https://pypi.org/project/okschema/0.2/", "requires_dist": null, "requires_python": "", "summary": "Validate JSON data using a schema written in Python", "version": "0.2" }, "last_serial": 4583046, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "425b9f897a668c8436fdc09c2f78fae2", "sha256": "6f96fe40926b5b4ea512c8257af8bea8b53f3facefb36aac294bc88d31c7c112" }, "downloads": -1, "filename": "okschema-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "425b9f897a668c8436fdc09c2f78fae2", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 6190, "upload_time": "2018-06-13T12:38:05", "url": "https://files.pythonhosted.org/packages/14/bf/9e7f7b2c87b1f1cb071e14d2b846265fca9d0ef676c1a01dacfd17276700/okschema-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "280adf6b24e7dcbbec05a9d14556b4d8", "sha256": "1dbf91f382976c7e80f33a590a8b90dfecba6242e537d75e36be07a8b3b87dfd" }, "downloads": -1, "filename": "okschema-0.1.0.tar.gz", "has_sig": false, "md5_digest": "280adf6b24e7dcbbec05a9d14556b4d8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6077, "upload_time": "2018-06-13T12:38:03", "url": "https://files.pythonhosted.org/packages/ac/e2/d1a14eac745b3e87e64581f44f9c6639b4259a7abd87ec5a44fdb20a8db6/okschema-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "676f0f7c824a4a9fe54e3542246316e0", "sha256": "3ceb5fc462bba59339a544f7b32fc65b7f1b9455917c96bf9fe18ecdf3b47c12" }, "downloads": -1, "filename": "okschema-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "676f0f7c824a4a9fe54e3542246316e0", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 6203, "upload_time": "2018-06-22T20:18:51", "url": "https://files.pythonhosted.org/packages/1c/83/51b018b337cd627878d73c1e36ea3ab0bd6910cf628bd59c90d31aa6e666/okschema-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "99f54f27aa0ec980dc9ae3ea6685c401", "sha256": "037c9a4a8c49b62be1df861bbf8f302443702dd641071df6577bb9e5ee9f1a62" }, "downloads": -1, "filename": "okschema-0.1.1.tar.gz", "has_sig": false, "md5_digest": "99f54f27aa0ec980dc9ae3ea6685c401", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6124, "upload_time": "2018-06-22T20:18:49", "url": "https://files.pythonhosted.org/packages/39/d7/a9575e4c7665ca176e7b1fbe0cfc99ea7c0a1a2063299d6b7588ae729656/okschema-0.1.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "e705a594e2a90dd6f6fdb5b710d105a9", "sha256": "b024850706de849022451a8a3b6b3917724c7665fcf6c11f11bce29f55f8bf38" }, "downloads": -1, "filename": "okschema-0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "e705a594e2a90dd6f6fdb5b710d105a9", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 6251, "upload_time": "2018-12-10T23:15:36", "url": "https://files.pythonhosted.org/packages/21/64/797a19a2f71460c0e89b5a628c4279aef0336ceca9cfccc1ef4cb419e832/okschema-0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "719d489c6f6869620a5607917c57a44d", "sha256": "ea4c3196d5f4be0b367e4fed3234c4e5c3f8417807632984b81ead66532b897c" }, "downloads": -1, "filename": "okschema-0.2.tar.gz", "has_sig": false, "md5_digest": "719d489c6f6869620a5607917c57a44d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6151, "upload_time": "2018-12-10T23:15:33", "url": "https://files.pythonhosted.org/packages/4c/d2/b0320701cc1422d94f05b8eedfac79f93563d2e7e69420e069662cb73932/okschema-0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e705a594e2a90dd6f6fdb5b710d105a9", "sha256": "b024850706de849022451a8a3b6b3917724c7665fcf6c11f11bce29f55f8bf38" }, "downloads": -1, "filename": "okschema-0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "e705a594e2a90dd6f6fdb5b710d105a9", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 6251, "upload_time": "2018-12-10T23:15:36", "url": "https://files.pythonhosted.org/packages/21/64/797a19a2f71460c0e89b5a628c4279aef0336ceca9cfccc1ef4cb419e832/okschema-0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "719d489c6f6869620a5607917c57a44d", "sha256": "ea4c3196d5f4be0b367e4fed3234c4e5c3f8417807632984b81ead66532b897c" }, "downloads": -1, "filename": "okschema-0.2.tar.gz", "has_sig": false, "md5_digest": "719d489c6f6869620a5607917c57a44d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6151, "upload_time": "2018-12-10T23:15:33", "url": "https://files.pythonhosted.org/packages/4c/d2/b0320701cc1422d94f05b8eedfac79f93563d2e7e69420e069662cb73932/okschema-0.2.tar.gz" } ] }