Skip to content

Commit 1db7e5a

Browse files
authored
Merge pull request #49 from Ge0rg3/dev/smt5541/multi_source
Add MultiSource Parameter Type
2 parents 7cbc8a9 + 2fc5524 commit 1db7e5a

File tree

8 files changed

+875
-114
lines changed

8 files changed

+875
-114
lines changed

README.md

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def error_handler(err):
6868
"error_message": str(err)
6969
}, 400
7070

71-
@ValidateParameters(error_handler)
7271
@app.route(...)
72+
@ValidateParameters(error_handler)
7373
def api(...)
7474
```
7575

@@ -84,26 +84,44 @@ The `Parameter` class provides a base for validation common among all input type
8484
| Json | Parameter in the JSON object in the request body, must have header `Content-Type: application/json` | POST Methods |
8585
| Query | Parameter in the query of the URL, such as /news_article?id=55 | All HTTP Methods |
8686
| File | Parameter is a file uploaded in the request body | POST Method |
87+
| MultiSource | Parameter is in one of the locations provided to the constructor | Dependent on selected locations |
88+
89+
Note: "**POST Methods**" refers to the HTTP methods that send data in the request body, such as POST, PUT, PATCH and DELETE. Although sending data via some methods such as DELETE is not standard, it is supported by Flask and this library.
90+
91+
##### MultiSource Parameters
92+
Using the `MultiSource` parameter type, parameters can be accepted from any combination of `Parameter` subclasses. Example usage is as follows:
93+
94+
```py
95+
@app.route("/")
96+
@app.route("/<v>") # If accepting parameters by Route and another type, a path with and without that Route parameter must be specified
97+
@ValidateParameters()
98+
def multi_source_example(
99+
value: int = MultiSource(Route, Query, Json, min_int=0)
100+
)
101+
```
102+
103+
The above example will accept parameters passed to the route through Route, Query, and JSON Body.
104+
87105

88106
Note: "**POST Methods**" refers to the HTTP methods that send data in the request body, such as POST, PUT, PATCH and DELETE. Although sending data via some methods such as DELETE is not standard, it is supported by Flask and this library.
89107

90108
#### Type Hints and Accepted Input Types
91109
Type Hints allow for inline specification of the input type of a parameter. Some types are only available to certain `Parameter` subclasses.
92110

93-
| Type Hint / Expected Python Type | Notes | `Route` | `Form` | `Json` | `Query` | `File` |
94-
|------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|---------|--------|--------|---------|--------|
95-
| `str` | | Y | Y | Y | Y | N |
96-
| `int` | | Y | Y | Y | Y | N |
97-
| `bool` | | Y | Y | Y | Y | N |
98-
| `float` | | Y | Y | Y | Y | N |
99-
| `typing.List` (must not be `list`) | For `Query` inputs, users can pass via either `value=1&value=2&value=3`, or `value=1,2,3`, both will be transformed to a `list`. | N | Y | Y | Y | N |
100-
| `typing.Union` | | Y | Y | Y | Y | N |
101-
| `typing.Optional` | | Y | Y | Y | Y | Y |
102-
| `datetime.datetime` | received as a `str` in ISO-8601 date-time format | Y | Y | Y | Y | N |
103-
| `datetime.date` | received as a `str` in ISO-8601 full-date format | Y | Y | Y | Y | N |
104-
| `datetime.time` | received as a `str` in ISO-8601 partial-time format | Y | Y | Y | Y | N |
105-
| `dict` | | N | N | Y | N | N |
106-
| `FileStorage` | | N | N | N | N | Y |
111+
| Type Hint / Expected Python Type | Notes | `Route` | `Form` | `Json` | `Query` | `File` |
112+
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|--------|---------|--------|
113+
| `str` | | Y | Y | Y | Y | N |
114+
| `int` | | Y | Y | Y | Y | N |
115+
| `bool` | | Y | Y | Y | Y | N |
116+
| `float` | | Y | Y | Y | Y | N |
117+
| `typing.List` (must not be `list`) | For `Query` and `Form` inputs, users can pass via either `value=1&value=2&value=3`, or `value=1,2,3`, both will be transformed to a `list`. | N | Y | Y | Y | N |
118+
| `typing.Union` | Cannot be used inside of `typing.List` | Y | Y | Y | Y | N |
119+
| `typing.Optional` | | Y | Y | Y | Y | Y |
120+
| `datetime.datetime` | Received as a `str` in ISO-8601 date-time format | Y | Y | Y | Y | N |
121+
| `datetime.date` | Received as a `str` in ISO-8601 full-date format | Y | Y | Y | Y | N |
122+
| `datetime.time` | Received as a `str` in ISO-8601 partial-time format | Y | Y | Y | Y | N |
123+
| `dict` | For `Query` and `Form` inputs, users should pass the stringified JSON | N | Y | Y | Y | N |
124+
| `FileStorage` | | N | N | N | N | Y |
107125

108126
These can be used in tandem to describe a parameter to validate: `parameter_name: type_hint = ParameterSubclass()`
109127
- `parameter_name`: The field name itself, such as username

flask_parameter_validation/parameter_types/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from .json import Json
44
from .query import Query
55
from .route import Route
6+
from .multi_source import MultiSource
67

78
__all__ = [
8-
"File", "Form", "Json", "Query", "Route"
9+
"File", "Form", "Json", "Query", "Route", "MultiSource"
910
]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from typing import Type
2+
3+
from flask_parameter_validation.parameter_types.parameter import Parameter
4+
5+
6+
class MultiSource(Parameter):
7+
name = "multi_source"
8+
9+
def __init__(self, *sources: list[Type[Parameter]], **kwargs):
10+
self.sources = [Source(**kwargs) for Source in sources]
11+
super().__init__(**kwargs)

flask_parameter_validation/parameter_types/parameter.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""
55
import re
66
from datetime import date, datetime, time
7+
78
import dateutil.parser as parser
89
import jsonschema
910
from jsonschema.exceptions import ValidationError as JSONSchemaValidationError
@@ -150,8 +151,6 @@ def validate(self, value):
150151
if self.func is not None and not original_value_type_list:
151152
self.func_helper(value)
152153

153-
154-
155154
return True
156155

157156
def convert(self, value, allowed_types):

0 commit comments

Comments
 (0)