CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-bravado

Library for accessing Swagger-enabled APIs

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

configuration.mddocs/

Configuration

Flexible configuration system for both global bravado settings and per-request options. The configuration system supports response metadata customization, timeout configuration, callback mechanisms, and extensive behavioral controls.

Capabilities

BravadoConfig

Global configuration object that controls bravado's behavior across all requests. Uses a NamedTuple structure for type safety and immutability.

class BravadoConfig:
    also_return_response: bool
    disable_fallback_results: bool
    response_metadata_class: Type[BravadoResponseMetadata]
    sensitive_headers: list

Attributes:

  • also_return_response (bool): Whether operations should return BravadoResponse objects with metadata
  • disable_fallback_results (bool): Kill switch to disable fallback results even if provided
  • response_metadata_class (Type): Class to use for response metadata objects
  • sensitive_headers (list): List of header names to exclude from debug logs

RequestConfig

Per-request configuration that allows fine-grained control over individual API operations.

class RequestConfig:
    also_return_response: bool
    force_fallback_result: bool
    response_callbacks: list
    connect_timeout: float
    timeout: float
    headers: dict
    use_msgpack: bool
    additional_properties: dict
    def __init__(self, request_options: dict, also_return_response_default: bool): ...

Attributes:

  • also_return_response (bool): Override global setting for this request
  • force_fallback_result (bool): Force fallback result regardless of success
  • response_callbacks (list): Functions to call during response processing
  • connect_timeout (float): Connection timeout in seconds
  • timeout (float): Request timeout in seconds
  • headers (dict): Additional headers for this request
  • use_msgpack (bool): Use MessagePack encoding for request/response
  • additional_properties (dict): Custom properties for extensions

Usage Example:

from bravado.config import RequestConfig

# Create per-request configuration
request_config = RequestConfig({
    'timeout': 30.0,
    'headers': {'X-Custom-Header': 'value'},
    'use_msgpack': True
}, also_return_response_default=False)

# Use with operation
response = client.pet.getPetById(petId=1, _request_config=request_config).response()

Configuration Defaults

Default configuration values used when no explicit configuration is provided.

CONFIG_DEFAULTS: dict = {
    'also_return_response': False,
    'disable_fallback_results': False,
    'response_metadata_class': 'bravado.response.BravadoResponseMetadata',
    'sensitive_headers': ['Authorization']
}

These defaults provide sensible behavior for most use cases while allowing full customization.

Configuration Factory Function

Utility function to create BravadoConfig objects from dictionary configurations.

def bravado_config_from_config_dict(config_dict: dict) -> BravadoConfig: ...

Parameters:

  • config_dict (dict): Configuration dictionary with bravado settings

Returns:

  • BravadoConfig instance with validated settings

Usage Example:

from bravado.config import bravado_config_from_config_dict

config_dict = {
    'also_return_response': True,
    'disable_fallback_results': False,
    'sensitive_headers': ['Authorization', 'X-API-Key']
}

bravado_config = bravado_config_from_config_dict(config_dict)

Global Configuration

Configure bravado behavior globally when creating SwaggerClient instances:

from bravado.client import SwaggerClient

# Global configuration
config = {
    # Bravado-specific settings
    'also_return_response': True,
    'disable_fallback_results': False,
    'response_metadata_class': 'bravado.response.BravadoResponseMetadata',
    'sensitive_headers': ['Authorization', 'X-Secret-Key'],
    
    # bravado-core settings (validation, models, etc.)
    'validate_requests': True,
    'validate_responses': True,
    'use_models': True,
    'validate_swagger_spec': True,
    'formats': [],  # Custom format validators
}

client = SwaggerClient.from_url(spec_url, config=config)

Response Metadata Customization

You can provide a custom response metadata class:

from bravado.response import BravadoResponseMetadata

class CustomResponseMetadata(BravadoResponseMetadata):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.custom_field = "custom_value"
    
    @property
    def custom_property(self):
        return f"Request took {self.elapsed_time:.2f}s"

config = {
    'response_metadata_class': 'myapp.CustomResponseMetadata'
}

client = SwaggerClient.from_url(spec_url, config=config)

Per-Request Configuration

Override global settings for specific requests using RequestConfig:

from bravado.config import RequestConfig

# Timeout configuration
timeout_config = RequestConfig({
    'timeout': 60.0,  # 60 second timeout
    'connect_timeout': 10.0  # 10 second connection timeout
}, also_return_response_default=False)

# Custom headers
headers_config = RequestConfig({
    'headers': {
        'X-Request-ID': 'req-12345',
        'X-Client-Version': '1.0.0'
    }
}, also_return_response_default=False)

# Use configurations
response1 = client.pet.getPetById(petId=1, _request_config=timeout_config).response()
response2 = client.pet.addPet(body=pet_data, _request_config=headers_config).response()

Response Callbacks

Execute custom logic during response processing:

def log_request_time(response, operation):
    print(f"Operation {operation.operation_id} took {response.elapsed_time:.2f}s")

def validate_custom_header(response, operation):
    if 'X-Custom-Header' not in response.headers:
        print("Warning: Expected custom header missing")

callback_config = RequestConfig({
    'response_callbacks': [log_request_time, validate_custom_header]
}, also_return_response_default=True)

response = client.pet.getPetById(petId=1, _request_config=callback_config).response()

MessagePack Support

Use MessagePack encoding for better performance with large payloads:

msgpack_config = RequestConfig({
    'use_msgpack': True,
    'headers': {'Accept': 'application/msgpack'}
}, also_return_response_default=False)

# Request and response will use MessagePack encoding
response = client.pet.addPet(body=large_pet_data, _request_config=msgpack_config).response()

Advanced Configuration Patterns

Environment-Based Configuration

import os
from bravado.client import SwaggerClient

def create_client(spec_url):
    config = {
        'also_return_response': os.getenv('BRAVADO_RETURN_RESPONSE', 'false').lower() == 'true',
        'validate_requests': os.getenv('BRAVADO_VALIDATE_REQUESTS', 'true').lower() == 'true',
        'validate_responses': os.getenv('BRAVADO_VALIDATE_RESPONSES', 'true').lower() == 'true',
    }
    
    # Development vs production settings
    if os.getenv('ENVIRONMENT') == 'development':
        config.update({
            'validate_swagger_spec': True,
            'sensitive_headers': ['Authorization']  # More logging in dev
        })
    else:
        config.update({
            'validate_swagger_spec': False,  # Skip validation in production
            'sensitive_headers': ['Authorization', 'X-API-Key', 'Cookie']
        })
    
    return SwaggerClient.from_url(spec_url, config=config)

Profile-Based Configuration

from dataclasses import dataclass
from bravado.config import RequestConfig

@dataclass
class RequestProfile:
    timeout: float
    connect_timeout: float
    retries: int
    
    def to_request_config(self):
        return RequestConfig({
            'timeout': self.timeout,
            'connect_timeout': self.connect_timeout,
            'additional_properties': {'retries': self.retries}
        }, also_return_response_default=True)

# Define profiles
PROFILES = {
    'fast': RequestProfile(timeout=5.0, connect_timeout=2.0, retries=1),
    'standard': RequestProfile(timeout=30.0, connect_timeout=10.0, retries=3),
    'slow': RequestProfile(timeout=120.0, connect_timeout=30.0, retries=5)
}

# Use profiles
fast_config = PROFILES['fast'].to_request_config()
response = client.pet.getPetById(petId=1, _request_config=fast_config).response()

Configuration Validation

from bravado.config import bravado_config_from_config_dict

def validate_config(config_dict):
    """Validate configuration before creating client."""
    required_keys = ['also_return_response', 'validate_requests']
    
    for key in required_keys:
        if key not in config_dict:
            raise ValueError(f"Missing required config key: {key}")
    
    if config_dict.get('timeout', 0) <= 0:
        raise ValueError("Timeout must be positive")
    
    return bravado_config_from_config_dict(config_dict)

# Use validation
try:
    config = validate_config({
        'also_return_response': True,
        'validate_requests': True,
        'timeout': 30.0
    })
    client = SwaggerClient.from_url(spec_url, config=config._asdict())
except ValueError as e:
    print(f"Configuration error: {e}")

Configuration Best Practices

  1. Use Environment Variables: Configure behavior based on deployment environment
  2. Validate Early: Validate configuration at startup, not during requests
  3. Profile-Based Settings: Create reusable configuration profiles for different use cases
  4. Sensitive Data: Properly configure sensitive_headers to avoid logging credentials
  5. Timeout Strategy: Set appropriate timeouts based on your application's requirements
  6. Development vs Production: Use different validation settings for different environments
# Good configuration example
import os
from bravado.client import SwaggerClient
from bravado.requests_client import RequestsClient

def create_production_client(spec_url):
    # Production-optimized HTTP client
    http_client = RequestsClient(
        ssl_verify=True,  # Always verify SSL in production
    )
    
    # Production configuration
    config = {
        'also_return_response': True,  # Always get metadata for monitoring
        'validate_requests': True,     # Validate requests to catch issues early
        'validate_responses': False,   # Skip response validation for performance
        'validate_swagger_spec': False, # Skip spec validation for startup performance
        'sensitive_headers': [         # Comprehensive sensitive header list
            'Authorization', 'X-API-Key', 'Cookie', 
            'X-Auth-Token', 'X-Session-ID'
        ]
    }
    
    return SwaggerClient.from_url(spec_url, http_client=http_client, config=config)

def create_development_client(spec_url):
    config = {
        'also_return_response': True,
        'validate_requests': True,     # Full validation in development
        'validate_responses': True,
        'validate_swagger_spec': True,
        'sensitive_headers': ['Authorization']  # Minimal for easier debugging
    }
    
    return SwaggerClient.from_url(spec_url, config=config)

# Use environment-based client creation
if os.getenv('ENVIRONMENT') == 'production':
    client = create_production_client(spec_url)
else:
    client = create_development_client(spec_url)

Install with Tessl CLI

npx tessl i tessl/pypi-bravado

docs

authentication.md

client-management.md

configuration.md

exception-handling.md

http-clients.md

index.md

response-handling.md

spec-loading.md

testing-utilities.md

tile.json