flask-toolkits


Nameflask-toolkits JSON
Version 0.7.10 PyPI version JSON
download
home_pagehttps://github.com/Danangjoyoo/flask-toolkits
SummaryFlask toolkits to boost your development and simplify flask, its featured with AutoSwagger
upload_time2023-04-10 12:14:37
maintainer
docs_urlNone
authordanangjoyoo (Agus Danangjoyo)
requires_python
license
keywords flask middleware http request response swagger openapi toolkit
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Flask Toolkits
[![Downloads](https://static.pepy.tech/personalized-badge/flask-toolkits?period=total&units=international_system&left_color=black&right_color=blue&left_text=Downloads)](https://pepy.tech/project/flask-toolkits)


## Installation
```
pip install flask-toolkits
```

## Description
Flask toolkits implements and provides several features from `FastAPI` like:
- Automatic API documentation (define the function and we'll generate the `swagger`/`openapi` spec for you)
- Passing parameters through `view`/`router` function which is unable in `Flask` before
- Easy Middleware setup
- Parameters and schema validation using `Pydantic`
- Response classes that could return any type of data without worried to get error
- much more..


## Changelogs
- v0.0
    - First Upload
- v0.1
    - Integration with [flask-http-middleware](https://pypi.org/project/flask-http-middleware)
    - [pydantic](https://pypi.org/project/pydantic) support for JSON arguments and validation
    - Multiple response type generator
    - Added `JSONResponse` class to replace `jsonify` roles in send dictionary data with encoding improvements.
- v0.2
    - Supported enumeration API documentation
    - Added support for type hint from `typing`'s generic (ex: `Optional`, `Union`, `List`)
    - Fixed input parameter validations
- v0.3
    - Support `File` and `Form` input parameters validation and automatic swagger.
    - Added constraint feature for parameters (ex: limit, max/min length, greater/less than, equals than etc)
- v0.4
    - Support `Authorization` header in openapi spec.
    - Added `Authorization` processing function for security and can be used as `login` or `auth`.
- v0.5
    - Support `add_url_rule` and `route` for endpoint definition
    - Support auto swagger for multiple methods in a single endpoints
- v0.6
    - Support `alias` on endpoint parameters (path, query, header, etc) to enable
        non-pythonic terms of parameter names
- v0.7
    - support response structure generator function to helps creating the response schema and examples

## Key Tools inside this `toolkit`
- Automatic API documentation (`swagger`/`openapi`)
- Request-Response direct HTTP middleware (`flask-http-middleware`)
- Automatic parameters validation (`pydantic`)
- Response generator (JSON, Plain Text, HTML)

## Automatic Parameters Validation
The original `Blueprints` class from `flask` can't insert most of arguments inside endpoint.
Here our `APIRouter` allows you to have arguments inside your endpoint
```
from typing import Optional
from flask_toolkits import APIRouter, Body, Header, Query
from flask_toolkits.responses import JSONResponse


router = APIRouter("email", import_name=__name__, static_folder="/routers/email", url_prefix="/email")


@router.post("/read", tags=["Email Router"])
def get_email(
    id: int,
    name: Optional[str],
):
    return JSONResponse({"id": id, "name": name})

```

## Automatic API Documentation
Here our `APIRouter` allows you to auto-documenting your endpoint through `AutoSwagger`.
Define the new router using `APIRouter` class, lets put it in another pyfile

`email_view.py`
```
from typing import Optional
from flask_toolkits import APIRouter, Body, Header, Query
from flask_toolkits.responses import JSONResponse


router = APIRouter("email", import_name=__name__, static_folder="/routers/email", url_prefix="/email")


@router.post("/read", tags=["Email Router"])
def get_email(
    id: int = Body(),
    name: Optional[str] = Body(None),
    token: int = Header(),
    race: Optional[str] = Query(None)
):
    return JSONResponse({"id":id, "name": name})
```

`main.py`
```
from flask import Flask
from flask_toolkits import AutoSwagger

from email_view import router as email_router


app = Flask(__name__)

auto_swagger = AutoSwagger()

app.register_blueprint(email_router)
app.register_blueprint(auto_swagger)


if __name__ == "__main__":
    app.run()
```

then you can go to `http://localhost:5000/docs` and you will found you router is already documented

![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/auto1.png?raw=true)

---

## Supported Field Parameters
`flask-toolkits` provide multiple field parameters such as `Header`, `Query`, `Body`, `Path`, `File`, `Form`

---

## Easy Security Scheme Setup and Documentation
`flask-toolkits` helps you to define your security scheme for authorization easier than before. In advance this also give you automated documentation.

### Basic Usage
lets assume you have your own bearer security schema. You just have to create a new instance of `HTTPBearerSecurity()` to enable automatic documentation on it.
```
from flask import request
from flask_toolkits import APIRouter
from flask_toolkits.security import HTTPBearerSecurity

router = APIRouter("api", __name__)

@router.get("/home", security=HTTPBearerSecurity())
def home(message: str):
    if my_security_scheme(request):
        return JSONResponse({"message": message})
    return JSONResponse({"message": "invalid authorization"})
```

this is how it looks like
![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/auth0.png?raw=true)

on you clicked it
![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/auth1.png?raw=true)

### Define your own security scheme
If you want to define your own security scheme you can follow below guidance
```
from flask import request
from flask_toolkits import APIRouter
from flask_toolkits.security import HTTPBearerSecurity

class JWTBearer(HTTPBearerSecurity):
    def __init__(self):
        super().__init__()

    def __call__(self, req):
        data = self.get_authorization_data(req)
        if data != "abcdefghij":
            raise Exception("This is not good")
        return req

router = APIRouter("api", __name__)

@router.get("/home", security=JWTBearer())
def home(message: str):
    if my_security_scheme(request):
        return JSONResponse({"message": message})
    return JSONResponse({"message": "invalid authorization"})

```
Overriding `__call__` method inside the subclass would define your security schema for the routers that are using your security scheme

---

## Define to all endpoints in a router
Just pass it to `APIRouter` and all its endpoint will use that security scheme!
```
router_with_bearer = APIRouter("api", __name__, security=JWTBearer())
```
but don't worries! You can also override it by just defining in the router decorator!
```
@router_with_bearer.get("/home", security=AnotherBearerSecurity())
def home():
    return {"message": "hello"}
```

---

## Parameter Alias
In case you have non-pythonic terms with unicode character (-, +, _, =) for your paramter names, you can apply the `alias` into the parameters easily
```
@app.get("/test-alias")
def test_alias(
    apikey: str = Header(alias="x-api-key")
):
    return JSONResponse({"apikey": apikey})
```
here you will also have your swagger is defined with that `alias`
![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/alias1.png?raw=true)

---

## Response Structure
Creating the response example and schema easily by just defining the class and pass it to `create_response_example` or accessing `as_response()` from `BaseSchema` objects
```
from flask_toolkits.responses import response_json_example


class PersonResponse(BaseSchema):
    name: str
    age: int

class FailedResponse(BaseSchema):
    message: str
    error_code: int

@router.route(
    '/hello_world/<first>/<int:number>', tags=["My Hello"],
    responses={
        200: response_json_example(PersonResponse(name="Alex", age=20)),
        400: FailedResponse(message="Data not found", error_code=101).as_response()
    },
)
def hello_world(
    name: str = Query(),
    age: int = Query()
):
    resp = {
        "name": name,
        "age": age
    }

    return JSONResponse(resp)
```
![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/response_example1.png?raw=true)
![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/response_schema1.png?raw=true)

---

## Multiple HTTP Methods in a single endpoint
`add_url_rule` and `route` method for `Flask`'s App or `Blueprints` object are now supported. This also allows you to have multiple HTTP methods in a single endpoint function
```
@app.route("/test-multiple-method", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
def go_multi_method(
    name: str = Body()
):
    return JSONResponse({"result": name})
```
Here you will get `null` if you hit it using `GET` but you'll get the value on you hit with other methods that support `Body`. You won't loose your validation since it only applied for methods that support that kind of params.

---

## Request-Response direct HTTP middleware
```
import time
from flask import Flask
from flask_toolkits.middleware import MiddlewareManager, BaseHTTPMiddleware

app = Flask(__name__)

class MetricsMiddleware(BaseHTTPMiddleware):
    def __init__(self):
        super().__init__()

    def dispatch(self, request, call_next):
        t0 = time.time()
        response = call_next(request)
        response_time = time.time()-t0
        response.headers.add("response_time", response_time)
        return response

app.wsgi_app = MiddlewareManager(app)
app.wsgi_app.add_middleware(MetricsMiddleware)

@app.get("/health")
def health():
    return {"message":"I'm healthy"}
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Danangjoyoo/flask-toolkits",
    "name": "flask-toolkits",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "flask,middleware,http,request,response,swagger,openapi,toolkit",
    "author": "danangjoyoo (Agus Danangjoyo)",
    "author_email": "<agus.danangjoyo.blog@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/33/0d/665a8e57d4f6d94e14095a852c5e3e3b8d49178d06f3da8121d084389615/flask-toolkits-0.7.10.tar.gz",
    "platform": null,
    "description": "# Flask Toolkits\n[![Downloads](https://static.pepy.tech/personalized-badge/flask-toolkits?period=total&units=international_system&left_color=black&right_color=blue&left_text=Downloads)](https://pepy.tech/project/flask-toolkits)\n\n\n## Installation\n```\npip install flask-toolkits\n```\n\n## Description\nFlask toolkits implements and provides several features from `FastAPI` like:\n- Automatic API documentation (define the function and we'll generate the `swagger`/`openapi` spec for you)\n- Passing parameters through `view`/`router` function which is unable in `Flask` before\n- Easy Middleware setup\n- Parameters and schema validation using `Pydantic`\n- Response classes that could return any type of data without worried to get error\n- much more..\n\n\n## Changelogs\n- v0.0\n    - First Upload\n- v0.1\n    - Integration with [flask-http-middleware](https://pypi.org/project/flask-http-middleware)\n    - [pydantic](https://pypi.org/project/pydantic) support for JSON arguments and validation\n    - Multiple response type generator\n    - Added `JSONResponse` class to replace `jsonify` roles in send dictionary data with encoding improvements.\n- v0.2\n    - Supported enumeration API documentation\n    - Added support for type hint from `typing`'s generic (ex: `Optional`, `Union`, `List`)\n    - Fixed input parameter validations\n- v0.3\n    - Support `File` and `Form` input parameters validation and automatic swagger.\n    - Added constraint feature for parameters (ex: limit, max/min length, greater/less than, equals than etc)\n- v0.4\n    - Support `Authorization` header in openapi spec.\n    - Added `Authorization` processing function for security and can be used as `login` or `auth`.\n- v0.5\n    - Support `add_url_rule` and `route` for endpoint definition\n    - Support auto swagger for multiple methods in a single endpoints\n- v0.6\n    - Support `alias` on endpoint parameters (path, query, header, etc) to enable\n        non-pythonic terms of parameter names\n- v0.7\n    - support response structure generator function to helps creating the response schema and examples\n\n## Key Tools inside this `toolkit`\n- Automatic API documentation (`swagger`/`openapi`)\n- Request-Response direct HTTP middleware (`flask-http-middleware`)\n- Automatic parameters validation (`pydantic`)\n- Response generator (JSON, Plain Text, HTML)\n\n## Automatic Parameters Validation\nThe original `Blueprints` class from `flask` can't insert most of arguments inside endpoint.\nHere our `APIRouter` allows you to have arguments inside your endpoint\n```\nfrom typing import Optional\nfrom flask_toolkits import APIRouter, Body, Header, Query\nfrom flask_toolkits.responses import JSONResponse\n\n\nrouter = APIRouter(\"email\", import_name=__name__, static_folder=\"/routers/email\", url_prefix=\"/email\")\n\n\n@router.post(\"/read\", tags=[\"Email Router\"])\ndef get_email(\n    id: int,\n    name: Optional[str],\n):\n    return JSONResponse({\"id\": id, \"name\": name})\n\n```\n\n## Automatic API Documentation\nHere our `APIRouter` allows you to auto-documenting your endpoint through `AutoSwagger`.\nDefine the new router using `APIRouter` class, lets put it in another pyfile\n\n`email_view.py`\n```\nfrom typing import Optional\nfrom flask_toolkits import APIRouter, Body, Header, Query\nfrom flask_toolkits.responses import JSONResponse\n\n\nrouter = APIRouter(\"email\", import_name=__name__, static_folder=\"/routers/email\", url_prefix=\"/email\")\n\n\n@router.post(\"/read\", tags=[\"Email Router\"])\ndef get_email(\n    id: int = Body(),\n    name: Optional[str] = Body(None),\n    token: int = Header(),\n    race: Optional[str] = Query(None)\n):\n    return JSONResponse({\"id\":id, \"name\": name})\n```\n\n`main.py`\n```\nfrom flask import Flask\nfrom flask_toolkits import AutoSwagger\n\nfrom email_view import router as email_router\n\n\napp = Flask(__name__)\n\nauto_swagger = AutoSwagger()\n\napp.register_blueprint(email_router)\napp.register_blueprint(auto_swagger)\n\n\nif __name__ == \"__main__\":\n    app.run()\n```\n\nthen you can go to `http://localhost:5000/docs` and you will found you router is already documented\n\n![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/auto1.png?raw=true)\n\n---\n\n## Supported Field Parameters\n`flask-toolkits` provide multiple field parameters such as `Header`, `Query`, `Body`, `Path`, `File`, `Form`\n\n---\n\n## Easy Security Scheme Setup and Documentation\n`flask-toolkits` helps you to define your security scheme for authorization easier than before. In advance this also give you automated documentation.\n\n### Basic Usage\nlets assume you have your own bearer security schema. You just have to create a new instance of `HTTPBearerSecurity()` to enable automatic documentation on it.\n```\nfrom flask import request\nfrom flask_toolkits import APIRouter\nfrom flask_toolkits.security import HTTPBearerSecurity\n\nrouter = APIRouter(\"api\", __name__)\n\n@router.get(\"/home\", security=HTTPBearerSecurity())\ndef home(message: str):\n    if my_security_scheme(request):\n        return JSONResponse({\"message\": message})\n    return JSONResponse({\"message\": \"invalid authorization\"})\n```\n\nthis is how it looks like\n![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/auth0.png?raw=true)\n\non you clicked it\n![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/auth1.png?raw=true)\n\n### Define your own security scheme\nIf you want to define your own security scheme you can follow below guidance\n```\nfrom flask import request\nfrom flask_toolkits import APIRouter\nfrom flask_toolkits.security import HTTPBearerSecurity\n\nclass JWTBearer(HTTPBearerSecurity):\n    def __init__(self):\n        super().__init__()\n\n    def __call__(self, req):\n        data = self.get_authorization_data(req)\n        if data != \"abcdefghij\":\n            raise Exception(\"This is not good\")\n        return req\n\nrouter = APIRouter(\"api\", __name__)\n\n@router.get(\"/home\", security=JWTBearer())\ndef home(message: str):\n    if my_security_scheme(request):\n        return JSONResponse({\"message\": message})\n    return JSONResponse({\"message\": \"invalid authorization\"})\n\n```\nOverriding `__call__` method inside the subclass would define your security schema for the routers that are using your security scheme\n\n---\n\n## Define to all endpoints in a router\nJust pass it to `APIRouter` and all its endpoint will use that security scheme!\n```\nrouter_with_bearer = APIRouter(\"api\", __name__, security=JWTBearer())\n```\nbut don't worries! You can also override it by just defining in the router decorator!\n```\n@router_with_bearer.get(\"/home\", security=AnotherBearerSecurity())\ndef home():\n    return {\"message\": \"hello\"}\n```\n\n---\n\n## Parameter Alias\nIn case you have non-pythonic terms with unicode character (-, +, _, =) for your paramter names, you can apply the `alias` into the parameters easily\n```\n@app.get(\"/test-alias\")\ndef test_alias(\n    apikey: str = Header(alias=\"x-api-key\")\n):\n    return JSONResponse({\"apikey\": apikey})\n```\nhere you will also have your swagger is defined with that `alias`\n![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/alias1.png?raw=true)\n\n---\n\n## Response Structure\nCreating the response example and schema easily by just defining the class and pass it to `create_response_example` or accessing `as_response()` from `BaseSchema` objects\n```\nfrom flask_toolkits.responses import response_json_example\n\n\nclass PersonResponse(BaseSchema):\n    name: str\n    age: int\n\nclass FailedResponse(BaseSchema):\n    message: str\n    error_code: int\n\n@router.route(\n    '/hello_world/<first>/<int:number>', tags=[\"My Hello\"],\n    responses={\n        200: response_json_example(PersonResponse(name=\"Alex\", age=20)),\n        400: FailedResponse(message=\"Data not found\", error_code=101).as_response()\n    },\n)\ndef hello_world(\n    name: str = Query(),\n    age: int = Query()\n):\n    resp = {\n        \"name\": name,\n        \"age\": age\n    }\n\n    return JSONResponse(resp)\n```\n![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/response_example1.png?raw=true)\n![alt text](https://github.com/Danangjoyoo/flask-toolkits/blob/main/docs/response_schema1.png?raw=true)\n\n---\n\n## Multiple HTTP Methods in a single endpoint\n`add_url_rule` and `route` method for `Flask`'s App or `Blueprints` object are now supported. This also allows you to have multiple HTTP methods in a single endpoint function\n```\n@app.route(\"/test-multiple-method\", methods=[\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\"])\ndef go_multi_method(\n    name: str = Body()\n):\n    return JSONResponse({\"result\": name})\n```\nHere you will get `null` if you hit it using `GET` but you'll get the value on you hit with other methods that support `Body`. You won't loose your validation since it only applied for methods that support that kind of params.\n\n---\n\n## Request-Response direct HTTP middleware\n```\nimport time\nfrom flask import Flask\nfrom flask_toolkits.middleware import MiddlewareManager, BaseHTTPMiddleware\n\napp = Flask(__name__)\n\nclass MetricsMiddleware(BaseHTTPMiddleware):\n    def __init__(self):\n        super().__init__()\n\n    def dispatch(self, request, call_next):\n        t0 = time.time()\n        response = call_next(request)\n        response_time = time.time()-t0\n        response.headers.add(\"response_time\", response_time)\n        return response\n\napp.wsgi_app = MiddlewareManager(app)\napp.wsgi_app.add_middleware(MetricsMiddleware)\n\n@app.get(\"/health\")\ndef health():\n    return {\"message\":\"I'm healthy\"}\n```\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Flask toolkits to boost your development and simplify flask, its featured with AutoSwagger",
    "version": "0.7.10",
    "split_keywords": [
        "flask",
        "middleware",
        "http",
        "request",
        "response",
        "swagger",
        "openapi",
        "toolkit"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3d39f885d5c9365d8786d61d4ecb3cf26accdbc6be128ec47baa68f3451511af",
                "md5": "b346859a861de39c5506c73ce8ea4941",
                "sha256": "95eec867fc900b27a86d84d616f2cf5eda9b622dce7095d334a6626ce4a87e76"
            },
            "downloads": -1,
            "filename": "flask_toolkits-0.7.10-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b346859a861de39c5506c73ce8ea4941",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 1020490,
            "upload_time": "2023-04-10T12:14:33",
            "upload_time_iso_8601": "2023-04-10T12:14:33.444353Z",
            "url": "https://files.pythonhosted.org/packages/3d/39/f885d5c9365d8786d61d4ecb3cf26accdbc6be128ec47baa68f3451511af/flask_toolkits-0.7.10-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "330d665a8e57d4f6d94e14095a852c5e3e3b8d49178d06f3da8121d084389615",
                "md5": "6c899d114766bf4bf000f834fc88f536",
                "sha256": "82519db56181ab450f23f1650f4a04e17b268419fce1caa8448c199848dd8fdc"
            },
            "downloads": -1,
            "filename": "flask-toolkits-0.7.10.tar.gz",
            "has_sig": false,
            "md5_digest": "6c899d114766bf4bf000f834fc88f536",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 1014427,
            "upload_time": "2023-04-10T12:14:37",
            "upload_time_iso_8601": "2023-04-10T12:14:37.418523Z",
            "url": "https://files.pythonhosted.org/packages/33/0d/665a8e57d4f6d94e14095a852c5e3e3b8d49178d06f3da8121d084389615/flask-toolkits-0.7.10.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-04-10 12:14:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "Danangjoyoo",
    "github_project": "flask-toolkits",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "flask-toolkits"
}
        
Elapsed time: 0.11561s