{ "info": { "author": "Diogo Dutra", "author_email": "diogodutradamata@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 1 - Planning", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Topic :: Software Development :: Libraries" ], "description": "# dataclassesapi\n\n
\n \n \n \n
\n Asgi App using typing annotation\n
\n\n---\n\n**Documentation**: https://dutradda.github.io/dataclassesapi\n\n**Source Code**: https://github.com/dutradda/dataclassesapi\n\n---\n\n\n## Key Features\n\n- Declare request object as @dataclass:\n + `PathArgs` for values on path\n + `Query` for values on query string\n + `Headers` for values on headers\n + `Body` for values on body\n\n- Declare response object as @dataclass:\n + `Headers` for values on headers\n + `Body` for values on body\n\n\n## Requirements\n\n - Python 3.7+\n - [dataclassesjson](https://github.com/dutradda/dataclassesjson) for json validation/parsing\n - [orjson](https://github.com/ijl/orjson) for json/bytes serialization\n\n\n## Instalation\n```\n$ pip install dataclassesapi\n```\n\n\n## Basic example\n\n```python\nfrom dataclasses import dataclass\nfrom http import HTTPStatus\n\nfrom dataclassesjson import dataclassjson\n\nfrom dataclassesapi import MethodType, Route, asgi_app\nfrom dataclassesapi.request import Query, Request\nfrom dataclassesapi.response import Body as ResponseBody\nfrom dataclassesapi.response import Response\n\n\n@dataclass\nclass MyQuery(Query):\n name: str\n\n\n@dataclass\nclass MyRequest(Request):\n query: MyQuery\n\n\n@dataclass\nclass MyResponseBody(ResponseBody):\n message: str\n\n\n@dataclassjson\n@dataclass\nclass MyResponse(Response):\n body: MyResponseBody\n\n\ndef hello_controller(req: MyRequest) -> MyResponse:\n name = req.query.name\n body = MyResponseBody(message=f'Hello {name}!')\n return MyResponse(HTTPStatus.OK, body=body)\n\n\napp = asgi_app([Route('/hello', MethodType.GET, hello_controller)])\n\n```\n\nRunning the server (needs uvicorn [installed](https://www.uvicorn.org)):\n\n```bash\nuvicorn myapp:app\n\n```\n\n```\nINFO: Started server process [16220]\nINFO: Waiting for application startup.\nINFO: ASGI 'lifespan' protocol appears unsupported.\nINFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\n\n```\n\nQuering the server (needs curl [installed](https://curl.haxx.se/docs/install.html)):\n\n```bash\ncurl -i localhost:8000/hello?name=World\n\n```\n\n```\nHTTP/1.1 200 OK\ndate: Thu, 1st January 1970 00:00:00 GMT\nserver: uvicorn\ncontent-type: application/json\ncontent-length: 26\n\n{\"message\":\"Hello World!\"}\n\n```\n\n\n## Example for complete request/response\n\n```python\nfrom dataclasses import dataclass\nfrom http import HTTPStatus\n\nfrom dataclassesjson import dataclassjson, integer, string\n\nfrom dataclassesapi import MethodType, Route, asgi_app\nfrom dataclassesapi.request import Body, Headers, PathArgs, Query, Request\nfrom dataclassesapi.response import Body as ResponseBody\nfrom dataclassesapi.response import Response\n\n\n@dataclass\nclass MyPathArgs(PathArgs):\n name: str\n\n\n@dataclass\nclass MyQuery(Query):\n location: str\n\n\n@dataclass\nclass MyHeaders(Headers):\n x_req_id: str\n\n\n@dataclass\nclass MyBody(Body):\n last_name: str\n age: int\n\n\n@dataclass\nclass MyRequest(Request):\n path_args: MyPathArgs\n query: MyQuery\n headers: MyHeaders\n body: MyBody\n\n\n@dataclass\nclass You:\n name: str\n last_name: str\n location: string(max_length=100)\n age: integer(minimum=18)\n\n\n@dataclass\nclass MyResponseBody(ResponseBody):\n hello_message: str\n about_you: You\n\n\n@dataclassjson\n@dataclass\nclass MyResponse(Response):\n body: MyResponseBody\n headers: MyHeaders\n\n\ndef hello_controller(req: MyRequest) -> MyResponse:\n body = MyResponseBody(\n hello_message=hello_message(req.path_args.name, req.query.location),\n about_you=You(\n name=req.path_args.name,\n last_name=req.body.last_name,\n location=req.query.location,\n age=req.body.age,\n ),\n )\n headers = MyHeaders(x_req_id=req.headers.x_req_id)\n return MyResponse(HTTPStatus.OK, body=body, headers=headers)\n\n\ndef hello_message(name: str, location: str) -> str:\n return f'Hello {name}! Welcome to {location}!'\n\n\napp = asgi_app([Route('/hello/{name}', MethodType.PUT, hello_controller)])\n\n```\n\nRunning the server:\n\n```bash\nuvicorn myapp:app\n\n```\n\n```\nINFO: Started server process [16220]\nINFO: Waiting for application startup.\nINFO: ASGI 'lifespan' protocol appears unsupported.\nINFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\n\n```\n\nQuering the server:\n\n```bash\ncurl -i -X PUT localhost:8000/hello/Me?location=World \\\n -H 'x-req-id: 1a2b3c4d5e6f7g8h' \\\n -d '{\"last_name\":\"My Self\",\"age\":32}'\n\n```\n\n```\nHTTP/1.1 200 OK\ndate: Thu, 1st January 1970 00:00:00 GMT\nserver: uvicorn\nx-req-id: 1a2b3c4d5e6f7g8h\ncontent-type: application/json\ncontent-length: 123\n\n{\"hello_message\":\"Hello Me! Welcome to World!\",\"about_you\":{\"name\":\"Me\",\"last_name\":\"My Self\",\"location\":\"World\",\"age\":32}}\n\n```\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/dutradda/dataclassesapi", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "dataclassesapi", "package_url": "https://pypi.org/project/dataclassesapi/", "platform": "", "project_url": "https://pypi.org/project/dataclassesapi/", "project_urls": { "Documentation": "https://dutradda.github.io/dataclassesapi/", "Homepage": "https://github.com/dutradda/dataclassesapi" }, "release_url": "https://pypi.org/project/dataclassesapi/0.2.0/", "requires_dist": [ "dataclassesjson[orjson]", "mkdocs; extra == \"doc\"", "mkdocs-material; extra == \"doc\"", "markdown-include; extra == \"doc\"", "asgi-testclient; extra == \"test\"", "bumpversion; extra == \"test\"", "black; extra == \"test\"", "flake8; extra == \"test\"", "isort; extra == \"test\"", "ipython; extra == \"test\"", "mypy; extra == \"test\"", "pytest-asyncio; extra == \"test\"", "pytest-cov; extra == \"test\"", "pytest-mock; extra == \"test\"", "pytest>=5.1.1; extra == \"test\"", "tox; extra == \"test\"", "towncrier; extra == \"test\"", "uvicorn; extra == \"test\"" ], "requires_python": ">=3.7", "summary": "ASGI App using dataclasses module for request/response objects", "version": "0.2.0" }, "last_serial": 5847886, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "772eedc735821db33138f4b9d1c41187", "sha256": "099763ed9d794440ce81a85e0ef7e00ad95d9cd5c8a8b627d44ee577dc29eb73" }, "downloads": -1, "filename": "dataclassesapi-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "772eedc735821db33138f4b9d1c41187", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 26585, "upload_time": "2019-09-18T03:26:35", "url": "https://files.pythonhosted.org/packages/40/1d/b57ca095c69bf6fbf1b7e92e203e877aafb0ca814cf99dd424a55f5d47ec/dataclassesapi-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d99458276933469cd65e045a0ebf1942", "sha256": "cb05338dd9c8429946948910c1586322b8a39d184ef9b0b128ca825d2f83bea5" }, "downloads": -1, "filename": "dataclassesapi-0.1.0.tar.gz", "has_sig": false, "md5_digest": "d99458276933469cd65e045a0ebf1942", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 23355, "upload_time": "2019-09-18T03:26:39", "url": "https://files.pythonhosted.org/packages/a7/8b/a3322bcec9e2b85ff00e9aa30368bf4a5e0ce450ec3e023beb8f3108b748/dataclassesapi-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "5de8fbf9e3ea8de46a8730adc922cd17", "sha256": "15ef2459503e49c71c288ec805ef83ec4903880ae43e2d7f81168fc2d5939eb3" }, "downloads": -1, "filename": "dataclassesapi-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5de8fbf9e3ea8de46a8730adc922cd17", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 26584, "upload_time": "2019-09-18T03:33:51", "url": "https://files.pythonhosted.org/packages/10/f3/0a0c6b44dbdc88eb20d3a85fb91a65647c12e07494b801aef0b995194b68/dataclassesapi-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4b41cf09c4e5b0237f8e1cb7e828801d", "sha256": "7ff4a8430cf51abb020418f178683ede5c03211a7a47ed8bab53613aebdb1906" }, "downloads": -1, "filename": "dataclassesapi-0.1.1.tar.gz", "has_sig": false, "md5_digest": "4b41cf09c4e5b0237f8e1cb7e828801d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 23377, "upload_time": "2019-09-18T03:33:54", "url": "https://files.pythonhosted.org/packages/c5/47/45c202fe7f5a5532bfebe876d00167eccdd5009ea4f2a48729fefe370f3c/dataclassesapi-0.1.1.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "0ed765136ecf9aef0641e7ca8544da9d", "sha256": "03148da85c78b7be32bd43308c0383740013fb8fa9cf2de77801ed60165fc685" }, "downloads": -1, "filename": "dataclassesapi-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0ed765136ecf9aef0641e7ca8544da9d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 26095, "upload_time": "2019-09-18T05:28:33", "url": "https://files.pythonhosted.org/packages/a4/2a/79eef2e3f88de83cf1eaaf04f61785d6b48e6d93e3ef0d39d0f37c5025d2/dataclassesapi-0.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8a973b301286a09c25fc7ea78bc946d7", "sha256": "b63727d480f22d690ae03f5136872f1dc10f26a2dca3b519d263d62ee3226346" }, "downloads": -1, "filename": "dataclassesapi-0.2.0.tar.gz", "has_sig": false, "md5_digest": "8a973b301286a09c25fc7ea78bc946d7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 23507, "upload_time": "2019-09-18T05:28:36", "url": "https://files.pythonhosted.org/packages/29/71/7e439dcb4f38df3f3b3c779d9aa986486fa32c869796dbce679bed3e7fd5/dataclassesapi-0.2.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0ed765136ecf9aef0641e7ca8544da9d", "sha256": "03148da85c78b7be32bd43308c0383740013fb8fa9cf2de77801ed60165fc685" }, "downloads": -1, "filename": "dataclassesapi-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0ed765136ecf9aef0641e7ca8544da9d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 26095, "upload_time": "2019-09-18T05:28:33", "url": "https://files.pythonhosted.org/packages/a4/2a/79eef2e3f88de83cf1eaaf04f61785d6b48e6d93e3ef0d39d0f37c5025d2/dataclassesapi-0.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8a973b301286a09c25fc7ea78bc946d7", "sha256": "b63727d480f22d690ae03f5136872f1dc10f26a2dca3b519d263d62ee3226346" }, "downloads": -1, "filename": "dataclassesapi-0.2.0.tar.gz", "has_sig": false, "md5_digest": "8a973b301286a09c25fc7ea78bc946d7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 23507, "upload_time": "2019-09-18T05:28:36", "url": "https://files.pythonhosted.org/packages/29/71/7e439dcb4f38df3f3b3c779d9aa986486fa32c869796dbce679bed3e7fd5/dataclassesapi-0.2.0.tar.gz" } ] }