Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ requires-python = ">=3.11"
dependencies = [
"pystapi-client",
"pystapi-validator",
"pystapi-schema-generator",
"stapi-pydantic",
"stapi-fastapi",
]
Expand Down Expand Up @@ -34,11 +35,18 @@ docs = [
default-groups = ["dev", "docs"]

[tool.uv.workspace]
members = ["pystapi-validator", "stapi-pydantic", "pystapi-client", "stapi-fastapi"]
members = [
"pystapi-client",
"pystapi-validator",
"pystapi-schema-generator",
"stapi-pydantic",
"stapi-fastapi"
]

[tool.uv.sources]
pystapi-client.workspace = true
pystapi-validator.workspace = true
pystapi-schema-generator.workspace = true
stapi-pydantic.workspace = true
stapi-fastapi.workspace = true

Expand Down Expand Up @@ -66,6 +74,7 @@ strict = true
files = [
"pystapi-client/src/pystapi_client/**/*.py",
"pystapi-validator/src/pystapi_validator/**/*.py",
"pystapi-schema-generator/src/pystapi_schema_generator/**/*.py",
"stapi-pydantic/src/stapi_pydantic/**/*.py",
"stapi-fastapi/src/stapi_fastapi/**/*.py"
]
Expand Down
16 changes: 16 additions & 0 deletions pystapi-schema-generator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.0.1] - 2025-04-01

### Added

- A spec product that tightly follows the [STAPI specification](https://github.com/stapi-spec/stapi-spec)
- A STAPI FastAPI application offering the spec product
- A script that creates the FastAPI application to create the OpenAPI schema
1 change: 1 addition & 0 deletions pystapi-schema-generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# pystapi-schema-generator
26 changes: 26 additions & 0 deletions pystapi-schema-generator/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[project]
name = "pystapi-schema-generator"
version = "0.0.1"
description = "Schema Generator for the Satellite Tasking API (STAPI) Specification"
readme = "README.md"
authors = [
{ name = "Tobias Rohnstock", email = "tobias.rohnstock@live-eo.com" },
{ name = "Justin Trautmann", email = "justin@live-eo.com" },
]
requires-python = ">=3.11"
dependencies = [
"uvicorn>=0.34",
"fastapi>=0.115",
"pydantic>=2.10",
"PyYAML>=6",
"types-PyYAML>=6",
"geojson-pydantic>=1.2",
"stapi-pydantic>=0.0.3",
]

[project.scripts]
stapi-schema-generator = "pystapi_schema_generator.application:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""STAPI Schema Generator package."""

import importlib.metadata

STAPI_VERSION = importlib.metadata.version("stapi_pydantic")
STAPI_BASE_URL = "https://stapi.example.com"
STAPI_EXAMPLE_URL = "https://api.example.com"
142 changes: 142 additions & 0 deletions pystapi-schema-generator/src/pystapi_schema_generator/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from fastapi import FastAPI
from stapi_pydantic import Product, Provider

from pystapi_schema_generator import STAPI_BASE_URL, STAPI_VERSION
from pystapi_schema_generator.root_router import RootRouter


def create_app() -> FastAPI:
"""Create and configure the FastAPI application for OpenAPI spec generation."""
app = FastAPI(
title="STAPI API",
description=(
"The Sensor Tasking API (STAPI) defines a JSON-based web API to query for "
"spatio-temporal analytic and data products derived from remote sensing "
"(satellite or airborne) providers. The specification supports both products "
"derived from new tasking and products from provider archives."
),
version=STAPI_VERSION,
openapi_tags=[
{
"name": "Core",
"description": "Core endpoints for API discovery and metadata.",
"externalDocs": {
"description": "STAPI Core Specification",
"url": "https://github.com/stapi-spec/stapi-spec/blob/main/core/README.md",
},
},
{
"name": "Products",
"description": "Endpoints for discovering and accessing remote sensing data products.",
"externalDocs": {
"description": "STAPI Product Specification",
"url": "https://github.com/stapi-spec/stapi-spec/blob/main/product/README.md",
},
},
{
"name": "Orders",
"description": "Endpoints for creating and managing remote sensing data orders.",
"externalDocs": {
"description": "STAPI Order Specification",
"url": "https://github.com/stapi-spec/stapi-spec/blob/main/order/README.md",
},
},
{
"name": "Opportunities",
"description": "Endpoints for searching remote sensing acquisition opportunities.",
"externalDocs": {
"description": "STAPI Opportunity Specification",
"url": "https://github.com/stapi-spec/stapi-spec/blob/main/opportunity/README.md",
},
},
],
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
# Enhanced OpenAPI configuration
openapi_extra={
"info": {
"contact": {
"name": "STAPI Specification Organization",
"url": "https://github.com/stapi-spec",
}
},
"externalDocs": {
"description": "STAPI Specification Documentation",
"url": "https://github.com/stapi-spec/stapi-spec",
},
},
# Swagger UI customization
swagger_ui_parameters={
"deepLinking": True,
"docExpansion": "list", # list endpoints but details are collapsed
"defaultModelsExpandDepth": 0, # Show schemas at the bottom but collapsed
"supportedSubmitMethods": [], # Disable all submit methods to prevent "Try it out"
},
# ReDoc customization
redoc_ui_parameters={
# TODO: Add Redoc customization parameters here if needed
},
)

router = RootRouter()
router.add_product(
Product(
id="{productId}",
title="Example Product",
description=(
"This is an example product that demonstrates the STAPI specification. "
"Implementers should replace this with their actual product definitions, "
"including specific metadata, queryable properties, and order parameters."
),
license="proprietary",
providers=[
Provider(
name="Example Provider",
roles=["producer"],
url="https://example.com/provider",
description="Example provider for demonstration purposes",
)
],
links=[],
stapi_type="Product",
stapi_version=STAPI_VERSION,
conformsTo=[
f"{STAPI_BASE_URL}/{STAPI_VERSION}/core",
"https://geojson.org/schema/Polygon.json",
],
)
)

app.include_router(router, prefix="")

return app


# Create the FastAPI application instance
app = create_app()


def main() -> None:
"""Generate OpenAPI schema for STAPI."""
import argparse

import yaml

parser = argparse.ArgumentParser(description="Generate OpenAPI schema for STAPI")
parser.add_argument(
"--output",
"-o",
default="openapi.yml",
help="Output file path for the OpenAPI schema (default: openapi.yml)",
)
args = parser.parse_args()

with open(args.output, "w") as f:
yaml.dump(app.openapi(), f)

print(f"OpenAPI schema saved to '{args.output}'.")


if __name__ == "__main__":
main()
Loading