CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-apispec

A pluggable API specification generator for OpenAPI/Swagger specifications

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

utils.mddocs/

Utilities and YAML Support

Utility functions for OpenAPI reference building, docstring processing, dictionary manipulation, and YAML serialization with docstring parsing capabilities. These utilities support the core APISpec functionality and provide helpers for common OpenAPI operations.

Capabilities

Reference Building

Build OpenAPI reference objects for component linking and reusability.

def build_reference(
    component_type: str,
    openapi_major_version: int, 
    component_name: str
) -> dict[str, str]:
    """
    Build OpenAPI reference object for a component.
    
    Parameters:
    - component_type: Type of component ('schema', 'parameter', 'response', 'header', 'example', 'security_scheme')
    - openapi_major_version: OpenAPI major version (2 or 3)
    - component_name: Name of the component to reference
    
    Returns:
    Dictionary with $ref key pointing to the component location
    
    Examples:
    - OpenAPI 2.x: {"$ref": "#/definitions/User"}
    - OpenAPI 3.x: {"$ref": "#/components/schemas/User"}
    """

Docstring Processing

Process and clean docstrings for use in OpenAPI documentation.

def trim_docstring(docstring: str) -> str:
    """
    Uniformly trim leading/trailing whitespace from docstrings.
    
    Parameters:
    - docstring: Raw docstring text
    
    Returns:
    Cleaned docstring with consistent indentation removed
    
    Based on PEP 257 docstring handling conventions.
    """

def dedent(content: str) -> str:
    """
    Remove leading indent from a block of text.
    
    Parameters:
    - content: Text content with potential leading indentation
    
    Returns:
    Text with consistent leading indentation removed
    
    Used for processing multiline docstrings and descriptions.
    More robust than textwrap.dedent for mixed indentation patterns.
    """

Dictionary Manipulation

Utility for deep dictionary updates and merging.

def deepupdate(original: dict, update: dict) -> dict:
    """
    Recursively update a dictionary without overwriting nested dictionaries.
    
    Parameters:
    - original: Original dictionary to update
    - update: Dictionary containing updates
    
    Returns:
    Updated dictionary with deep merging of nested structures
    
    Nested dictionaries are merged rather than replaced entirely.
    """

YAML Serialization

Convert dictionaries to YAML format with OpenAPI-optimized settings.

def dict_to_yaml(dic: dict, yaml_dump_kwargs: Any | None = None) -> str:
    """
    Serialize dictionary to YAML string.
    
    Parameters:
    - dic: Dictionary to serialize
    - yaml_dump_kwargs: Additional arguments passed to yaml.dump()
    
    Returns:
    YAML string representation
    
    Default behavior preserves key ordering (sort_keys=False) to respect
    schema field ordering in OpenAPI specifications.
    """

Docstring YAML Parsing

Extract YAML content and OpenAPI operations from function docstrings.

def load_yaml_from_docstring(docstring: str) -> dict:
    """
    Load YAML content from docstring.
    
    Parameters:
    - docstring: Function or method docstring
    
    Returns:
    Dictionary parsed from YAML section of docstring
    
    Looks for YAML content after '---' delimiter in docstring.
    Returns empty dict if no YAML section found.
    """

def load_operations_from_docstring(docstring: str) -> dict:
    """
    Extract OpenAPI operations from docstring YAML.
    
    Parameters:
    - docstring: Function or method docstring containing YAML
    
    Returns:
    Dictionary mapping HTTP methods to operation definitions
    
    Filters YAML content to only include valid HTTP methods and x- extensions.
    """

Constants

Configuration constants for OpenAPI specification structure.

COMPONENT_SUBSECTIONS: dict[int, dict[str, str]] = {
    2: {
        "schema": "definitions",
        "response": "responses", 
        "parameter": "parameters",
        "security_scheme": "securityDefinitions"
    },
    3: {
        "schema": "schemas",
        "response": "responses",
        "parameter": "parameters", 
        "header": "headers",
        "example": "examples",
        "security_scheme": "securitySchemes"
    }
}

PATH_KEYS: set[str] = {"get", "put", "post", "delete", "options", "head", "patch"}

Usage Examples

Building References

from apispec.utils import build_reference

# OpenAPI 3.x references
schema_ref = build_reference("schema", 3, "User")
# {"$ref": "#/components/schemas/User"}

param_ref = build_reference("parameter", 3, "UserId") 
# {"$ref": "#/components/parameters/UserId"}

# OpenAPI 2.x references  
schema_ref_v2 = build_reference("schema", 2, "User")
# {"$ref": "#/definitions/User"}

response_ref_v2 = build_reference("response", 2, "NotFound")
# {"$ref": "#/responses/NotFound"}

Processing Docstrings

from apispec.utils import trim_docstring, dedent

# Clean up docstring formatting
raw_docstring = '''
    This is a function that does something important.
    
        It has multiple lines with inconsistent indentation.
        
    Returns:
        Something useful
'''

cleaned = trim_docstring(raw_docstring)
# "This is a function that does something important.\n\n    It has multiple lines with inconsistent indentation.\n\nReturns:\n    Something useful"

dedented = dedent(cleaned)
# "This is a function that does something important.\n\nIt has multiple lines with inconsistent indentation.\n\nReturns:\nSomething useful"

Dictionary Updates

from apispec.utils import deepupdate

original = {
    "info": {"title": "My API"},
    "paths": {
        "/users": {
            "get": {"summary": "List users"}
        }
    }
}

update = {
    "info": {"version": "1.0.0", "description": "API description"},
    "paths": {
        "/users": {
            "post": {"summary": "Create user"}
        }
    }
}

result = deepupdate(original, update)
# {
#     "info": {"title": "My API", "version": "1.0.0", "description": "API description"},
#     "paths": {
#         "/users": {
#             "get": {"summary": "List users"},
#             "post": {"summary": "Create user"}
#         }
#     }
# }

YAML Operations

from apispec.yaml_utils import dict_to_yaml, load_operations_from_docstring

# Convert specification to YAML
spec_dict = {"openapi": "3.0.2", "info": {"title": "API", "version": "1.0.0"}}
yaml_output = dict_to_yaml(spec_dict)

# Custom YAML formatting
yaml_sorted = dict_to_yaml(spec_dict, {"sort_keys": True, "indent": 4})

Extracting Operations from Docstrings

from apispec.yaml_utils import load_operations_from_docstring

def get_user(user_id):
    """Get user by ID.
    ---
    get:
      summary: Retrieve user information
      parameters:
        - name: user_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        200:
          description: User found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        404:
          description: User not found
    """
    pass

# Extract operations from docstring  
operations = load_operations_from_docstring(get_user.__doc__)
# {
#     "get": {
#         "summary": "Retrieve user information",
#         "parameters": [...],
#         "responses": {...}
#     }
# }

# Use with APISpec
spec.path("/users/{user_id}", operations=operations)

Framework Integration Helper

from apispec.yaml_utils import load_operations_from_docstring
from apispec.utils import trim_docstring

def extract_openapi_from_view(view_function):
    """Helper to extract OpenAPI spec from framework view function."""
    if not view_function.__doc__:
        return {}
    
    # Clean and parse docstring
    cleaned_doc = trim_docstring(view_function.__doc__)
    operations = load_operations_from_docstring(cleaned_doc)
    
    # Add operation ID if not specified
    for method, operation in operations.items():
        operation.setdefault('operationId', f"{method}_{view_function.__name__}")
    
    return operations

# Usage in framework plugin
class FrameworkPlugin(BasePlugin):
    def operation_helper(self, path=None, operations=None, **kwargs):
        view_function = kwargs.get('view_function')
        if view_function and operations:
            doc_operations = extract_openapi_from_view(view_function)
            operations.update(doc_operations)

Exception Classes

All utility functions may raise APISpec-related exceptions for error conditions.

class APISpecError(Exception):
    """Base class for all apispec-related errors."""

class OpenAPIError(APISpecError):
    """Raised when OpenAPI spec validation fails."""

Install with Tessl CLI

npx tessl i tessl/pypi-apispec

docs

components.md

core-spec.md

index.md

marshmallow.md

plugin-system.md

utils.md

tile.json