Skip to content

Commit

Permalink
📝 Add Python code representation of OpenAPI document document.
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Krupinski committed Jan 1, 2024
1 parent d0420e5 commit e431e13
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
71 changes: 71 additions & 0 deletions docs/python_representation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Python code representation of OpenAPI document

The goal of python representation is to allow python code to fully replace OpanAPI document, allow Lapidary library to prepare a HTTP request and parse the response, in a way compatible with the server describe by that OpenAPI document.

The python representation must be fully sufficient, must not require the original document to function, and usage must execute a valid exchange with a server.

## Client

A client to a remote service may be represented as a collection of functions, each representing an operation, and a collection of data classes, each representing a schema.
The functions could be module-level or grouped in one or more classes, optionally forming an object hierarchy.

Lapidary implements a single class approach, but supporting all three styles at later stage should be simple.

## Paths and Operations

OpenAPI paths can be explained as a mapping of HTTP method and path to an Operation declaration.

OpenAPI Operation specifies the request body, parameters and responses, so it's the closest thing to a python function.

### Parameters

#### Naming

Each of cookie, header, path and query parameters have their own namespace, so they can't be directly mapped to names of parameters of a python function.

The possible work-arounds are:

- grouping parameters in mappings, named tuples or objects,
- name mangling,
- annotations.

Lapidary uses annotations, which declares parameter location and may be used to provide the name.

```python
from typing import Annotated
from lapidary.runtime.model.params import CookieParam


async def operation(
self,
param1_c: Annotated[str, CookieParam('param1')],
):
...
```

#### Serialization

Serialization in OpenAPI is a rather complex subject, and not well defined.

An example of undefined behaviour is serialization of nested object with simple or form style, which is neither defined nor forbidden.

Possible solution are:
- explicitly forbidding certain cases
- extending the specification, and optionally accepting extra parameters (i.e. field delimiter in nested objects)
- accepting custom de/serialization function

### Request Body

See [Request body](request_body.md)

### Responses

TBD

## Auth

TBD

## Servers

TBD
12 changes: 12 additions & 0 deletions docs/request_body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Serializing request body

## Input

OpenAPI 3.x essentially defines the request body object as a mapping of media type (or media type range) to schema and encoding object.

This means that the server accepts various media types there may be different data types, but also it may be the same data type.

On the client side we have the type as the input, the mapping transforms to mapping of schema to a set of (media type or type range and encoding object).
That set needs to be resolved to a single media type.

This parameter only declares what is accepted by the server, and in some cases it might be insufficient to determine the request body serialization method. For this reason the operation method should accept, and in some cases require, the requests content-type.

0 comments on commit e431e13

Please sign in to comment.