Genie
Genie (geniespec on PyPI) generates API code from an api.yaml spec. Install it like any other tool and run it from your build scripts; the generated code is gitignored, not committed.
geniespec build --spec api.yaml --target <python-server | typescript-client> [--output .]
geniespec watch --spec api.yaml --target <python-server | typescript-client> [--output .] [-- <command>]
buildwrites the target's package into the output directory. Only files in that package are touched: changed files are rewritten and files it no longer generates are removed.python-server:./<service>_api/v<major>/(api,endpoints,resources,internal,exceptions). Code run from the output directory imports it directly, e.g.from my_service_api.v1 import api. Needskiba-core(core.api,core.util.typing_util; 0.5.3.dev87 or later forFilefields),pydanticandstarlette.typescript-client:./<service>-api/v<major>/(client,endpoints,resources,index) with a<Service>ApiV<major>Clientthat extends@kibalabs/core'sServiceClient. Construct it with the url the API version is mounted at, e.g.new MyServiceApiV1Client(requester, 'https://api.example.com/v1'). Methods take path parameters, then a params object for the request fields, and return the response field; stream transitions take a callback for each item; transitions withFilefields send a multipart form. Transitions withresponseType: redirector aquery-parametersfield are left out, as browsers open redirects directly and query-parameters fields receive third-party callbacks. Needs@kibalabs/core.
watchbuilds, then rebuilds whenever the spec changes. If the spec is invalid it logs the error and keeps the previous output. Given a command after--, it runs it once the first build is done, keeps rebuilding while it runs, exits with its exit code and stops it when watch itself is stopped, e.g.geniespec watch --spec api.yaml --target python-server -- uvicorn app:app --reload.- The bundled templates are examples of a kibalabs-style target.
Enums, oneOfs and files
Enums are string values limited to a list. Name them at the top level to reuse them, or give a field its own:
enums:
- name: ViewKind
values: [member, cycle-start]
resources:
- singleName: View
collectionName: Views
attributes:
- name: kind
type: ViewKind
- name: size
type: Enum
enumValues: [small, large]
python-server types them as typing.Literal[...] (named ones as ViewKindV1 in resources) and rejects requests with other values; typescript-client types them as 'member' | 'cycle-start' (named ones as an exported ViewKindV1).
type: File request fields upload a file. They are only allowed on POST transitions, and the transition's other fields must be single primitive or enum values, as the request is sent as a multipart form. Internal methods receive kiba-core's UploadedFile (filename, contentType, content); clients pass a File.
A oneOf is a value that is one of several resources, told apart by a discriminator attribute. Each member resource needs that attribute as a non-nullable enum with a single value:
oneOfs:
- name: ViewContent
discriminator: kind
types: [ChartContent, TableContent]
resources:
- singleName: ChartContent
collectionName: ChartContents
attributes:
- name: kind
type: Enum
enumValues: [chart]
Fields use it like any other type (type: ViewContent, also inside List and Mapping). python-server generates a ViewContentV1 pydantic discriminated union in resources; typescript-client generates a ViewContentV1 union type and a viewContentV1FromObject function that builds the member class named by the discriminator (and throws for unknown values).
Development
make install
make lint-check type-check test
tests/python_server covers the core and the python-server target (the core tests generate through it) and runs in Dockerfile. tests/typescript_client covers the typescript-client target; it needs node and runs in typescript-client.Dockerfile:
make install-typescript-client
make test-typescript-client
Merges to main publish a dev version to PyPI. To release, bump version in pyproject.toml in a PR, then run the Release workflow on main (Actions → Release → Run workflow). It tags vX.Y.Z and the Publish workflow publishes it. Only the release workflow can push version tags.
Things that need work
Typing of params and fields in general
I think we need to create an object for Type. what would it look like?
class BaseFieldType:
isNullable: bool
class RawFieldType(BaseFieldType):
name: str
class ClassFieldType(BaseFieldType):
fieldType: RawFieldType
class ListFieldType:(BaseFieldType)
fieldType: RawFieldType
isNullable: bool
class MappingFieldType(BaseFieldType):
keyFieldType: RawFieldType
valueFieldType: RawFieldType
class OneOfFieldType(BaseFieldType):
fieldTypes: list[RawFieldType]
class EnumFieldType(BaseFieldType):
values: list[str]
Metadata
Release files for geniespec 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| geniespec-0.1.1.tar.gz | 27.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| geniespec-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 62.4 kB
Release files / geniespec-0.1.1.tar.gz
| Download URL | geniespec-0.1.1.tar.gz |
|---|---|
| Size | 27.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5235842c2ee0d1fcaf7cce8c155919d01cb747a82a5cf2c4cbd3d87c8b014bbd
|
|
BLAKE2b-256 checksum How to use checksums |
d5a1afa7ca1fc0730732069a68712c7b2eee32d02e97102dc5036de014a31f1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / geniespec-0.1.1-py3-none-any.whl
| Download URL | geniespec-0.1.1-py3-none-any.whl |
|---|---|
| Size | 34.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
76787e5c01e4a67865415767cedac1ad69e9175c7a95cbbebb1179858105aee1
|
|
BLAKE2b-256 checksum How to use checksums |
7fd00aec450108d78a085f333657ae6a017492b9896a7bec41528d9a9f41bd29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for geniespec 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.