summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-04-11 11:32:34 +0000
committerCoprDistGit <infra@openeuler.org>2023-04-11 11:32:34 +0000
commit5fd7d44a402a178892efd9c34906dadb879cedf8 (patch)
tree9ece53979f81474ca77b96d94d3b129097b99dce
parent75a650f0f61858101cd837fa6db65942a1c01ec7 (diff)
automatic import of python-flask-pydantic
-rw-r--r--.gitignore1
-rw-r--r--python-flask-pydantic.spec782
-rw-r--r--sources1
3 files changed, 784 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..bc96ef6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/Flask-Pydantic-0.11.0.tar.gz
diff --git a/python-flask-pydantic.spec b/python-flask-pydantic.spec
new file mode 100644
index 0000000..e2deb1e
--- /dev/null
+++ b/python-flask-pydantic.spec
@@ -0,0 +1,782 @@
+%global _empty_manifest_terminate_build 0
+Name: python-Flask-Pydantic
+Version: 0.11.0
+Release: 1
+Summary: Flask extension for integration with Pydantic library
+License: MIT
+URL: https://github.com/bauerji/flask_pydantic.git
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/a8/f4/34f688e8a15c1efc7caede3cb9f81f9824e2daccd4b41436a28b2cb5c518/Flask-Pydantic-0.11.0.tar.gz
+BuildArch: noarch
+
+Requires: python3-Flask
+Requires: python3-pydantic
+
+%description
+### Additional `validate` arguments
+- Success response status code can be modified via `on_success_status` parameter of `validate` decorator.
+- `response_many` parameter set to `True` enables serialization of multiple models (route function should therefore return iterable of models).
+- `request_body_many` parameter set to `False` analogically enables serialization of multiple models inside of the root level of request body. If the request body doesn't contain an array of objects `400` response is returned,
+- `get_json_params` - parameters to be passed to [`flask.Request.get_json`](https://tedboy.github.io/flask/generated/generated/flask.Request.get_json.html) function
+- If validation fails, `400` response is returned with failure explanation.
+For more details see in-code docstring or example app.
+## Usage
+### Example 1: Query parameters only
+Simply use `validate` decorator on route function.
+```python
+from typing import Optional
+from flask import Flask, request
+from pydantic import BaseModel
+from flask_pydantic import validate
+app = Flask("flask_pydantic_app")
+class QueryModel(BaseModel):
+ age: int
+class ResponseModel(BaseModel):
+ id: int
+ age: int
+ name: str
+ nickname: Optional[str]
+# Example 1: query parameters only
+@app.route("/", methods=["GET"])
+@validate()
+def get(query: QueryModel):
+ age = query.age
+ return ResponseModel(
+ age=age,
+ id=0, name="abc", nickname="123"
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+- `age` query parameter is a required `int`
+ - `curl --location --request GET 'http://127.0.0.1:5000/'`
+ - if none is provided the response contains:
+ ```json
+ {
+ "validation_error": {
+ "query_params": [
+ {
+ "loc": ["age"],
+ "msg": "field required",
+ "type": "value_error.missing"
+ }
+ ]
+ }
+ }
+ ```
+ - for incompatible type (e. g. string `/?age=not_a_number`)
+ - `curl --location --request GET 'http://127.0.0.1:5000/?age=abc'`
+ ```json
+ {
+ "validation_error": {
+ "query_params": [
+ {
+ "loc": ["age"],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+ }
+ }
+ ```
+- likewise for body parameters
+- example call with valid parameters:
+ `curl --location --request GET 'http://127.0.0.1:5000/?age=20'`
+-> `{"id": 0, "age": 20, "name": "abc", "nickname": "123"}`
+### Example 2: URL path parameter
+```python
+@app.route("/character/<character_id>/", methods=["GET"])
+@validate()
+def get_character(character_id: int):
+ characters = [
+ ResponseModel(id=1, age=95, name="Geralt", nickname="White Wolf"),
+ ResponseModel(id=2, age=45, name="Triss Merigold", nickname="sorceress"),
+ ResponseModel(id=3, age=42, name="Julian Alfred Pankratz", nickname="Jaskier"),
+ ResponseModel(id=4, age=101, name="Yennefer", nickname="Yenn"),
+ ]
+ try:
+ return characters[character_id]
+ except IndexError:
+ return {"error": "Not found"}, 400
+```
+### Example 3: Request body only
+```python
+class RequestBodyModel(BaseModel):
+ name: str
+ nickname: Optional[str]
+# Example2: request body only
+@app.route("/", methods=["POST"])
+@validate()
+def post(body: RequestBodyModel):
+ name = body.name
+ nickname = body.nickname
+ return ResponseModel(
+ name=name, nickname=nickname,id=0, age=1000
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Example 4: BOTH query paramaters and request body
+```python
+# Example 3: both query paramters and request body
+@app.route("/both", methods=["POST"])
+@validate()
+def get_and_post(body: RequestBodyModel,query: QueryModel):
+ name = body.name # From request body
+ nickname = body.nickname # From request body
+ age = query.age # from query parameters
+ return ResponseModel(
+ age=age, name=name, nickname=nickname,
+ id=0
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Example 5: Request form-data only
+```python
+class RequestFormDataModel(BaseModel):
+ name: str
+ nickname: Optional[str]
+# Example2: request body only
+@app.route("/", methods=["POST"])
+@validate()
+def post(form: RequestFormDataModel):
+ name = form.name
+ nickname = form.nickname
+ return ResponseModel(
+ name=name, nickname=nickname,id=0, age=1000
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Modify response status code
+The default success status code is `200`. It can be modified in two ways
+- in return statement
+```python
+# necessary imports, app and models definition
+@app.route("/", methods=["POST"])
+@validate(body=BodyModel, query=QueryModel)
+def post():
+ return ResponseModel(
+ id=id_,
+ age=request.query_params.age,
+ name=request.body_params.name,
+ nickname=request.body_params.nickname,
+ ), 201
+```
+- in `validate` decorator
+```python
+@app.route("/", methods=["POST"])
+@validate(body=BodyModel, query=QueryModel, on_success_status=201)
+def post():
+```
+Status code in case of validation error can be modified using `FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE` flask configuration variable.
+### Using the decorated function `kwargs`
+Instead of passing `body` and `query` to `validate`, it is possible to directly
+defined them by using type hinting in the decorated function.
+```python
+# necessary imports, app and models definition
+@app.route("/", methods=["POST"])
+@validate()
+def post(body: BodyModel, query: QueryModel):
+ return ResponseModel(
+ id=id_,
+ age=query.age,
+ name=body.name,
+ nickname=body.nickname,
+ )
+```
+This way, the parsed data will be directly available in `body` and `query`.
+Furthermore, your IDE will be able to correctly type them.
+### Model aliases
+Pydantic's [alias feature](https://pydantic-docs.helpmanual.io/usage/model_config/#alias-generator) is natively supported for query and body models.
+To use aliases in response modify response model
+```python
+def modify_key(text: str) -> str:
+ # do whatever you want with model keys
+ return text
+class MyModel(BaseModel):
+ class Config:
+ alias_generator = modify_key
+ allow_population_by_field_name = True
+```
+and set `response_by_alias=True` in `validate` decorator
+```
+@app.route(...)
+@validate(response_by_alias=True)
+def my_route():
+ return MyModel(...)
+```
+### Example app
+For more complete examples see [example application](https://github.com/bauerji/flask_pydantic/tree/master/example_app).
+### Configuration
+The behaviour can be configured using flask's application config
+`FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE` - response status code after validation error (defaults to `400`)
+Additionally, you can set `FLASK_PYDANTIC_VALIDATION_ERROR_RAISE` to `True` to cause
+`flask_pydantic.ValidationError` to be raised with either `body_params`,
+`form_params`, `path_params`, or `query_params` set as a list of error
+dictionaries. You can use `flask.Flask.register_error_handler` to catch that
+exception and fully customize the output response for a validation error.
+## Contributing
+Feature requests and pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
+- clone repository
+ ```bash
+ git clone https://github.com/bauerji/flask_pydantic.git
+ cd flask_pydantic
+ ```
+- create virtual environment and activate it
+ ```bash
+ python3 -m venv venv
+ source venv/bin/activate
+ ```
+- install development requirements
+ ```bash
+ python3 -m pip install -r requirements/test.pip
+ ```
+- checkout new branch and make your desired changes (don't forget to update tests)
+ ```bash
+ git checkout -b <your_branch_name>
+ ```
+- run tests
+ ```bash
+ python3 -m pytest
+ ```
+- if tests fails on Black tests, make sure You have your code compliant with style of [Black formatter](https://github.com/psf/black)
+- push your changes and create a pull request to master branch
+## TODOs:
+- header request parameters
+- cookie request parameters
+
+%package -n python3-Flask-Pydantic
+Summary: Flask extension for integration with Pydantic library
+Provides: python-Flask-Pydantic
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-Flask-Pydantic
+### Additional `validate` arguments
+- Success response status code can be modified via `on_success_status` parameter of `validate` decorator.
+- `response_many` parameter set to `True` enables serialization of multiple models (route function should therefore return iterable of models).
+- `request_body_many` parameter set to `False` analogically enables serialization of multiple models inside of the root level of request body. If the request body doesn't contain an array of objects `400` response is returned,
+- `get_json_params` - parameters to be passed to [`flask.Request.get_json`](https://tedboy.github.io/flask/generated/generated/flask.Request.get_json.html) function
+- If validation fails, `400` response is returned with failure explanation.
+For more details see in-code docstring or example app.
+## Usage
+### Example 1: Query parameters only
+Simply use `validate` decorator on route function.
+```python
+from typing import Optional
+from flask import Flask, request
+from pydantic import BaseModel
+from flask_pydantic import validate
+app = Flask("flask_pydantic_app")
+class QueryModel(BaseModel):
+ age: int
+class ResponseModel(BaseModel):
+ id: int
+ age: int
+ name: str
+ nickname: Optional[str]
+# Example 1: query parameters only
+@app.route("/", methods=["GET"])
+@validate()
+def get(query: QueryModel):
+ age = query.age
+ return ResponseModel(
+ age=age,
+ id=0, name="abc", nickname="123"
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+- `age` query parameter is a required `int`
+ - `curl --location --request GET 'http://127.0.0.1:5000/'`
+ - if none is provided the response contains:
+ ```json
+ {
+ "validation_error": {
+ "query_params": [
+ {
+ "loc": ["age"],
+ "msg": "field required",
+ "type": "value_error.missing"
+ }
+ ]
+ }
+ }
+ ```
+ - for incompatible type (e. g. string `/?age=not_a_number`)
+ - `curl --location --request GET 'http://127.0.0.1:5000/?age=abc'`
+ ```json
+ {
+ "validation_error": {
+ "query_params": [
+ {
+ "loc": ["age"],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+ }
+ }
+ ```
+- likewise for body parameters
+- example call with valid parameters:
+ `curl --location --request GET 'http://127.0.0.1:5000/?age=20'`
+-> `{"id": 0, "age": 20, "name": "abc", "nickname": "123"}`
+### Example 2: URL path parameter
+```python
+@app.route("/character/<character_id>/", methods=["GET"])
+@validate()
+def get_character(character_id: int):
+ characters = [
+ ResponseModel(id=1, age=95, name="Geralt", nickname="White Wolf"),
+ ResponseModel(id=2, age=45, name="Triss Merigold", nickname="sorceress"),
+ ResponseModel(id=3, age=42, name="Julian Alfred Pankratz", nickname="Jaskier"),
+ ResponseModel(id=4, age=101, name="Yennefer", nickname="Yenn"),
+ ]
+ try:
+ return characters[character_id]
+ except IndexError:
+ return {"error": "Not found"}, 400
+```
+### Example 3: Request body only
+```python
+class RequestBodyModel(BaseModel):
+ name: str
+ nickname: Optional[str]
+# Example2: request body only
+@app.route("/", methods=["POST"])
+@validate()
+def post(body: RequestBodyModel):
+ name = body.name
+ nickname = body.nickname
+ return ResponseModel(
+ name=name, nickname=nickname,id=0, age=1000
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Example 4: BOTH query paramaters and request body
+```python
+# Example 3: both query paramters and request body
+@app.route("/both", methods=["POST"])
+@validate()
+def get_and_post(body: RequestBodyModel,query: QueryModel):
+ name = body.name # From request body
+ nickname = body.nickname # From request body
+ age = query.age # from query parameters
+ return ResponseModel(
+ age=age, name=name, nickname=nickname,
+ id=0
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Example 5: Request form-data only
+```python
+class RequestFormDataModel(BaseModel):
+ name: str
+ nickname: Optional[str]
+# Example2: request body only
+@app.route("/", methods=["POST"])
+@validate()
+def post(form: RequestFormDataModel):
+ name = form.name
+ nickname = form.nickname
+ return ResponseModel(
+ name=name, nickname=nickname,id=0, age=1000
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Modify response status code
+The default success status code is `200`. It can be modified in two ways
+- in return statement
+```python
+# necessary imports, app and models definition
+@app.route("/", methods=["POST"])
+@validate(body=BodyModel, query=QueryModel)
+def post():
+ return ResponseModel(
+ id=id_,
+ age=request.query_params.age,
+ name=request.body_params.name,
+ nickname=request.body_params.nickname,
+ ), 201
+```
+- in `validate` decorator
+```python
+@app.route("/", methods=["POST"])
+@validate(body=BodyModel, query=QueryModel, on_success_status=201)
+def post():
+```
+Status code in case of validation error can be modified using `FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE` flask configuration variable.
+### Using the decorated function `kwargs`
+Instead of passing `body` and `query` to `validate`, it is possible to directly
+defined them by using type hinting in the decorated function.
+```python
+# necessary imports, app and models definition
+@app.route("/", methods=["POST"])
+@validate()
+def post(body: BodyModel, query: QueryModel):
+ return ResponseModel(
+ id=id_,
+ age=query.age,
+ name=body.name,
+ nickname=body.nickname,
+ )
+```
+This way, the parsed data will be directly available in `body` and `query`.
+Furthermore, your IDE will be able to correctly type them.
+### Model aliases
+Pydantic's [alias feature](https://pydantic-docs.helpmanual.io/usage/model_config/#alias-generator) is natively supported for query and body models.
+To use aliases in response modify response model
+```python
+def modify_key(text: str) -> str:
+ # do whatever you want with model keys
+ return text
+class MyModel(BaseModel):
+ class Config:
+ alias_generator = modify_key
+ allow_population_by_field_name = True
+```
+and set `response_by_alias=True` in `validate` decorator
+```
+@app.route(...)
+@validate(response_by_alias=True)
+def my_route():
+ return MyModel(...)
+```
+### Example app
+For more complete examples see [example application](https://github.com/bauerji/flask_pydantic/tree/master/example_app).
+### Configuration
+The behaviour can be configured using flask's application config
+`FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE` - response status code after validation error (defaults to `400`)
+Additionally, you can set `FLASK_PYDANTIC_VALIDATION_ERROR_RAISE` to `True` to cause
+`flask_pydantic.ValidationError` to be raised with either `body_params`,
+`form_params`, `path_params`, or `query_params` set as a list of error
+dictionaries. You can use `flask.Flask.register_error_handler` to catch that
+exception and fully customize the output response for a validation error.
+## Contributing
+Feature requests and pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
+- clone repository
+ ```bash
+ git clone https://github.com/bauerji/flask_pydantic.git
+ cd flask_pydantic
+ ```
+- create virtual environment and activate it
+ ```bash
+ python3 -m venv venv
+ source venv/bin/activate
+ ```
+- install development requirements
+ ```bash
+ python3 -m pip install -r requirements/test.pip
+ ```
+- checkout new branch and make your desired changes (don't forget to update tests)
+ ```bash
+ git checkout -b <your_branch_name>
+ ```
+- run tests
+ ```bash
+ python3 -m pytest
+ ```
+- if tests fails on Black tests, make sure You have your code compliant with style of [Black formatter](https://github.com/psf/black)
+- push your changes and create a pull request to master branch
+## TODOs:
+- header request parameters
+- cookie request parameters
+
+%package help
+Summary: Development documents and examples for Flask-Pydantic
+Provides: python3-Flask-Pydantic-doc
+%description help
+### Additional `validate` arguments
+- Success response status code can be modified via `on_success_status` parameter of `validate` decorator.
+- `response_many` parameter set to `True` enables serialization of multiple models (route function should therefore return iterable of models).
+- `request_body_many` parameter set to `False` analogically enables serialization of multiple models inside of the root level of request body. If the request body doesn't contain an array of objects `400` response is returned,
+- `get_json_params` - parameters to be passed to [`flask.Request.get_json`](https://tedboy.github.io/flask/generated/generated/flask.Request.get_json.html) function
+- If validation fails, `400` response is returned with failure explanation.
+For more details see in-code docstring or example app.
+## Usage
+### Example 1: Query parameters only
+Simply use `validate` decorator on route function.
+```python
+from typing import Optional
+from flask import Flask, request
+from pydantic import BaseModel
+from flask_pydantic import validate
+app = Flask("flask_pydantic_app")
+class QueryModel(BaseModel):
+ age: int
+class ResponseModel(BaseModel):
+ id: int
+ age: int
+ name: str
+ nickname: Optional[str]
+# Example 1: query parameters only
+@app.route("/", methods=["GET"])
+@validate()
+def get(query: QueryModel):
+ age = query.age
+ return ResponseModel(
+ age=age,
+ id=0, name="abc", nickname="123"
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+- `age` query parameter is a required `int`
+ - `curl --location --request GET 'http://127.0.0.1:5000/'`
+ - if none is provided the response contains:
+ ```json
+ {
+ "validation_error": {
+ "query_params": [
+ {
+ "loc": ["age"],
+ "msg": "field required",
+ "type": "value_error.missing"
+ }
+ ]
+ }
+ }
+ ```
+ - for incompatible type (e. g. string `/?age=not_a_number`)
+ - `curl --location --request GET 'http://127.0.0.1:5000/?age=abc'`
+ ```json
+ {
+ "validation_error": {
+ "query_params": [
+ {
+ "loc": ["age"],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+ }
+ }
+ ```
+- likewise for body parameters
+- example call with valid parameters:
+ `curl --location --request GET 'http://127.0.0.1:5000/?age=20'`
+-> `{"id": 0, "age": 20, "name": "abc", "nickname": "123"}`
+### Example 2: URL path parameter
+```python
+@app.route("/character/<character_id>/", methods=["GET"])
+@validate()
+def get_character(character_id: int):
+ characters = [
+ ResponseModel(id=1, age=95, name="Geralt", nickname="White Wolf"),
+ ResponseModel(id=2, age=45, name="Triss Merigold", nickname="sorceress"),
+ ResponseModel(id=3, age=42, name="Julian Alfred Pankratz", nickname="Jaskier"),
+ ResponseModel(id=4, age=101, name="Yennefer", nickname="Yenn"),
+ ]
+ try:
+ return characters[character_id]
+ except IndexError:
+ return {"error": "Not found"}, 400
+```
+### Example 3: Request body only
+```python
+class RequestBodyModel(BaseModel):
+ name: str
+ nickname: Optional[str]
+# Example2: request body only
+@app.route("/", methods=["POST"])
+@validate()
+def post(body: RequestBodyModel):
+ name = body.name
+ nickname = body.nickname
+ return ResponseModel(
+ name=name, nickname=nickname,id=0, age=1000
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Example 4: BOTH query paramaters and request body
+```python
+# Example 3: both query paramters and request body
+@app.route("/both", methods=["POST"])
+@validate()
+def get_and_post(body: RequestBodyModel,query: QueryModel):
+ name = body.name # From request body
+ nickname = body.nickname # From request body
+ age = query.age # from query parameters
+ return ResponseModel(
+ age=age, name=name, nickname=nickname,
+ id=0
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Example 5: Request form-data only
+```python
+class RequestFormDataModel(BaseModel):
+ name: str
+ nickname: Optional[str]
+# Example2: request body only
+@app.route("/", methods=["POST"])
+@validate()
+def post(form: RequestFormDataModel):
+ name = form.name
+ nickname = form.nickname
+ return ResponseModel(
+ name=name, nickname=nickname,id=0, age=1000
+ )
+```
+<a href="blob/master/example_app/example.py">
+ See the full example app here
+</a>
+### Modify response status code
+The default success status code is `200`. It can be modified in two ways
+- in return statement
+```python
+# necessary imports, app and models definition
+@app.route("/", methods=["POST"])
+@validate(body=BodyModel, query=QueryModel)
+def post():
+ return ResponseModel(
+ id=id_,
+ age=request.query_params.age,
+ name=request.body_params.name,
+ nickname=request.body_params.nickname,
+ ), 201
+```
+- in `validate` decorator
+```python
+@app.route("/", methods=["POST"])
+@validate(body=BodyModel, query=QueryModel, on_success_status=201)
+def post():
+```
+Status code in case of validation error can be modified using `FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE` flask configuration variable.
+### Using the decorated function `kwargs`
+Instead of passing `body` and `query` to `validate`, it is possible to directly
+defined them by using type hinting in the decorated function.
+```python
+# necessary imports, app and models definition
+@app.route("/", methods=["POST"])
+@validate()
+def post(body: BodyModel, query: QueryModel):
+ return ResponseModel(
+ id=id_,
+ age=query.age,
+ name=body.name,
+ nickname=body.nickname,
+ )
+```
+This way, the parsed data will be directly available in `body` and `query`.
+Furthermore, your IDE will be able to correctly type them.
+### Model aliases
+Pydantic's [alias feature](https://pydantic-docs.helpmanual.io/usage/model_config/#alias-generator) is natively supported for query and body models.
+To use aliases in response modify response model
+```python
+def modify_key(text: str) -> str:
+ # do whatever you want with model keys
+ return text
+class MyModel(BaseModel):
+ class Config:
+ alias_generator = modify_key
+ allow_population_by_field_name = True
+```
+and set `response_by_alias=True` in `validate` decorator
+```
+@app.route(...)
+@validate(response_by_alias=True)
+def my_route():
+ return MyModel(...)
+```
+### Example app
+For more complete examples see [example application](https://github.com/bauerji/flask_pydantic/tree/master/example_app).
+### Configuration
+The behaviour can be configured using flask's application config
+`FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE` - response status code after validation error (defaults to `400`)
+Additionally, you can set `FLASK_PYDANTIC_VALIDATION_ERROR_RAISE` to `True` to cause
+`flask_pydantic.ValidationError` to be raised with either `body_params`,
+`form_params`, `path_params`, or `query_params` set as a list of error
+dictionaries. You can use `flask.Flask.register_error_handler` to catch that
+exception and fully customize the output response for a validation error.
+## Contributing
+Feature requests and pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
+- clone repository
+ ```bash
+ git clone https://github.com/bauerji/flask_pydantic.git
+ cd flask_pydantic
+ ```
+- create virtual environment and activate it
+ ```bash
+ python3 -m venv venv
+ source venv/bin/activate
+ ```
+- install development requirements
+ ```bash
+ python3 -m pip install -r requirements/test.pip
+ ```
+- checkout new branch and make your desired changes (don't forget to update tests)
+ ```bash
+ git checkout -b <your_branch_name>
+ ```
+- run tests
+ ```bash
+ python3 -m pytest
+ ```
+- if tests fails on Black tests, make sure You have your code compliant with style of [Black formatter](https://github.com/psf/black)
+- push your changes and create a pull request to master branch
+## TODOs:
+- header request parameters
+- cookie request parameters
+
+%prep
+%autosetup -n Flask-Pydantic-0.11.0
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-Flask-Pydantic -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Tue Apr 11 2023 Python_Bot <Python_Bot@openeuler.org> - 0.11.0-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..98beaac
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+e64f152e0bf67bb5d90ab7eb04bdf715 Flask-Pydantic-0.11.0.tar.gz