prkumar / uplink

A Declarative HTTP Client for Python
https://uplink.readthedocs.io/
MIT License
1.07k stars 61 forks source link

Type hinting Optional parameters with the Field annotation #289

Open koioannis opened 1 year ago

koioannis commented 1 year ago

Is your feature request related to a problem? Please describe.

Imagine the following scenario where you want to make a POST request with a body that contains a only a few fields and creating a seperate Pydantic (or Marshmallow) model would be just more boilerplate (I'm not considerring passing a dict or kwargs directly as it is not that user friendly). Right now, you can always specify the JSON body fields as parameters, but it doesn't seem to play nice with the Optional type hint (which means with the Union type actually).

import uplink
from typing import Optional

@uplink.json
@uplink.post("/foo/{id}", args={
    "id": Path, 
    "bar": Field,
    "optional_bar": Field
})
def make_request(self, id: str, bar: str, optional_bar: Optional[str] = None) -> None:
    pass

What I am seeing in the stack trace is:

 
  File "/python3.10/site-packages/uplink/builder.py", line 100, in __call__
    self._request_definition.define_request(request_builder, args, kwargs)
  File "/python3.10/site-packages/uplink/commands.py", line 284, in define_request
    self._argument_handler.handle_call(
  File "/python3.10/site-packages/uplink/arguments.py", line 154, in handle_call
    self.handle_call_args(request_builder, call_args)
  File "/python3.10/site-packages/uplink/arguments.py", line 159, in handle_call_args
    annotation.modify_request(request_builder, call_args[name])
  File "/python3.10/site-packages/uplink/arguments.py", line 182, in modify_request
    converter = request_builder.get_converter(converter_key, argument_type)
  File "/python3.10/site-packages/uplink/helpers.py", line 96, in get_converter
    return self._converter_registry[converter_key](*args, **kwargs)
  File "/python3.10/site-packages/uplink/converters/__init__.py", line 52, in __call__
    converter = self._converter_factory(*args, **kwargs)
  File "/python3.10/site-packages/uplink/converters/__init__.py", line 112, in chain
    converter = func(factory)(*args, **kwargs)
  File "/python3.10/site-packages/uplink/converters/typing_.py", line 130, in create_request_body_converter
    return self._base_converter(type_)
  File "/python3.10/site-packages/uplink/converters/typing_.py", line 121, in _base_converter
    if issubclass(type_.__origin__, self.typing.Sequence):
  File "/python3.10/typing.py", line 1158, in __subclasscheck__
    return issubclass(cls, self.__origin__)
  File "/python3.10/abc.py", line 123, in __subclasscheck__
    return _abc_subclasscheck(cls, subclass)
TypeError: issubclass() arg 1 must be a clas

Describe the solution you'd like Parameters should work with the Union type hint.

P.S: I haven't looked into the library hence, I don't even know if that's possible. That's why I am posting it as a feature request and not a bug. Thanks for the great library :).