Skip to content

Commit 91dae7f

Browse files
Adds OSEG for example generation from JSON
1 parent 489118a commit 91dae7f

File tree

95 files changed

+17691
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+17691
-0
lines changed

oseg/.editorconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[{*.yml,*.yaml,*.md}]
2+
indent_style = space
3+
indent_size = 2
4+
[*.py]
5+
indent_size = 4

oseg/.gitignore

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
env/
12+
build/
13+
develop-eggs/
14+
dist/
15+
downloads/
16+
eggs/
17+
.eggs/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
*.egg-info/
23+
.installed.cfg
24+
*.egg
25+
26+
# PyInstaller
27+
# Usually these files are written by a python script from a template
28+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
29+
*.manifest
30+
*.spec
31+
32+
# Installer logs
33+
pip-log.txt
34+
pip-delete-this-directory.txt
35+
36+
# Unit test / coverage reports
37+
htmlcov/
38+
.tox/
39+
.coverage
40+
.coverage.*
41+
.cache
42+
nosetests.xml
43+
coverage.xml
44+
*,cover
45+
.hypothesis/
46+
venv/
47+
.venv/
48+
.python-version
49+
.pytest_cache
50+
51+
# Translations
52+
*.mo
53+
*.pot
54+
55+
# Django stuff:
56+
*.log
57+
58+
# Sphinx documentation
59+
docs/_build/
60+
61+
# PyBuilder
62+
target/
63+
64+
#Ipython Notebook
65+
.ipynb_checkpoints

oseg/Dockerfile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
FROM ghcr.io/astral-sh/uv:python3.13-alpine
2+
LABEL maintainer="Dropbox Sign <apisupport@hellosign.com>"
3+
4+
# Install the project into `/app`
5+
WORKDIR /app
6+
7+
# Enable bytecode compilation
8+
ENV UV_COMPILE_BYTECODE=1
9+
10+
# Copy from the cache instead of linking since it's a mounted volume
11+
ENV UV_LINK_MODE=copy
12+
13+
# Install the project's dependencies using the lockfile and settings
14+
RUN --mount=type=cache,target=/root/.cache/uv \
15+
--mount=type=bind,source=uv.lock,target=uv.lock \
16+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
17+
uv sync --frozen --no-install-project --no-dev
18+
19+
# Then, add the rest of the project source code and install it
20+
# Installing separately from its dependencies allows optimal layer caching
21+
ADD ./pyproject.toml /app/pyproject.toml
22+
ADD ./uv.lock /app/uv.lock
23+
ADD ./oseg /app/oseg
24+
ADD ./static /app/static
25+
ADD ./LICENSE /app/LICENSE
26+
ADD ./README.md /app/README.md
27+
ADD ./run.py /app/run.py
28+
29+
RUN --mount=type=cache,target=/root/.cache/uv \
30+
uv sync --frozen --no-dev
31+
32+
# Place executables in the environment at the front of the path
33+
ENV PATH="/app/.venv/bin:$PATH"
34+
35+
# Reset the entrypoint, don't invoke `uv`
36+
ENTRYPOINT ["python", "/app/run.py"]

oseg/README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# OSEG - OpenAPI SDK Example Generator
2+
3+
Create (almost) ready to use SDK snippets for SDKs generated using [openapi-generator](https://openapi-generator.tech/) using example data from your OpenAPI spec.
4+
5+
## Where does the example data come from?
6+
7+
Example data used to generate the code snippets can come from a number of places:
8+
9+
* example or examples values in schema
10+
* default values in schema
11+
* Externally referenced JSON files defined in schema
12+
* You can also create a JSON file with examples for all the endpoints you want
13+
14+
OSEG currently generates one code snippet file per `requestBody` definition, but only a single example per `parameters` definition.
15+
16+
In other words, you can generate multiple examples of the same operation/endpoint by having multiple `requestBody` definitions. Each generate example will have different data embedded within it. However, since `parameters` is tied to a single operation, the same data will apply to any and all `requestBody` definitions.
17+
18+
If you use a custom JSON file with examples you can define as many examples per endpoint as you want, since you can define each data source separately (`query`, `path`, `header`, `cookie`, and `body`) per endpoint.
19+
20+
## How to run
21+
22+
The entrypoint to this project is `run.py`. It currently supports two commands:
23+
24+
### config-help
25+
26+
Prints all config options available to a given generator.
27+
28+
Run `python3 run.py config-help --help` for more details.
29+
30+
Show config options for the `python` generator:
31+
32+
```bash
33+
python3 run.py config-help -g python
34+
```
35+
36+
## Tests
37+
38+
See [tests directory](tests).
39+
40+
## Feature support
41+
42+
The aim of this project is to cover the most common use-cases in an OpenAPI spec.
43+
44+
### Supported
45+
46+
* Requests with and without formdata: `openapi-generator` will create a different interface if an endpoint's `content-type` has formdata (`multipart/form-data` or `application/x-www-form-urlencoded`) and everything else
47+
* Discriminators with `allOf`
48+
49+
### Issues
50+
51+
The following are issues with the SDK code generated by `openapi-generator`.
52+
53+
* `allOf` without a discriminator: Depending on the `openapi-generator` generator used, the generated SDK may be completely broken
54+
* `typescript-node` SDK code is generated broken by `openapi-generator`
55+
* Other SDKs currently supported by OSEG will usually just use a generic `object` type
56+
* `anyOf`
57+
* `typescript-node` generated SDK does not set data
58+
* `php` generated SDK does not set data
59+
* Other SDKs currently supported by OSEG generate a class
60+
* `oneOf`
61+
* `typescript-node` generated SDK does not set data
62+
* `php` generated SDK does not set data
63+
* Other SDKs currently supported by OSEG generate a class
64+
* Multiple values in `type` definition. New in OpenAPI 3.1 `type` can now be an array of supported types
65+
* `c#`, `java`, `ruby` Generate a class
66+
* `python` generates a class but does not use it, types property as the first value in `type`
67+
* `php` generates a class, data not set
68+
* `typescript-node` generates a class, data not set
69+
* `openapi-generator` generates a class for inline schema with `type=object`. If two or more Operations share identical inline schema definitions, `openapi-generator` will only generate a class for one of the Operations, and all Operations will reference this class. The name of the class depends on which Operation is read first by `openapi-generator`, but it may not reflect the first definition within the OAS file and thus is impossible for OSEG to know the name of the class ahead of time.

oseg/bin/build

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
DIR=$(cd `dirname $0` && pwd)
6+
BASE_DIR="${DIR}/.."
7+
8+
pushd "${BASE_DIR}"
9+
uv build
10+
popd

oseg/bin/code-cov

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
DIR=$(cd `dirname $0` && pwd)
6+
BASE_DIR="${DIR}/.."
7+
8+
pushd "${BASE_DIR}"
9+
uv run coverage run -m unittest discover -s tests
10+
uv run coverage html --omit=tests/*
11+
popd

oseg/bin/docker-build

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
DIR=$(cd `dirname $0` && pwd)
6+
VERSION=$1
7+
8+
if [[ -z "${VERSION-}" ]]; then
9+
echo "Must provide version"
10+
exit 1
11+
fi
12+
13+
pushd "${DIR}/.."
14+
15+
docker image build \
16+
-f Dockerfile \
17+
-t dropbox/oseg:${VERSION} .
18+
19+
popd

oseg/oseg/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import os
2+
3+
# coding: utf-8
4+
5+
"""
6+
oseg
7+
"""
8+
9+
__version__ = "0.3-dev"
10+
__ROOT_DIR__ = os.path.dirname(os.path.abspath(__file__)) + "/.."
11+
12+
from .jinja_extension import *
13+
from .generator import *
14+
from .model import *
15+
from .parser import *
16+
from .oseg import *

oseg/oseg/generator/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from .base_generator import (
2+
BaseConfig,
3+
BaseConfigDef,
4+
BaseConfigOseg,
5+
BaseGenerator,
6+
GeneratorFactory,
7+
Project,
8+
ProjectTemplateFilesDef,
9+
PropsOptionalT,
10+
)
11+
from .csharp_generator import CSharpGenerator
12+
from .java_generator import JavaGenerator
13+
from .kotlin_generator import KotlinGenerator
14+
from .php_generator import PhpGenerator
15+
from .python_generator import PythonGenerator
16+
from .ruby_generator import RubyGenerator
17+
from .typescript_axios_generator import TypescriptAxiosGenerator
18+
from .typescript_node_generator import TypescriptNodeGenerator

0 commit comments

Comments
 (0)