OpenAPI 3 Specification Client and Validator
openapi3 is a Python library designed to act as both a client and validator for OpenAPI 3 Specifications. It allows developers to load OpenAPI specification files (YAML or JSON), parse them into Python objects, validate the specification's structure, and interact with the described API by calling defined operations. The library aims to provide an interactive client experience, handling authentication and parameter passing. The current version is 1.8.2, and releases are made as features are developed and bugs are fixed, though a strict cadence isn't published. The project's roadmap indicates ongoing development for richer model and parameter handling.
Common errors
-
ModuleNotFoundError: No module named 'openapi3'
cause The `openapi3` library has not been installed in your Python environment.fixInstall the library using pip: `pip install openapi3` -
yaml.scanner.ScannerError: while scanning for the next token
cause The OpenAPI specification file (YAML) is malformed or contains syntax errors.fixValidate your `openapi.yaml` file using an online YAML validator or an OpenAPI linter (e.g., `spectral lint`). Ensure correct indentation and syntax. -
AttributeError: 'OpenAPI' object has no attribute 'call_yourOperationId'
cause You are attempting to call an operation (`call_yourOperationId`) that is not defined with a unique `operationId` in your OpenAPI specification, or the `operationId` is misspelled. The library dynamically creates methods based on these IDs.fixVerify that each operation (e.g., GET, POST) in your OpenAPI spec has a unique `operationId` defined and that you are calling the corresponding `call_` method with the correct casing and spelling. For example, an `operationId: getMyResource` would be called as `api.call_getMyResource()`. -
KeyError: 'securitySchemes'
cause You are trying to authenticate using a security scheme that is not defined under `components.securitySchemes` in your OpenAPI specification, or the name used in `api.authenticate()` does not match the definition.fixCheck your OpenAPI specification to ensure that the security scheme (e.g., `personalAccessToken`) is correctly defined under `components.securitySchemes` and that the name passed to `api.authenticate()` matches exactly.
Warnings
- gotcha The `openapi3` library's roadmap indicates that advanced features like automatic request body model generation, explicit parameter typing, and comprehensive validation for requests/responses are ongoing or future work. Users expecting full ORM-like model generation or strict runtime validation for request/response bodies and complex parameters might find current capabilities limited, requiring manual handling or external validation.
- gotcha The library returns models that are 'of the same (generated) type' (e.g., `openapi.schemas.YourSchemaName`). While this provides a consistent interface, users expecting distinct Python classes generated for each specific schema definition in their OpenAPI spec might find the type introspection or direct attribute access less intuitive without understanding the underlying generated structure.
- gotcha While `openapi3` supports OpenAPI 3 specifications, the broader ecosystem has seen updates (e.g., OpenAPI 3.1). Using a specification version not fully supported by `openapi3` or containing advanced features from newer drafts might lead to parsing errors or unexpected behavior. The library specifically targets OpenAPI 3, not older Swagger 2.x specifications.
Install
-
pip install openapi3
Imports
- OpenAPI
from openapi3 import OpenAPI
Quickstart
import os
import yaml
from openapi3 import OpenAPI
# Example OpenAPI 3.0 Specification (simplified for demonstration)
# In a real scenario, load this from a file or URL.
spec_content = """
openapi: 3.0.0
info:
title: Example API
version: 1.0.0
paths:
/regions:
get:
operationId: getRegions
summary: Get available regions
responses:
'200':
description: A list of regions
content:
application/json:
schema:
type: array
items:
type: string
/secure-data:
get:
operationId: getSecureData
summary: Get secure data
security:
- personalAccessToken: []
responses:
'200':
description: Secure data
content:
application/json:
schema:
type: object
properties:
data:
type: string
components:
securitySchemes:
personalAccessToken:
type: http
scheme: bearer
bearerFormat: JWT
"""
# Load the spec (e.g., from a string, or a file)
spec = yaml.safe_load(spec_content)
# Parse the spec into a Python object
api = OpenAPI(spec)
# Call an operation that does not require authentication
try:
regions = api.call_getRegions()
print(f"Available regions: {regions}")
except Exception as e:
print(f"Error calling getRegions: {e}")
# Authenticate for operations that require it
my_token = os.environ.get('API_BEARER_TOKEN', 'YOUR_SUPER_SECRET_TOKEN')
if my_token == 'YOUR_SUPER_SECRET_TOKEN':
print("Warning: Please set the API_BEARER_TOKEN environment variable for authentication.")
# Note: The `authenticate` method expects the security scheme name and the credentials.
# For 'http' 'bearer', it typically expects the token string directly.
# The example in docs uses `api.authenticate('personalAccessToken', my_token)` for a bearer token.
# However, the exact usage might depend on how the spec defines the security scheme
# and how the `openapi3` library interprets it.
# As per the library's docs, `api.authenticate('personalAccessToken', my_token)` is correct for bearer.
if my_token:
try:
api.authenticate('personalAccessToken', my_token)
secure_data = api.call_getSecureData()
print(f"Secure data: {secure_data}")
except Exception as e:
print(f"Error calling getSecureData: {e}")
else:
print("Skipping authenticated call as API_BEARER_TOKEN is not set.")