How can I convert an OpenAPIv3/swagger spec into a proxy around an API using Python and Prance library?

635 Views Asked by At

I'm building an automatic proxy generator around any arbitrary API given it's swagger document. The intended output would be a python module that could be used as a client for said API. The API itself would import the proxy generator, point it at its own Swagger page and export the dynamically constructed python client as part of a module.

Currently I'm using the prance library to parse the swagger.json document into a nested-dict structure.

parser = ResolvingParser(swagger_url)
print(parser.specification.keys())
>> dict_keys(['openapi', 'info', 'paths', 'components'])

The paths key here contains most of the juicy bits as a nested dictionary. This can be thought of as a tree, where the root of the tree is the given api path. For example '/api/v1/products' and the rest of the dictionaries are describing details of this path given the OpenAPI spec.

My goal is to take this nested dictionary structure and produce a set of objects that can be used to dynamically create a proxy around the API. The end-goal is to have a structure similar to the below

class Schema:
""" This class would define the object that is going to be returned. aka schema)"""

class Parameter:
name: str
type: str
in: str (Example: query, path, etc.)

class Get(Method):
parameters: List[Parameter]
body: Body = None
return_schema: Schema

class Endpoint():
path: str
description: str
methods: List[Type[Method]]

I would use these objects to dynamically generate a set of methods on a proxy for each endpoint.

I've explored a couple different paths to achieve the goal but am getting stuck on how to best handle the data structure given to me via Prance. I have a vague notion that flattening the data-structure is the best way to continue but need some guidance after this point.

I've:

  • Explored using pd.json_normalize() to normalize the json into a more usable format. This is promising but I'm unsure of how to continue
  • Flattening the nested dictionary into one level where the keys are the path through the tree separated by ..
  • Tried using the built in prance iterators (although I found them to be a bit obtuse to use)
  • Tried using openapi-generator but it didn't work for my purposes, as well as the python client being outdated

I'm looking for resources on how I can continue development, given my goals and this data-structure I'm working with.

Although this is the current path I've decided to take, other suggestions are welcome.

1

There are 1 best solutions below

0
Deep Singhvi On

I've been working on a standard parser for OpenAPI that is modeled similarly to the classes you described. I've been referring to the format as OpenAPIIntermediateRepresentation and you can see how the object is modeled in this yaml file. The parser is open source and published under the npm package @fern-api/openapi-parser.

For context, I work on an open source project called Fern and we are building an OpenAPI alternative but we also are compatible with existing OpenAPI documents. We have a python SDK generator that generates modern, idiomatic code. If you want to check it out, here are our docs: https://buildwithfern.com/docs/spec/openapi.