/micro-openapi

Primary LanguagePythonApache License 2.0Apache-2.0

Micro-OpenAPI

The code in this repository is aimed at demonstrating how to combine Pydantic, APISpec and a micro-framework, to help you write OpenAPI documentation. We currently have sketched examples in Flask; Falcon and Starlette will come soon.

What it is not

This library is not a tool to help you validate body request, content, or other parameters.

It is not a tool to think for you and allow you to speed up what you should be good at.

It is not a tool to automatically generate OpenAPI documentation based on Pydantic, or any other, typing or validation library.

The issues it tries to solve

Maintaining OpenAPI documentation can be difficult. The usual formats (JSON or YAML) ask you to write texts, in aside files or in doc-strings. This might not be convenient for different reasons:

  1. Non locality: Having the specification in another file, or even another place in code, diminishes code locality and increases the overhead for a reader to keep information in memory;
  2. External dialect: Writing YAML or JSON, even though not difficult per se, involved an external dialect that might not help in code readability. They also tend to take more space they would need, or introduce noisy characters;
  3. Unchecked writing: Writing plain text (even through a format) usually increases the changes to perform typos or even OpenAPI errors.
  4. Compromise (worst of all worlds): Solution that try to find a compromise between two type systems, usually fail at it and cannot render the flavors of both (often not even of a single one of them).
  5. Intrusive policy: Hyper-branded solutions (see FastAPI or APIFlask, for example) are opinionated and perform micro-framework intrusions: they alter the micro-framework they hook and limit it in an intrusive way; in some cases, prevent other third parties to continue working along.

What it is

Micro-OpenAPI is a micro annotation set that is aimed to live along class-based views (which you can find in Starlette, Flask, or Falcon). We have chosen class-based approach because it suits well the OpenAPI wording already, where a single path is declined through operations. This is a radically different approach to FastAPI, for example, which stresses RPC style of code.

The primilary goal is to help you write OpenAPI specification along with Pydantic code, by providing annotations that roughly act as the identity over functions, yet memoizing definitions to infer a specification using APISpec and Pydantic.

Even though the examples tend to be funky, it is not aimed to create a new layer of abstraction on top of the micro-framework you love the most. We tried to show, through a real non scholar example, how the tool can be used.

Note We emphasize that micro-openapi is not a third-party library you should be blindly using. Rather, it is a code whose purpose is to demonstrate that Swagger generation does not have to be difficult for your use case. You know your business better than a third-party, and you likely don't need to be generic.

How it works

The basic annotation is Definition (or its counter part AsyncDefinition for asynchronous views). It morally acts as the identity decorator, except it stores the definition schema.

The schema is then used when you (the developper) registers the views in the application. Pydantic models will get collected in a set, by traversing the range of all definitions, and will get converted using the schema method of Pydantic (no hacking). Once this is done, the schema components will be registered in APISpec (no hacking), and then we traverse the paths by registered them in APISpec (no hacking).

Why APISpec?

The project currently has more derivated products that the count of my fingers, and is still under activate maintainance. It is a sign it is still viable. It is used to compose the final document, and could be used in case we would have wanted Marshmallow instead of Pydantic.

Why Pydantic?

Apparently it's the trend. Aside from that, it embraces Python typing quite nicely (though maybe attrs would be much better) and receives a lot of implicit support, through libraries like Django-Ninja, FastAPI, Litestar,... Crucial point for us, is that there is a way to automatically get the components schemas as a whole.

Why not frameworks?

If you have an opinion about that, you would understand what "opinionated" means. You're likely pride enough to consider your opinion is better than others. If it is indeed the case, there is nothing to really debate against.

Install

First install the microapi library in a fresh environment.

python3.9 -m venv venv39
source venv39/bin/activate
pip install -r requirements.txt
pip install mypy
pip install build

# Run MyPy, for satisfaction purpose

python -m build

# Install the wheel in your environment

It is recommended to check out the examples to get an idea of what the library actually does.