Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

phalt/cicerone

Open more actions menu

Repository files navigation

📜 Cicerone

Turn OpenAPI schemas into Pydantic models

Package version codecov PyPI - License OpenAPI Compatibility

Cicerone parses OpenAPI schemas into Pydantic models for introspection and traversal.

It's fast, minimal, fully typed, and pythonic.

Features

  • Tested at scale: We run tests against 4000+ real schemas from APIs.guru OpenAPI Directory.
  • Pydantic models: All models are type-safe.
  • Multiple input formats: Files, URLs, or in-memory data.
  • OpenAPI 3.x support: Works with OpenAPI 3.0 and 3.1 specifications.
  • Minimal dependencies: Just Pydantic and pyyaml. Everything else is stdlib.
  • Simple API: Easy to use, hard to misuse.
  • Modern Python: Fully typed with 100% test coverage.

Installation

pip

pip install cicerone

uv

uv add cicerone

Quick Start

Parsing Specifications

from cicerone import parse as cicerone_parse

# From a file
file_spec = cicerone_parse.parse_spec_from_file("openapi.yaml")

# From a URL
url_spec = cicerone_parse.parse_spec_from_url("https://api.example.com/openapi.json")

# From a dictionary
dict_spec = cicerone_parse.parse_spec_from_dict({"openapi": "3.0.0", ...})

# From JSON string
json_spec = cicerone_parse.parse_spec_from_json('{"openapi": "3.0.0", ...}')

# From YAML string
yaml_spec = cicerone_parse.parse_spec_from_yaml('openapi: "3.0.0"\n...')

Exploring the schema

from cicerone import parse as cicerone_parse

spec = cicerone_parse.parse_spec_from_file('tests/fixtures/petstore_openapi3.yaml')

print("OpenAPISpec:", spec)
>>> OpenAPISpec: <OpenAPISpec: 'Test API' v3.0.0, 2 paths, 2 schemas>

print("Paths:", spec.paths)
>>> Paths: <Paths: 2 paths, 3 operations [/users, /users/{userId}]>

print("PathItem:", spec.paths["/users"])
>>> PathItem: <PathItem: /users [GET, POST]>

print("Operation:", spec.operation_by_operation_id("listUsers"))
>>> Operation: <Operation: GET /users, id=listUsers, 'List all users', tags=['users']>

print("Components:", spec.components)
>>> Components: <Components: 2 schemas [User, Error]>

print("Schema:", spec.components.get_schema("User"))
>>> Schema: <Schema: type=object, 5 properties, required=['id', 'username', 'email']>

user = spec.components.get_schema("User")
print(f"User properties: {list(user.properties.keys())}")
>>> User properties: ['id', 'username', 'email', 'age', 'roles']

Resolving References

Resolve $ref references to their typed objects:

from cicerone import parse as cicerone_parse

spec = cicerone_parse.parse_spec_from_file('tests/fixtures/petstore_openapi3.yaml')

# Resolve a reference to get a typed Schema object
# follow_nested=True will recursively resolve all nested $refs
user_schema = spec.resolve_reference('#/components/schemas/User', follow_nested=True)
print(f"User schema type: {user_schema.type}")
>>> User schema type: object
print(f"Required fields: {user_schema.required}")
>>> Required fields: ['id', 'username', 'email']
Morty Proxy This is a proxified and sanitized view of the page, visit original site.