OpenBBTerminal icon indicating copy to clipboard operation
OpenBBTerminal copied to clipboard

[BugFix] Set Default State For **kwargs in API to Make Them Optional.

Open deeleeramone opened this issue 3 months ago • 1 comments

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.

deeleeramone avatar Mar 23 '24 02:03 deeleeramone

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.

deeleeramone avatar Apr 05 '24 16:04 deeleeramone