spec2sdk


Namespec2sdk JSON
Version 1.0.202411031804 PyPI version JSON
download
home_pagehttps://github.com/moneymeets/spec2sdk
SummaryGenerate Pydantic models and API client code from OpenAPI 3.x specifications
upload_time2024-11-03 18:04:38
maintainerNone
docs_urlNone
authormoneymeets
requires_python<3.13,>=3.12
licenseMIT
keywords openapi pydantic code-generator openapi-codegen
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Usage

## From command line

`spec2sdk --input path/to/api.yml --output-dir path/to/output-dir/`

## From the code

```python
from pathlib import Path
from spec2sdk.main import generate

generate(url=Path("path/to/api.yml").absolute().as_uri(), output_dir=Path("path/to/output-dir/"))
```

# Open API specification requirements

## Operation ID

`operationId` must be specified for each endpoint to generate meaningful method names. It must be unique among all operations described in the API.

### Input

```yaml
paths:
  /health:
    get:
      operationId: healthCheck
      responses:
        '200':
          description: Successful response
```

### Output

```python
class APIClient:
    def health_check(self) -> None:
        ...
```

## Inline schemas

Inline schemas should be annotated with the schema name in the `x-schema-name` field that doesn't overlap with the existing schema names in the specification.

### Input

```yaml
paths:
  /me:
    get:
      operationId: getMe
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                x-schema-name: User
                type: object
                properties:
                  name:
                    type: string
                  email:
                    type: string
```

### Output

```python
class User(Model):
    name: str | None = Field(default=None)
    email: str | None = Field(default=None)
```

## Enum variable names

Variable names for enums can be specified by the `x-enum-varnames` field.

### Input

```yaml
components: 
  schemas:
    Direction:
      x-enum-varnames: [ NORTH, SOUTH, WEST, EAST ]
      type: string
      enum: [ N, S, W, E ]
```

### Output

```python
from enum import StrEnum

class Direction(StrEnum):
    NORTH = "N"
    SOUTH = "S"
    WEST = "W"
    EAST = "E"
```

# Custom types

Register Python converters and renderers to implement custom types.

## Input

```yaml
components: 
  schemas: 
    User:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
          format: email
```

```python
from pathlib import Path

from spec2sdk.parsers.entities import DataType, StringDataType
from spec2sdk.generators.converters import converters
from spec2sdk.generators.entities import PythonType
from spec2sdk.generators.predicates import is_instance
from spec2sdk.generators.imports import Import
from spec2sdk.generators.models.entities import TypeRenderer
from spec2sdk.generators.models.renderers import render_root_model, renderers
from spec2sdk.main import generate


class EmailPythonType(PythonType):
    pass


def is_email_format(data_type: DataType) -> bool:
    return isinstance(data_type, StringDataType) and data_type.format == "email"


@converters.register(predicate=is_email_format)
def convert_email_field(data_type: StringDataType) -> EmailPythonType:
    return EmailPythonType(
        name=None,
        type_hint="EmailStr",
        description=data_type.description,
        default_value=data_type.default_value,
    )


@renderers.register(predicate=is_instance(EmailPythonType))
def render_email_field(py_type: EmailPythonType) -> TypeRenderer:
    return render_root_model(
        py_type,
        extra_imports=(Import(name="EmailStr", package="pydantic"),),
        content="EmailStr",
    )


if __name__ == "__main__":
    generate(url=Path("api.yml").absolute().as_uri(), output_dir=Path("output"))
```

## Output

```python
from pydantic import EmailStr, Field

class User(Model):
    name: str | None = Field(default=None)
    email: EmailStr | None = Field(default=None)
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/moneymeets/spec2sdk",
    "name": "spec2sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<3.13,>=3.12",
    "maintainer_email": null,
    "keywords": "openapi, pydantic, code-generator, openapi-codegen",
    "author": "moneymeets",
    "author_email": "service@moneymeets.com",
    "download_url": "https://files.pythonhosted.org/packages/dc/35/dac5d9c8e55c481c1587f3108d02d802367f762ee33e8be5ec245e677c59/spec2sdk-1.0.202411031804.tar.gz",
    "platform": null,
    "description": "# Usage\n\n## From command line\n\n`spec2sdk --input path/to/api.yml --output-dir path/to/output-dir/`\n\n## From the code\n\n```python\nfrom pathlib import Path\nfrom spec2sdk.main import generate\n\ngenerate(url=Path(\"path/to/api.yml\").absolute().as_uri(), output_dir=Path(\"path/to/output-dir/\"))\n```\n\n# Open API specification requirements\n\n## Operation ID\n\n`operationId` must be specified for each endpoint to generate meaningful method names. It must be unique among all operations described in the API.\n\n### Input\n\n```yaml\npaths:\n  /health:\n    get:\n      operationId: healthCheck\n      responses:\n        '200':\n          description: Successful response\n```\n\n### Output\n\n```python\nclass APIClient:\n    def health_check(self) -> None:\n        ...\n```\n\n## Inline schemas\n\nInline schemas should be annotated with the schema name in the `x-schema-name` field that doesn't overlap with the existing schema names in the specification.\n\n### Input\n\n```yaml\npaths:\n  /me:\n    get:\n      operationId: getMe\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json:\n              schema:\n                x-schema-name: User\n                type: object\n                properties:\n                  name:\n                    type: string\n                  email:\n                    type: string\n```\n\n### Output\n\n```python\nclass User(Model):\n    name: str | None = Field(default=None)\n    email: str | None = Field(default=None)\n```\n\n## Enum variable names\n\nVariable names for enums can be specified by the `x-enum-varnames` field.\n\n### Input\n\n```yaml\ncomponents: \n  schemas:\n    Direction:\n      x-enum-varnames: [ NORTH, SOUTH, WEST, EAST ]\n      type: string\n      enum: [ N, S, W, E ]\n```\n\n### Output\n\n```python\nfrom enum import StrEnum\n\nclass Direction(StrEnum):\n    NORTH = \"N\"\n    SOUTH = \"S\"\n    WEST = \"W\"\n    EAST = \"E\"\n```\n\n# Custom types\n\nRegister Python converters and renderers to implement custom types.\n\n## Input\n\n```yaml\ncomponents: \n  schemas: \n    User:\n      type: object\n      properties:\n        name:\n          type: string\n        email:\n          type: string\n          format: email\n```\n\n```python\nfrom pathlib import Path\n\nfrom spec2sdk.parsers.entities import DataType, StringDataType\nfrom spec2sdk.generators.converters import converters\nfrom spec2sdk.generators.entities import PythonType\nfrom spec2sdk.generators.predicates import is_instance\nfrom spec2sdk.generators.imports import Import\nfrom spec2sdk.generators.models.entities import TypeRenderer\nfrom spec2sdk.generators.models.renderers import render_root_model, renderers\nfrom spec2sdk.main import generate\n\n\nclass EmailPythonType(PythonType):\n    pass\n\n\ndef is_email_format(data_type: DataType) -> bool:\n    return isinstance(data_type, StringDataType) and data_type.format == \"email\"\n\n\n@converters.register(predicate=is_email_format)\ndef convert_email_field(data_type: StringDataType) -> EmailPythonType:\n    return EmailPythonType(\n        name=None,\n        type_hint=\"EmailStr\",\n        description=data_type.description,\n        default_value=data_type.default_value,\n    )\n\n\n@renderers.register(predicate=is_instance(EmailPythonType))\ndef render_email_field(py_type: EmailPythonType) -> TypeRenderer:\n    return render_root_model(\n        py_type,\n        extra_imports=(Import(name=\"EmailStr\", package=\"pydantic\"),),\n        content=\"EmailStr\",\n    )\n\n\nif __name__ == \"__main__\":\n    generate(url=Path(\"api.yml\").absolute().as_uri(), output_dir=Path(\"output\"))\n```\n\n## Output\n\n```python\nfrom pydantic import EmailStr, Field\n\nclass User(Model):\n    name: str | None = Field(default=None)\n    email: EmailStr | None = Field(default=None)\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Generate Pydantic models and API client code from OpenAPI 3.x specifications",
    "version": "1.0.202411031804",
    "project_urls": {
        "Homepage": "https://github.com/moneymeets/spec2sdk",
        "Repository": "https://github.com/moneymeets/spec2sdk"
    },
    "split_keywords": [
        "openapi",
        " pydantic",
        " code-generator",
        " openapi-codegen"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f4ce515c92910d0daa437c19b5d184a688f0b624895cb24253e37d0241c738c5",
                "md5": "5ae10817d8002f573c1c67b68fcfcf1b",
                "sha256": "6a17946d8d569b3546e36ef97b0417d0f615c1c75c44e6cd7546fa6ae836a429"
            },
            "downloads": -1,
            "filename": "spec2sdk-1.0.202411031804-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5ae10817d8002f573c1c67b68fcfcf1b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<3.13,>=3.12",
            "size": 22992,
            "upload_time": "2024-11-03T18:04:37",
            "upload_time_iso_8601": "2024-11-03T18:04:37.387330Z",
            "url": "https://files.pythonhosted.org/packages/f4/ce/515c92910d0daa437c19b5d184a688f0b624895cb24253e37d0241c738c5/spec2sdk-1.0.202411031804-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "dc35dac5d9c8e55c481c1587f3108d02d802367f762ee33e8be5ec245e677c59",
                "md5": "2f5f1a71685464b3ecfc42c2d82c9e0a",
                "sha256": "42a0753086ddaa4c527061147511a34752e5da7b75ecd82de229a4a11ce22733"
            },
            "downloads": -1,
            "filename": "spec2sdk-1.0.202411031804.tar.gz",
            "has_sig": false,
            "md5_digest": "2f5f1a71685464b3ecfc42c2d82c9e0a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<3.13,>=3.12",
            "size": 15998,
            "upload_time": "2024-11-03T18:04:38",
            "upload_time_iso_8601": "2024-11-03T18:04:38.724776Z",
            "url": "https://files.pythonhosted.org/packages/dc/35/dac5d9c8e55c481c1587f3108d02d802367f762ee33e8be5ec245e677c59/spec2sdk-1.0.202411031804.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-03 18:04:38",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "moneymeets",
    "github_project": "spec2sdk",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "spec2sdk"
}
        
Elapsed time: 0.35836s