#!/bin/bash # Generate Python client from OpenAPI spec # This script downloads the OpenAPI spec from the running API server # and generates a Python client using openapi-python-client set -e # Configuration API_URL="${ATTUNE_API_URL:-http://localhost:8080}" OPENAPI_SPEC_URL="${API_URL}/api-spec/openapi.json" OUTPUT_DIR="tests/generated_client" TEMP_SPEC="/tmp/attune-openapi.json" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color echo -e "${BLUE}=== Attune Python Client Generator ===${NC}" echo "" # Check if openapi-python-client is installed OPENAPI_CLIENT_CMD="tests/venvs/e2e/bin/openapi-python-client" if [ ! -f "${OPENAPI_CLIENT_CMD}" ]; then echo -e "${YELLOW}openapi-python-client not found. Installing...${NC}" if [ -d "tests/venvs/e2e" ]; then tests/venvs/e2e/bin/pip install openapi-python-client else echo -e "${RED}ERROR: E2E venv not found. Please create it first.${NC}" exit 1 fi echo "" fi # Check if API is running echo -e "${BLUE}Checking API availability at ${API_URL}...${NC}" if ! curl -s -f "${API_URL}/health" > /dev/null; then echo -e "${RED}ERROR: API is not running at ${API_URL}${NC}" echo "Please start the API service first:" echo " cd tests && ./start_e2e_services.sh" exit 1 fi echo -e "${GREEN}✓ API is running${NC}" echo "" # Download OpenAPI spec echo -e "${BLUE}Downloading OpenAPI spec from ${OPENAPI_SPEC_URL}...${NC}" if ! curl -s -f "${OPENAPI_SPEC_URL}" -o "${TEMP_SPEC}"; then echo -e "${RED}ERROR: Failed to download OpenAPI spec${NC}" echo "Make sure the API is running and the spec endpoint is available" exit 1 fi echo -e "${GREEN}✓ OpenAPI spec downloaded${NC}" echo "" # Validate JSON echo -e "${BLUE}Validating OpenAPI spec...${NC}" if ! jq empty "${TEMP_SPEC}" 2>/dev/null; then echo -e "${RED}ERROR: Invalid JSON in OpenAPI spec${NC}" cat "${TEMP_SPEC}" exit 1 fi echo -e "${GREEN}✓ OpenAPI spec is valid${NC}" echo "" # Show spec info SPEC_TITLE=$(jq -r '.info.title' "${TEMP_SPEC}") SPEC_VERSION=$(jq -r '.info.version' "${TEMP_SPEC}") PATH_COUNT=$(jq '.paths | length' "${TEMP_SPEC}") echo -e "${BLUE}API Info:${NC}" echo " Title: ${SPEC_TITLE}" echo " Version: ${SPEC_VERSION}" echo " Endpoints: ${PATH_COUNT}" echo "" # Remove old generated client if it exists if [ -d "${OUTPUT_DIR}" ]; then echo -e "${YELLOW}Removing old generated client...${NC}" rm -rf "${OUTPUT_DIR}" fi # Generate Python client echo -e "${BLUE}Generating Python client...${NC}" "${OPENAPI_CLIENT_CMD}" generate \ --path "${TEMP_SPEC}" \ --output-path "${OUTPUT_DIR}" \ --overwrite \ --meta none if [ $? -ne 0 ]; then echo -e "${RED}ERROR: Client generation failed${NC}" exit 1 fi echo -e "${GREEN}✓ Python client generated${NC}" echo "" # Install the generated client echo -e "${BLUE}Installing generated client into E2E venv...${NC}" if [ -d "tests/venvs/e2e" ]; then tests/venvs/e2e/bin/pip install -e "${OUTPUT_DIR}" --quiet echo -e "${GREEN}✓ Client installed${NC}" else echo -e "${YELLOW}WARNING: E2E venv not found, skipping installation${NC}" echo "Run this to install manually:" echo " tests/venvs/e2e/bin/pip install -e ${OUTPUT_DIR}" fi echo "" # Clean up rm -f "${TEMP_SPEC}" # Create a simple usage example cat > "${OUTPUT_DIR}/USAGE.md" << 'EOF' # Attune Python Client Usage This client was auto-generated from the Attune OpenAPI specification. ## Installation ```bash pip install -e tests/generated_client ``` ## Basic Usage ```python from attune_client import Client from attune_client.api.auth import login from attune_client.models import LoginRequest # Create client client = Client(base_url="http://localhost:8080") # Login login_request = LoginRequest( login="test@attune.local", password="TestPass123!" ) response = login.sync(client=client, json_body=login_request) token = response.data.access_token # Use authenticated client client = Client( base_url="http://localhost:8080", token=token ) # List packs from attune_client.api.packs import list_packs packs = list_packs.sync(client=client) print(f"Found {len(packs.data)} packs") ``` ## Async Usage All API calls have async equivalents: ```python import asyncio from attune_client import Client from attune_client.api.packs import list_packs async def main(): client = Client(base_url="http://localhost:8080", token="your-token") packs = await list_packs.asyncio(client=client) print(f"Found {len(packs.data)} packs") asyncio.run(main()) ``` ## Regenerating To regenerate the client after API changes: ```bash ./scripts/generate-python-client.sh ``` EOF echo -e "${GREEN}=== Client Generation Complete ===${NC}" echo "" echo "Generated client location: ${OUTPUT_DIR}" echo "Usage guide: ${OUTPUT_DIR}/USAGE.md" echo "" echo "To use the client in tests:" echo " from attune_client import Client" echo " from attune_client.api.packs import list_packs" echo "" echo -e "${BLUE}Next steps:${NC}" echo " 1. Review the generated client in ${OUTPUT_DIR}" echo " 2. Update test fixtures to use the generated client" echo " 3. Remove manual client code in tests/helpers/client.py" echo ""