# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['chocs']

package_data = \
{'': ['*']}

install_requires = \
['typing_extensions>=3.7.4,<4.0.0']

setup_kwargs = {
    'name': 'chocs',
    'version': '0.5.3',
    'description': 'Lightweight and powerful wsgi rest framework for rapid building applications based on wsgi servers.',
    'long_description': '# Chocs ![Release](https://github.com/kodemore/chocs/workflows/Release/badge.svg) ![Linting and Tests](https://github.com/kodemore/chocs/workflows/Linting%20and%20Tests/badge.svg) [![codecov](https://codecov.io/gh/kodemore/chocs/branch/master/graph/badge.svg)](https://codecov.io/gh/kodemore/chocs) [![Maintainability](https://api.codeclimate.com/v1/badges/9e3c979283b2361a9174/maintainability)](https://codeclimate.com/github/kodemore/chocs/maintainability)\nChocs is a modern HTTP framework for building AWS HTTP API/REST API and WSGI compatible applications. \nChocs aims to be small, expressive, and robust. \nIt provides an elegant API for writing fault-proof, extensible microservices.  \n\n## Features\n\n - AWS Serverless integration\n - Elegant and easy API\n - No additional bloat like built-in template engines, session handlers, etc.\n - Compatible with all WSGI servers\n - Loosely coupled components which can be used separately\n - Multipart body parsing\n - Graceful error handling\n - HTTP middleware support\n - Fast routing\n\n## Installation\n```\npip install chocs\n```\n\n# Usage\n\n## Quick start\n\n```python\nfrom chocs import HttpApplication\nfrom chocs import HttpRequest\nfrom chocs import HttpResponse\nfrom chocs import serve\n\n\nhttp = HttpApplication()\n\n@http.get("/hello/{name}")\ndef hello(request: HttpRequest) -> HttpResponse:\n    return HttpResponse(f"Hello {request.path_parameters.get(\'name\')}!")\n\nserve()\n```\n\n > Keep in mind that the `serve()` function is using the `bjoern` package, so make sure you included it in your project \n > dependencies before using it. You are able to use any WSGI compatible server.\n\n## Running application with Gunicorn (or any other WSGI server)\n\n```python\n# myapp.py\nfrom chocs import HttpApplication\nfrom chocs import HttpRequest\nfrom chocs import HttpResponse\nfrom chocs import create_wsgi_handler\n\n\nhttp = HttpApplication()\n\n\n@http.get("/hello/{name}*")\ndef hello(request: HttpRequest) -> HttpResponse:\n    return HttpResponse(f"Hello {request.path_parameters.get(\'name\')}!")\n\napp = create_wsgi_handler(http, debug=False)\n```\n\n```bash\ngunicorn -w 4 myapp:app\n```\n\n## Running application in AWS Lambda (Http api or rest api)\n\n`handler.py`\n```python\nimport logging\n\nfrom chocs import HttpRequest\nfrom chocs import HttpResponse\nfrom chocs import HttpApplication\n\nlogger = logging.getLogger()\nlogger.setLevel(logging.INFO)\n\n\nhttp = HttpApplication()\n\n\n@http.get("/hello/{name}")\ndef hello_handler(request: HttpRequest) -> HttpResponse:\n    logger.info("Hello AWS!")\n    logger.info(request.attributes.get("aws_context"))\n    logger.info(request.attributes.get("aws_event"))\n    return HttpResponse(f"Hello {request.path_parameters.get(\'name\')}")\n\n\n__all__ = ["hello_handler"]\n```\n\n`serverless.yml`\n```yaml\nservice: aws-hello-name\n\nprovider:\n  name: aws\n  runtime: python3.8\n\nplugins:\n  - serverless-python-requirements\n\ncustom:\n  pythonRequirements:\n    dockerizePip: true\n\nfunctions:\n  hello_name:\n    handler: handler.hello_handler\n    events:\n      - httpApi:\n          method: GET\n          path: /hello/{name}\n```\n\n```bash\nserverless deploy\n```\n\n## Routing\nChocs is shipped with a built-in routing module. The easiest way to utilise chocs\' routing is to use `chocs.router` object.\n`chocs.router` is an instance of the module\'s internal class `chocs.application.HttpApplication`, which provides a simple API \nwhere each function is a decorator corresponding to an HTTP method.\n\n```python\nfrom chocs import HttpApplication, HttpResponse, HttpRequest\n\n\nhttp = HttpApplication()\n\n\n@http.get("/hello")\ndef hello(req: HttpRequest) -> HttpResponse:\n    ...\n```\n\nThe above example will assign the hello function to handle a `GET /hello` request. \n\nAvailable methods:\n- `delete`\n- `get`\n- `head`\n- `options`\n- `patch`\n- `post`\n- `put`\n- `trace`\n\n### Parametrized routes\n\nRoutes can contain parameterised parts. Parameters must be enclosed within `{` and `}`.\n\n```python\nfrom chocs import HttpApplication\n\nhttp = HttpApplication()\n\n\n@http.get("/pet/{id}")\ndef hello():\n    ...\n```\nWill match the following URIs:\n - `/pet/1`\n - `/pet/abc`\n - `/pet/abc1`\n \n### Wildcard routes\n\nAsterisks (`*`) can be used in the route\'s pattern to match any possible combination. Keep in mind that routes which \n_do not_ contain wildcards are prioritised over routes with wildcards.\n\n```python\nfrom chocs import HttpApplication\n\nhttp = HttpApplication()\n\n\n@http.get("/pet/*", id)\ndef hello():\n    ...\n```\n\nThe above example will match following URIs:\n- `/pet/a`\n- `/pet/a/b/c`\n- `/pet/12jd/fds`\n\n## Defining and using a custom middleware\n\nMiddleware are functions or classes that inherit `chocs.Middleware`. Middlewares have access to the request \nobject and the next function is used to control middleware stack flow. Successful middleware execution should call\nthe `next` function *(which accepts a `chocs.HttpRequest` instance and returns `chocs.HttpReponse`)* and return a\nvalid `chocs.HttpResponse` instance.\n\nMiddlewares can perform various tasks:\n - Making changes in request/response objects ending\n - Validating input data\n - Authenticating users\n - End request-response cycle\n - Connecting to external data sources\n \nMiddlewares are different to functions decorated by `router.*` decorators as they are executed every time a request \nhappens and they are not bound to the URI.\n \n```python\nfrom chocs import HttpRequest, HttpResponse, HttpApplication, serve\nfrom chocs.middleware import MiddlewareHandler\n\ndef my_custom_middleware(request: HttpRequest, next: MiddlewareHandler) -> HttpResponse:\n    name = request.query_string.get("name", "John")\n    return HttpResponse(body=f"Hello {name}")\n\napp = HttpApplication(my_custom_middleware)\n\nserve(app)\n```\n\n## Request\n`chocs.Request` object is an abstraction around WSGI\'s environment and `wsgi.input` data with handy interface \nto ease everyday work.\n\n#### `chocs.Request.headers:chocs.HttpHeaders (read-only)`\nKeeps parsed headers in dict-like object.\n\n#### `chocs.Request.body:io.BytesIO` \nRaw body data\n\n#### `Request.parsed_body:chocs.HttpMessage`\nDepending on the content type it could be one of the following:\n - `chocs.FormHttpMessage`\n - `chocs.JsonHttpMessage`\n - `chocs.MultipartHttpMessage`\n \n#### `chocs.Request.cookies:typing.List[chocs.HttpCookie]` \nRequest\'s cookies\n\n#### `chocs.Request.method:chocs.HttpMethod`\nThe request\'s method\n\n#### `chocs.Request.path:str`\nThe request\'s path\n\n#### `chocs.Request.query_string:chocs.HttpQueryString`\nA dict like object with parsed query string with JSON forms support\n        \n#### `chocs.Request.path_parameters:dict`\nMatched route parameters, for example when `/users/john` matches the `/users/{name}` route, parameters will contain a \n`name` key with a value of `john`\n\n#### `chocs.Request.attributes:dict`\nOther environmental or custom attributes attached to the request object, eg.: `aws_event` or `aws_context`\nwhen running chocs app as aws lambda.\n\n## Response\n`chocs.Response` object is a part of request-response flow and it is required to be returned by all functions\ndecorated with `router.*` method. Instance of the response class is recognised by `chocs.Application` and used to \ngenerate real response served to your clients.\n\n#### `chocs.Response.body: io.BytesIO` \nBody served to server\'s clients.\n\n### `chocs.Response.status_code: chocs.HttpStatus`\nValid response code, instance of `chocs.HttpStatus` enum can be used or just a status code\'s number.\n\n#### `chocs.Response.cookies:chocs.HttpCookieJar` \nResponse\'s cookies\n\n#### `chocs.Response.write(body: Union[bytes, str, bytearray])`\nWrite bytes to response body\n\n#### `chocs.Response.close()`\nMakes body non-writable.\n\n#### `chocs.Response.writable: bool`\nIndicates whether response\'s body is writable.\n\n## Working with cookies\n\n`chocs.HttpCookieJar` object takes care of cookie handling. It can be accessed in dict-like manner, when item is requested,\ninstance of `chocs.HttpCookie` is returned to user. \n\nCookies can be set either by passing string value to the `chocs.CookieJar`\'s key, or by calling `chocs.CookieJar.append` \nmethod which accepts instance of `chocs.Cookie`.\n\n### Reading client cookies\n\nCookies can be easily accessed from `chocs.Request.cookies` object which is injected as a parameter to each function \nregistered as route handler. Consider the following example:\n\n```python\nfrom chocs import HttpRequest\nfrom chocs import HttpResponse\nfrom chocs import HttpApplication\nfrom chocs import serve\n\nhttp = HttpApplication()\n\n\n@http.get("/cookies")\ndef read_cookies(request: HttpRequest) -> HttpResponse:\n\n    message = "Hello"\n    if "user_name" in request.cookies:\n        message += f", {str(request.cookies[\'user_name\'])}"\n    message += "!"\n\n    return HttpResponse(body=message)\n\nserve(http)\n```\n\n### Setting cookies\n```python\nfrom datetime import datetime\n\nfrom chocs import HttpCookie\nfrom chocs import HttpRequest\nfrom chocs import HttpResponse\nfrom chocs import HttpApplication\nfrom chocs import serve\n\nhttp = HttpApplication()\n\n\n@http.get("/cookies")\ndef read_cookies(request: HttpRequest) -> HttpResponse:\n    response = HttpResponse(body="Hi! I have baked some cookies for ya!")\n    response.cookies[\'simple-cookie\'] = "Simple cookie for simple people"\n    response.cookies.append(HttpCookie("advanced-cookie", "This cookie will expire in 2021-01-01", expires=datetime(2021, 1, 1)))\n    return response\n\nserve(http)\n```\n\n# Contributing\n\n## Prerequisites\n\n- libev\n- python 3.8\n- docker\n\n## Installation\n\n`poetry install`\n',
    'author': 'Dawid Kraczkowski',
    'author_email': 'dawid.kraczkowski@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/kodemore/chocs',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
