# webargs-sanic
[Sanic](https://github.com/huge-success/sanic) integration with [Webargs](https://github.com/sloria/webargs).
Parsing and validating request arguments: headers, arguments, cookies, files, json, etc.
IMPORTANT: From version 2.0.0 webargs-sanic requires you to have webargs >=7.0.1. Please be aware of changes happened in version of webargs > 6.0.0. If you need support of webargs 5.x with no location definition, please use previous version(1.5.0) of this module from pypi.
[![Build Status](https://img.shields.io/travis/EndurantDevs/webargs-sanic.svg?logo=travis)](https://app.travis-ci.com/EndurantDevs/webargs-sanic) [![Latest Version](https://img.shields.io/pypi/v/webargs-sanic.svg)](https://pypi.python.org/pypi/webargs-sanic/) [![Python Versions](https://img.shields.io/pypi/pyversions/webargs-sanic.svg)](https://github.com/EndurantDevs/webargs-sanic/blob/master/setup.py) [![Tests Coverage](https://img.shields.io/codecov/c/github/EndurantDevs/webargs-sanic/master.svg)](https://codecov.io/gh/EndurantDevs/webargs-sanic)
[webargs](https://github.com/sloria/webargs) is a Python library for parsing and validating HTTP request arguments, with built-in support for popular web frameworks. webargs-sanic allows you to use it for [Sanic](https://github.com/huge-success/sanic) apps. To read more about webargs usage, please check [Quickstart](https://webargs.readthedocs.io/en/latest/quickstart.html)
## Example Code ##
### Simple Application ###
```python
from sanic import Sanic
from sanic.response import text
from webargs import fields
from webargs_sanic.sanicparser import use_args
app = Sanic(__name__)
hello_args = {
'name': fields.Str(required=True)
}
@app.route('/')
@use_args(hello_args, location="query")
async def index(request, args):
return text('Hello ' + args['name'])
```
### Class-based Sanic app and args/kwargs ###
```python
from sanic import Sanic
from sanic.views import HTTPMethodView
from sanic.response import json
from webargs import fields
from webargs_sanic.sanicparser import use_args, use_kwargs
app = Sanic(__name__)
class EchoMethodViewUseArgs(HTTPMethodView):
@use_args({"val": fields.Int()}, location="form")
async def post(self, request, args):
return json(args)
app.add_route(EchoMethodViewUseArgs.as_view(), "/echo_method_view_use_args")
class EchoMethodViewUseKwargs(HTTPMethodView):
@use_kwargs({"val": fields.Int()}, location="query")
async def post(self, request, val):
return json({"val": val})
app.add_route(EchoMethodViewUseKwargs.as_view(), "/echo_method_view_use_kwargs")
```
### Parser without decorator with returning errors as JSON ###
```python
from sanic import Sanic
from sanic.response import json
from webargs import fields
from webargs_sanic.sanicparser import parser, HandleValidationError
app = Sanic(__name__)
@app.route("/echo_view_args_validated/<value>", methods=["GET"])
async def echo_use_args_validated(request, args):
parsed = await parser.parse(
{"value": fields.Int(required=True, validate=lambda args: args["value"] > 42)}, request, location="view_args"
)
return json(parsed)
# Return validation errors as JSON
@app.exception(HandleValidationError)
async def handle_validation_error(request, err):
return json({"errors": err.exc.messages}, status=422)
```
### More complicated custom example ###
```python
from sanic import Sanic
from sanic import response
from sanic import Blueprint
from webargs_sanic.sanicparser import use_kwargs
from some_CUSTOM_storage import InMemory
from webargs import fields
from webargs import validate
import marshmallow.fields
from validate_email import validate_email
#usually this should not be here, better to import ;)
#please check examples for more info
class Email(marshmallow.fields.Field):
def __init__(self, *args, **kwargs):
super(Email, self).__init__(*args, **kwargs)
def _deserialize(self, value, attr, obj):
value = value.strip().lower()
if not validate_email(value):
self.fail('validator_failed')
return value
user_update = {
'user_data': fields.Nested({
'email': Email(),
'password': fields.Str(validate=lambda value: len(value)>=8),
'first_name': fields.Str(validate=lambda value: len(value)>=1),
'last_name': fields.Str(validate=lambda value: len(value)>=1),
'middle_name': fields.Str(),
'gender': fields.Str(validate=validate.OneOf(["M", "F"])),
'birth_date': fields.Date(),
}),
'user_id': fields.Str(required=True, validate=lambda x:len(x)==32),
}
blueprint = Blueprint('app')
storage = InMemory()
@blueprint.put('/user/')
@use_kwargs(user_update, location="json_or_form")
async def update_user(request, user_id, user_data):
storage.update_or_404(user_id, user_data)
return response.text('', status=204)
app = Sanic(__name__)
app.blueprint(blueprint, url_prefix='/')
```
For more examples and checking how to use custom validations (phones, emails, etc.) please check apps in [Examples](https://github.com/EndurantDevs/webargs-sanic/tree/master/examples/)
## Installing ##
It is easy to do from `pip`
```
pip install webargs-sanic
```
or from sources
```
git clone git@github.com:EndurantDevs/webtest-sanic.git
cd webtest-sanic
python setup.py install
```
## Running the tests
Project uses common tests from webargs package. Thanks to [Steven Loria](https://github.com/sloria) for [sharing tests in webargs v4.1.0](https://github.com/sloria/webargs/pull/287#issuecomment-422232384).
Most of tests are run by webtest via [webtest-sanic](https://github.com/EndurantDevs/webtest-sanic).
Some own tests get run via Sanic's TestClient.
To be sure everything is fine before installation from sources, just run:
```bash
pip -r requirements.txt
```
and then
```bash
python setup.py test
```
Or
```bash
pytest tests/
```
## Authors
[<img src="https://github.com/EndurantDevs/botstat-seo/raw/master/docs/img/EndurantDevs-big.png" alt="Endurant Developers Python Team" width="150">](https://www.EndurantDev.com)
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
Raw data
{
"_id": null,
"home_page": "https://github.com/EndurantDevs/webargs-sanic",
"name": "webargs-sanic",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "webargs-sanic webargs sanic web args validation",
"author": "Endurant Devs, Dmytro Nikolayev",
"author_email": "info@endurantdev.com",
"download_url": "https://files.pythonhosted.org/packages/46/34/a4a12c7742d27e07d43372b1636f130ce502da3b6cd1fbfbe184f0f03e91/webargs-sanic-2.3.4.tar.gz",
"platform": null,
"description": "# webargs-sanic\n[Sanic](https://github.com/huge-success/sanic) integration with [Webargs](https://github.com/sloria/webargs). \n\nParsing and validating request arguments: headers, arguments, cookies, files, json, etc.\n\nIMPORTANT: From version 2.0.0 webargs-sanic requires you to have webargs >=7.0.1. Please be aware of changes happened in version of webargs > 6.0.0. If you need support of webargs 5.x with no location definition, please use previous version(1.5.0) of this module from pypi. \n\n[![Build Status](https://img.shields.io/travis/EndurantDevs/webargs-sanic.svg?logo=travis)](https://app.travis-ci.com/EndurantDevs/webargs-sanic) [![Latest Version](https://img.shields.io/pypi/v/webargs-sanic.svg)](https://pypi.python.org/pypi/webargs-sanic/) [![Python Versions](https://img.shields.io/pypi/pyversions/webargs-sanic.svg)](https://github.com/EndurantDevs/webargs-sanic/blob/master/setup.py) [![Tests Coverage](https://img.shields.io/codecov/c/github/EndurantDevs/webargs-sanic/master.svg)](https://codecov.io/gh/EndurantDevs/webargs-sanic)\n\n[webargs](https://github.com/sloria/webargs) is a Python library for parsing and validating HTTP request arguments, with built-in support for popular web frameworks. webargs-sanic allows you to use it for [Sanic](https://github.com/huge-success/sanic) apps. To read more about webargs usage, please check [Quickstart](https://webargs.readthedocs.io/en/latest/quickstart.html)\n\n## Example Code ##\n\n### Simple Application ###\n```python\nfrom sanic import Sanic\nfrom sanic.response import text\n\nfrom webargs import fields\nfrom webargs_sanic.sanicparser import use_args\n\n\napp = Sanic(__name__)\n\nhello_args = {\n 'name': fields.Str(required=True)\n}\n\n@app.route('/')\n@use_args(hello_args, location=\"query\")\nasync def index(request, args):\n return text('Hello ' + args['name'])\n\n\n```\n\n### Class-based Sanic app and args/kwargs ###\n\n```python\nfrom sanic import Sanic\nfrom sanic.views import HTTPMethodView\nfrom sanic.response import json\n\nfrom webargs import fields\nfrom webargs_sanic.sanicparser import use_args, use_kwargs\n\n\napp = Sanic(__name__)\n\nclass EchoMethodViewUseArgs(HTTPMethodView):\n @use_args({\"val\": fields.Int()}, location=\"form\")\n async def post(self, request, args):\n return json(args)\n\n\napp.add_route(EchoMethodViewUseArgs.as_view(), \"/echo_method_view_use_args\")\n\n\nclass EchoMethodViewUseKwargs(HTTPMethodView):\n @use_kwargs({\"val\": fields.Int()}, location=\"query\")\n async def post(self, request, val):\n return json({\"val\": val})\n\n\napp.add_route(EchoMethodViewUseKwargs.as_view(), \"/echo_method_view_use_kwargs\")\n```\n\n### Parser without decorator with returning errors as JSON ###\n```python\nfrom sanic import Sanic\nfrom sanic.response import json\n\nfrom webargs import fields\nfrom webargs_sanic.sanicparser import parser, HandleValidationError\n\napp = Sanic(__name__)\n\n@app.route(\"/echo_view_args_validated/<value>\", methods=[\"GET\"])\nasync def echo_use_args_validated(request, args):\n parsed = await parser.parse(\n {\"value\": fields.Int(required=True, validate=lambda args: args[\"value\"] > 42)}, request, location=\"view_args\"\n )\n return json(parsed)\n\n\n# Return validation errors as JSON\n@app.exception(HandleValidationError)\nasync def handle_validation_error(request, err):\n return json({\"errors\": err.exc.messages}, status=422)\n```\n\n### More complicated custom example ###\n```python\nfrom sanic import Sanic\nfrom sanic import response\nfrom sanic import Blueprint\n\nfrom webargs_sanic.sanicparser import use_kwargs\n\nfrom some_CUSTOM_storage import InMemory\n\nfrom webargs import fields\nfrom webargs import validate\n\nimport marshmallow.fields\nfrom validate_email import validate_email\n\n#usually this should not be here, better to import ;)\n#please check examples for more info\nclass Email(marshmallow.fields.Field):\n\n def __init__(self, *args, **kwargs):\n super(Email, self).__init__(*args, **kwargs)\n\n def _deserialize(self, value, attr, obj):\n value = value.strip().lower()\n if not validate_email(value):\n self.fail('validator_failed')\n return value\n\nuser_update = {\n 'user_data': fields.Nested({\n 'email': Email(),\n 'password': fields.Str(validate=lambda value: len(value)>=8),\n 'first_name': fields.Str(validate=lambda value: len(value)>=1),\n 'last_name': fields.Str(validate=lambda value: len(value)>=1),\n 'middle_name': fields.Str(),\n 'gender': fields.Str(validate=validate.OneOf([\"M\", \"F\"])),\n 'birth_date': fields.Date(),\n }),\n 'user_id': fields.Str(required=True, validate=lambda x:len(x)==32),\n}\n\n\nblueprint = Blueprint('app')\nstorage = InMemory()\n\n\n@blueprint.put('/user/')\n@use_kwargs(user_update, location=\"json_or_form\")\nasync def update_user(request, user_id, user_data):\n storage.update_or_404(user_id, user_data)\n return response.text('', status=204)\n\napp = Sanic(__name__)\napp.blueprint(blueprint, url_prefix='/')\n\n```\n\nFor more examples and checking how to use custom validations (phones, emails, etc.) please check apps in [Examples](https://github.com/EndurantDevs/webargs-sanic/tree/master/examples/)\n\n## Installing ##\n\nIt is easy to do from `pip`\n\n```\npip install webargs-sanic\n```\n\nor from sources\n\n```\ngit clone git@github.com:EndurantDevs/webtest-sanic.git\ncd webtest-sanic\npython setup.py install\n```\n\n## Running the tests\n\nProject uses common tests from webargs package. Thanks to [Steven Loria](https://github.com/sloria) for [sharing tests in webargs v4.1.0](https://github.com/sloria/webargs/pull/287#issuecomment-422232384). \nMost of tests are run by webtest via [webtest-sanic](https://github.com/EndurantDevs/webtest-sanic). \nSome own tests get run via Sanic's TestClient.\n\nTo be sure everything is fine before installation from sources, just run:\n```bash\npip -r requirements.txt\n```\nand then\n```bash\npython setup.py test\n```\nOr\n```bash\npytest tests/\n```\n\n\n## Authors\n[<img src=\"https://github.com/EndurantDevs/botstat-seo/raw/master/docs/img/EndurantDevs-big.png\" alt=\"Endurant Developers Python Team\" width=\"150\">](https://www.EndurantDev.com)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "webargs-sanic provides integration of Webargs with Sanic applications",
"version": "2.3.4",
"project_urls": {
"Homepage": "https://github.com/EndurantDevs/webargs-sanic"
},
"split_keywords": [
"webargs-sanic",
"webargs",
"sanic",
"web",
"args",
"validation"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "92b043229af2e4698b0ef56214500aea366649e2fa8e5b41f7c097c208058722",
"md5": "5114dfdfe88a92661aeeaf4b7d9fafab",
"sha256": "496ba37b3e616371dda65b7ef58106b13c6cd222550c99d218be1559f5e8c178"
},
"downloads": -1,
"filename": "webargs_sanic-2.3.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5114dfdfe88a92661aeeaf4b7d9fafab",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 6845,
"upload_time": "2023-06-26T10:23:09",
"upload_time_iso_8601": "2023-06-26T10:23:09.882908Z",
"url": "https://files.pythonhosted.org/packages/92/b0/43229af2e4698b0ef56214500aea366649e2fa8e5b41f7c097c208058722/webargs_sanic-2.3.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4634a4a12c7742d27e07d43372b1636f130ce502da3b6cd1fbfbe184f0f03e91",
"md5": "e08cb381e11c16843d59e9ca4fd93306",
"sha256": "9fe6975a733ef4b8ac7213acc5c9d69c6e890d3bb5bc5b8eb7bfb3a7ad66e7e2"
},
"downloads": -1,
"filename": "webargs-sanic-2.3.4.tar.gz",
"has_sig": false,
"md5_digest": "e08cb381e11c16843d59e9ca4fd93306",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 9772,
"upload_time": "2023-06-26T10:23:12",
"upload_time_iso_8601": "2023-06-26T10:23:12.334546Z",
"url": "https://files.pythonhosted.org/packages/46/34/a4a12c7742d27e07d43372b1636f130ce502da3b6cd1fbfbe184f0f03e91/webargs-sanic-2.3.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-26 10:23:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "EndurantDevs",
"github_project": "webargs-sanic",
"travis_ci": true,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "aiofiles",
"specs": [
[
"==",
"23.1.0"
]
]
},
{
"name": "aiohttp",
"specs": [
[
"==",
"3.8.4"
]
]
},
{
"name": "aiosignal",
"specs": [
[
"==",
"1.3.1"
]
]
},
{
"name": "anyio",
"specs": [
[
"==",
"3.7.0"
]
]
},
{
"name": "async-timeout",
"specs": [
[
"==",
"4.0.2"
]
]
},
{
"name": "attrs",
"specs": [
[
"==",
"23.1.0"
]
]
},
{
"name": "beautifulsoup4",
"specs": [
[
"==",
"4.12.2"
]
]
},
{
"name": "certifi",
"specs": [
[
"==",
"2023.5.7"
]
]
},
{
"name": "cffi",
"specs": [
[
"==",
"1.15.1"
]
]
},
{
"name": "charset-normalizer",
"specs": [
[
"==",
"3.1.0"
]
]
},
{
"name": "codecov",
"specs": [
[
"==",
"2.1.13"
]
]
},
{
"name": "coverage",
"specs": [
[
"==",
"7.2.7"
]
]
},
{
"name": "cryptography",
"specs": [
[
"==",
"41.0.1"
]
]
},
{
"name": "exceptiongroup",
"specs": [
[
"==",
"1.1.1"
]
]
},
{
"name": "frozenlist",
"specs": [
[
"==",
"1.3.3"
]
]
},
{
"name": "h11",
"specs": [
[
"==",
"0.14.0"
]
]
},
{
"name": "html5tagger",
"specs": [
[
"==",
"1.3.0"
]
]
},
{
"name": "httpcore",
"specs": [
[
"==",
"0.16.3"
]
]
},
{
"name": "httptools",
"specs": [
[
"==",
"0.5.0"
]
]
},
{
"name": "httpx",
"specs": [
[
"==",
"0.23.3"
]
]
},
{
"name": "idna",
"specs": [
[
"==",
"3.4"
]
]
},
{
"name": "iniconfig",
"specs": [
[
"==",
"2.0.0"
]
]
},
{
"name": "jeepney",
"specs": [
[
"==",
"0.8.0"
]
]
},
{
"name": "marshmallow",
"specs": [
[
"==",
"3.19.0"
]
]
},
{
"name": "mock",
"specs": [
[
"==",
"5.0.2"
]
]
},
{
"name": "multidict",
"specs": [
[
"==",
"5.2.0"
]
]
},
{
"name": "packaging",
"specs": [
[
"==",
"23.1"
]
]
},
{
"name": "pluggy",
"specs": [
[
"==",
"0.13.1"
]
]
},
{
"name": "pycparser",
"specs": [
[
"==",
"2.21"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"7.3.2"
]
]
},
{
"name": "pytest-aiohttp",
"specs": [
[
"==",
"0.3.0"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
"==",
"2.11.1"
]
]
},
{
"name": "requests",
"specs": [
[
"==",
"2.31.0"
]
]
},
{
"name": "rfc3986",
"specs": [
[
"==",
"1.5.0"
]
]
},
{
"name": "sanic",
"specs": [
[
"==",
"23.3.0"
]
]
},
{
"name": "sanic-routing",
"specs": [
[
"==",
"22.8.0"
]
]
},
{
"name": "sanic-testing",
"specs": [
[
"==",
"23.3.0"
]
]
},
{
"name": "SecretStorage",
"specs": [
[
"==",
"3.3.3"
]
]
},
{
"name": "sniffio",
"specs": [
[
"==",
"1.3.0"
]
]
},
{
"name": "soupsieve",
"specs": [
[
"==",
"2.4.1"
]
]
},
{
"name": "toml",
"specs": [
[
"==",
"0.10.2"
]
]
},
{
"name": "tracerite",
"specs": [
[
"==",
"1.1.0"
]
]
},
{
"name": "ujson",
"specs": [
[
"==",
"5.8.0"
]
]
},
{
"name": "urllib3",
"specs": [
[
"==",
"2.0.3"
]
]
},
{
"name": "uvloop",
"specs": [
[
"==",
"0.17.0"
]
]
},
{
"name": "waitress",
"specs": [
[
"==",
"2.1.2"
]
]
},
{
"name": "webargs",
"specs": []
},
{
"name": "WebOb",
"specs": [
[
"==",
"1.8.7"
]
]
},
{
"name": "websockets",
"specs": [
[
"==",
"11.0.3"
]
]
},
{
"name": "WebTest",
"specs": [
[
"==",
"3.0.0"
]
]
},
{
"name": "webtest-sanic",
"specs": [
[
"==",
"0.4.2"
]
]
},
{
"name": "yarl",
"specs": [
[
"==",
"1.9.2"
]
]
}
],
"lcname": "webargs-sanic"
}