OpenBBTerminal
OpenBBTerminal copied to clipboard
[BugFix] Set Default State For **kwargs in API to Make Them Optional.
This Tags on to #6250, #6248, #6240.
When parameter.kind == Parameter.VAR_KEYWORD
, it correctly cannot be assigned a default state because **kwargs cannot have one.
However, Fast API does not see it the same way and will make it a required field. In both, the body, and URL parameters.
To get around this, we can set:
parameter.kind == Parameter.POSITIONAL_OR_KEYWORD
, then assign it as Optional[Dict[str, Any]]
, and give it a default state of None
.
The end result is that **kwargs
can be a valid parameter for the API that gets assigned to the body of the request.
Note that **kwargs
could be anything - **extra_params
.
Why do we need to change FastAPI behavior? I believe it will cause some unexpected results in the future.
We aren't. We simply applying the correct Type and default state to **kwargs, which FastAPI does not recognize, but without having to manipulate the function signature in PackageBuilder, like what currently happens via changing "extra_params" to **kwargs. This does not require manipulating the function signature.
The reason to use **kwargs is to eliminate "unexpected keyword argument", and the added benefit is ANYONE can use **kwargs as a way to extend functionality without having to touch the router. This makes it work like the GET/provider functions where you can already do that.
If you just declare a Field, you then have to touch the router. This accomplishes exactly the same thing as your outcome and allows **extra_params to exist in POST functions where they could not be used before.
Why not go for the simplest approach and have something like this: (example signature):
def correlation_matrix(data: List[Data], payload: Dict[Any, Any] = None) -> OBBject[List[Data]]:
Which could then be used as follows on a POST request:
{ "data": [ { "additionalProp1": {} } ], "payload": {"chart_arg_1":"value1","chart_arg_2":"value2"} }
Which results in having the following values inside the function during execution:
Note taht this approach would avoid touching the
commands.py
file.