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

packages = \
['routerling']

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

install_requires = \
['uvicorn>=0.14.0,<0.15.0']

setup_kwargs = {
    'name': 'routerling',
    'version': '0.2.6',
    'description': 'Extremely Stupid Simple, Blazing Fast, Get Out of your way immediately Microframework for building Python Web Applications.',
    'long_description': '# Routerling\n\n<img src="https://img.shields.io/badge/coverage-92%25-green" />\n\nA new born baby router on it\'s way to being a web development platform. Routerling is a router\nmultiplexer built with 1 goal in mind.\n\n- Make it stupid simple to build high performance web applications\n\n\n## How?\nFollowing the unix philosophy of be the master of one thing and one thing only - Routerling has only **ONE** API you need to learn - `Router`. The API is also deliberately made\nconsistent across the 3 different supported languages [Golang, Python, Typescript/JavaScript].\n[See Similarities](#similarities)\n\n&nbsp;\n\n## Python\n\n```py\nfrom routerling import Context, HttpRequest, ResponseWriter, Router\nfrom logging import log\n\ndef get_customer_orders(r: HttpRequest, w: ReponseWriter, c: Context):\n    w.headers = "go-go-gadget", ""\n    w.body = \'{customer: {customer_id}, orders: []}\'.format(r.params.get(\'id\'))\n\ndef change_headers(r: HttpRequest, w: ResponseWriter, c: Context):\n    w.headers = "go-go-gadget", "i was included after..."\n\ndef create_customer(r: HttpRequest, w: ResponseWriter, c: Context):\n    print(r.body)\n    w.status = 201\n    w.body = \'{id: 13}\'\n\n\n# register functions to routes\nrouter.BEFORE(\'/*\', lambda req, res, state: print(\'will run before all routes are handled\'))\nrouter.AFTER(\'/v1/customers/*\', change_headers)\nrouter.GET(\'/v1/customers/:id/orders\', get_customer_orders)\nrouter.GET(\'/v1/customers/:id\', lambda req, res, state: log(2, state.abcxyz_variable))\nrouter.POST(\'/v1/customers\', create_customer)\n```\n\n### Serve your application\n```sh\nuvicorn app:router\n```\n\n\n&nbsp;\n\n\n## Request Object\n\n- **request.body**\n    > Body/payload of request if it exists. You can use any `XML, JSON, CSV etc.` library you prefer\n    > to parse `r.body` as you like.\n    ```py\n    # r.body: str\n    body: str = r.body\n    ```\n\n- **request.headers** `header = r.headers.get(\'header-name\')`\n    > All headers sent with the request.\n    ```py\n    # r.headers: dict\n    header = r.headers.get(\'content-type\')\n    ```\n\n- **request.params** `param = r.params.get(\'param-name\')`\n    > Dictionary containing parts of the url that matched your route parameters i.e. `/customers/:id/orders` will\n    > return `{\'id\': 45}` for url `/customers/45/orders`.\n    ```py\n    identifier = r.params.get(\'id\')\n    ```\n\n&nbsp;\n\n## Response Object\n\n- **response.abort**\n    > Signals to routerling that you want to abort a request and ignore all `GET`, `POST`, `PUT etc.` handlers including all\n    > `AFTER` or `BEFORE` hooks from executing. The payload given to abort is used as the response body.\n    > Only calling `w.abort() will not end function execution.` You have to explicitly return from the request handler after using w.abort().\n\n    ```py\n    w.abort(\'This is the body/payload i want to abort with\')\n    return\n\n    # or\n\n    return w.abort(\'This is the body/payload i want to abort with\')  #abort registers then returns None\n    ```\n\n- **response.body**\n    > Used to set payload/body to be sent back to the client. Returning data from a handler function does not do\n    > anything and is not used by routerling. `To send something back to the client use w.body`.\n\n    ```py\n    w.body = b\'my body\'\n    ```\n\n- **response.headers**\n    > Used to set headers to be sent back to the client.\n\n    ```py\n    w.headers = "Content-Type", "application/json"\n    w.headers = ["Authorization", "Bearer myToken"]\n    ```\n\n&nbsp;\n\n## Context Object\n\n- **context.keep**\n    > Used to store values across different request handlers for any given request lifecylce i.e. from the time\n    > a client browser hits your server (request start) to  the time a response is sent back to client (request end).\n    >\n    > &nbsp;\n    >\n    > **Sample Use Case**\n    >\n    > Imagine you want to use the amazing [**jsonschema**](https://pypi.org/project/jsonschema/) library to\n    > validate json request payloads received on every **POST**, **PATCH**, or **PUT** request from your users.\n    > One way to achieve this is to decorate your request handlers and abort the request if the json payload does not\n    > match your schema validation constraints.\n    > \n    > _The code snippet below shows a sample implementation for such a use case for reference_.\n\n\n    ```py\n    from http import HttpStatus as status\n    from json import dumps, loads  # consider using ujson in production apps\n\n    from jsonschema import validate, draft7_format_checker\n    from jsonschema.exceptions import ValidationError\n\n    def expects(schema):\n        def proxy(func):\n            @wraps(func)\n            async def delegate(r: HttpRequest, w: ResponseWriter, c: Context):\n                body = loads(r.body)\n                try: validate(instance=body, schema=schema, format_checker=draft7_format_checker)\n                except ValidationError as exc:\n                    w.status = status.NOT_ACCEPTABLE\n                    w.headers = \'content-type\', \'application/json\'\n                    return w.abort(dumps({\'message\': exc.message}))\n\n                # Here we call Context.keep(\'key\', value) to store values across handlers for the request lifecycle\n                # -------------------------------------------------------------------------------------------------\n                for k,v in body.items(): c.keep(k, v)\n                return await func(r, w, c)\n            return delegate\n        return proxy\n\n\n    @expects({\n        \'type\': \'object\',\n        \'properties\': {\n            \'username\': {\'type\': \'string\'}\n            \'password\': {\'type\': \'string\', \'minLength\': 8}\n        }\n    })\n    async def handler(r: HttpRequest, w: ResponseWriter, c: Context):\n        print(c.username, " you can do this because the @expects :func: calls c.keep(\'username\', value)")\n        print(c.password, " ^^^ same for this")\n        w.body = dumps({\'username\': username, \'password\': password})\n    ```\n\n- **context._application** \n    > Retrieves the root _Routerling_ **app** instance (root router instance), after all you are an\n    > adult when it comes to coding ;-)\n    >\n    > Newly introduced in routerling **version 0.2.3**\n\n&nbsp;\n\n&nbsp;\n\n# Socket Connections\n\n> Implementation &amp; Documentation coming soon\n',
    'author': 'Raymond Ortserga',
    'author_email': 'ortserga@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
