-
-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make response scraping from return values pluggable #107
Comments
I think there's several use cases/features we'll want to support:
A couple ways I can see of doing this. A global registrySome module level dict that allows plugins/extensions to register how to serialize their types and how to generate OpenAPI specs for them (we'd need to come up with some sort of Protocol, what the keys are in the dict, etc.). I don't like having global registers like this but it would allow the plugin/extension to "just work" from the user's perspective without extra boilerplate. We could read/load from that registry during app startup so that there is no import-time race conditions (import order). As far as I can tell though # Xpresso code
class XpressoResponseSchema:
def generate_openapi(self, model: type) -> ?:
...
class XpressoResponseJsonifier:
def jsonify(self, obj: object) -> object:
...
RESPONSES_BY_TYPE = {} # have Pydantic as the default here or something?
class JsonEncoder: # already exists
def encode(self, obj: object, ...) -> object:
if type(object) in RESPONSES_BY_TYPE:
return RESPONSES_BY_TYPE[type(object)]. jsonify(obj)
...
# Extension code
class MsgSpecResponse:
def generate_openapi(self, model: type) -> ?:
...
def jsonify(self, obj: object) -> object:
...
RESPONSES_BY_TYPE[Struct] = MsgSpecResponse I think one con here is that we would not be able to support something like Some sort of marker on return types.We'd come up with something like: # Xpresso code
class XpressoResponseSchema:
def generate_openapi(self, model: type) -> ?:
...
class XpressoResponseJsonifier:
def jsonify(self, obj: object) -> object:
...
class XpressoResponseEncoder:
def encode(self, obj: object) -> bytes:
...
# Extension code
class MsgSpecResponseSchema:
def generate_openapi(self, model: type) -> ?:
...
class MsgSpecResponseEncoder:
def encode(self, obj: object) -> bytes:
...
T = TypeVar("T")
MsgSpecResponse = Annotated[T, MsgSpecResponseSchema(), MsgSpecResponseEncoder()]
# User code
class MyStruct(msgspec.Struct): pass
def endpoint() -> MsgSpecResponse[list[MyStruct]]:
return [MyStruct()] The con here compared to the first approach is a lot more user boilerplate. But this would allow @jcrist would love your thoughts on this. |
#106 (comment)
While it is currently possible to use a combination of the
reponse_factory
parameter toOperation
and explicitly setting the response schema via theresponses
parameter toOperation
to support non-Pydantic responses, it is super boilerplatey and cumbersome.The text was updated successfully, but these errors were encountered: