un-inception/clients/python/scripts/validate-examples.sh
russell@unturf.com 75f687f12f feat: Complete Python and C SDK implementations with examples and pipeline integration
Python Sync SDK (clients/python/sync/):
- 712 lines core implementation with 13 public APIs
- HMAC-SHA256 authentication with OpenSSL
- 4-tier credential system (args > env > ~/.unsandbox > ./accounts.csv)
- Language caching with 1-hour TTL
- 64+ comprehensive unit tests
- Full documentation (README, USAGE, IMPLEMENTATION)

Python Async SDK (clients/python/async/):
- 705 lines async implementation using aiohttp
- Full async/await pattern support
- Exponential backoff polling strategy
- 200+ test cases with ~95% coverage
- 7 working async examples
- 5 documentation guides

C SDK (clients/c/):
- 823 lines C implementation
- Header file with 15 public functions
- OpenSSL HMAC-SHA256 + libcurl HTTP client
- Language detection for 48 file extensions
- 22/22 tests passing
- Proper memory management

Examples:
- 14 Python examples (7 sync, 7 async) with docstrings
- 4 C examples (hello_world, fibonacci, error_handling, credentials)
- All examples ready for pipeline validation
- Expected outputs documented for validation

Pipeline Integration:
- Updated .gitlab-ci.yml with gcc/musl-dev for C compilation
- Enhanced validate-examples.sh with C compilation support
- Updated detect-changes.sh to recognize python/c changes
- Updated generate-matrix.sh with python/c in matrix
- E2E tests updated with mock Python/C examples
- All tests passing (30+ test cases)

Documentation:
- PYTHON_C_INTEGRATION_SUMMARY.md (452 lines)
- Complete API references for both SDKs
- Quick start guides
- Pattern documentation
- Error handling guides
2026-01-15 16:42:58 -05:00

235 lines
7.9 KiB
Bash
Executable file

#!/bin/bash
##
# Validation script for Python SDK examples
#
# This script validates that all example files exist and have proper structure.
# It does NOT require credentials to run - it only checks syntax and structure.
#
# Usage:
# bash scripts/validate-examples.sh
#
# With actual credentials to test execution:
# UNSANDBOX_PUBLIC_KEY=... UNSANDBOX_SECRET_KEY=... bash scripts/validate-examples.sh --run
##
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SYNC_EXAMPLES="$PROJECT_ROOT/sync/examples"
ASYNC_EXAMPLES="$PROJECT_ROOT/async/examples"
SYNC_SRC="$PROJECT_ROOT/sync/src"
ASYNC_SRC="$PROJECT_ROOT/async/src"
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Counters
TOTAL_CHECKS=0
PASSED_CHECKS=0
FAILED_CHECKS=0
RUN_TESTS="${1:-}"
echo "=== Python SDK Examples Validation ==="
echo ""
##
# Check if file exists and is readable
##
check_file_exists() {
local file="$1"
local description="$2"
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
if [[ -f "$file" && -r "$file" ]]; then
echo -e "${GREEN}${NC} $description: $file"
PASSED_CHECKS=$((PASSED_CHECKS + 1))
return 0
else
echo -e "${RED}${NC} $description: $file (not found or not readable)"
FAILED_CHECKS=$((FAILED_CHECKS + 1))
return 1
fi
}
##
# Check if file contains expected string
##
check_file_contains() {
local file="$1"
local pattern="$2"
local description="$3"
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
if grep -q "$pattern" "$file"; then
echo -e "${GREEN}${NC} $description: $file"
PASSED_CHECKS=$((PASSED_CHECKS + 1))
return 0
else
echo -e "${RED}${NC} $description: $file (pattern not found: $pattern)"
FAILED_CHECKS=$((FAILED_CHECKS + 1))
return 1
fi
}
##
# Check Python syntax
##
check_syntax() {
local file="$1"
local description="$2"
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
if python3 -m py_compile "$file" 2>/dev/null; then
echo -e "${GREEN}${NC} $description: $file"
PASSED_CHECKS=$((PASSED_CHECKS + 1))
return 0
else
echo -e "${RED}${NC} $description: $file (syntax error)"
FAILED_CHECKS=$((FAILED_CHECKS + 1))
return 1
fi
}
##
# Try to run example (only if credentials provided)
##
run_example() {
local file="$1"
local description="$2"
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
if [[ -z "${UNSANDBOX_PUBLIC_KEY:-}" ]] || [[ -z "${UNSANDBOX_SECRET_KEY:-}" ]]; then
echo -e "${YELLOW}${NC} $description: $file (skipped - no credentials)"
return 0
fi
# Set timeout to 30 seconds per example
if timeout 30s python3 "$file" > /dev/null 2>&1; then
echo -e "${GREEN}${NC} $description: $file"
PASSED_CHECKS=$((PASSED_CHECKS + 1))
return 0
else
echo -e "${RED}${NC} $description: $file (execution failed)"
FAILED_CHECKS=$((FAILED_CHECKS + 1))
return 1
fi
}
echo "=== SDK Source Files ==="
check_file_exists "$SYNC_SRC/un.py" "Sync SDK module"
check_file_exists "$ASYNC_SRC/un_async.py" "Async SDK module"
echo ""
echo "=== Synchronous Examples ==="
echo "--- Basic Examples ---"
check_file_exists "$SYNC_EXAMPLES/hello_world.py" "Raw code snippet"
check_file_exists "$SYNC_EXAMPLES/hello_world_client.py" "SDK client wrapper"
check_file_contains "$SYNC_EXAMPLES/hello_world_client.py" "execute_code" "Contains execute_code"
check_syntax "$SYNC_EXAMPLES/hello_world_client.py" "Syntax check"
echo "--- Computational Examples ---"
check_file_exists "$SYNC_EXAMPLES/fibonacci.py" "Raw code snippet"
check_file_exists "$SYNC_EXAMPLES/fibonacci_client.py" "SDK client wrapper"
check_file_contains "$SYNC_EXAMPLES/fibonacci_client.py" "def fib" "Contains fib function"
check_syntax "$SYNC_EXAMPLES/fibonacci_client.py" "Syntax check"
echo "--- Data Processing Examples ---"
check_file_exists "$SYNC_EXAMPLES/http_request.py" "HTTP request example"
check_file_contains "$SYNC_EXAMPLES/http_request.py" "requests" "Uses requests library"
check_syntax "$SYNC_EXAMPLES/http_request.py" "Syntax check"
check_file_exists "$SYNC_EXAMPLES/json_processing.py" "JSON processing example"
check_file_contains "$SYNC_EXAMPLES/json_processing.py" "json.loads" "Parses JSON"
check_syntax "$SYNC_EXAMPLES/json_processing.py" "Syntax check"
check_file_exists "$SYNC_EXAMPLES/file_operations.py" "File operations example"
check_file_contains "$SYNC_EXAMPLES/file_operations.py" "open(" "Uses file I/O"
check_syntax "$SYNC_EXAMPLES/file_operations.py" "Syntax check"
echo ""
echo "=== Asynchronous Examples ==="
echo "--- Basic Examples ---"
check_file_exists "$ASYNC_EXAMPLES/hello_world_async.py" "SDK client wrapper"
check_file_contains "$ASYNC_EXAMPLES/hello_world_async.py" "async def" "Contains async function"
check_syntax "$ASYNC_EXAMPLES/hello_world_async.py" "Syntax check"
echo "--- Concurrent Computation ---"
check_file_exists "$ASYNC_EXAMPLES/fibonacci_async.py" "Fibonacci async example"
check_file_contains "$ASYNC_EXAMPLES/fibonacci_async.py" "asyncio.gather" "Uses asyncio.gather"
check_syntax "$ASYNC_EXAMPLES/fibonacci_async.py" "Syntax check"
echo "--- Network Examples ---"
check_file_exists "$ASYNC_EXAMPLES/concurrent_requests.py" "Concurrent requests example"
check_file_contains "$ASYNC_EXAMPLES/concurrent_requests.py" "httpbin.org" "Uses HTTP endpoints"
check_syntax "$ASYNC_EXAMPLES/concurrent_requests.py" "Syntax check"
echo "--- Stream Processing ---"
check_file_exists "$ASYNC_EXAMPLES/stream_processing.py" "Stream processing example"
check_file_contains "$ASYNC_EXAMPLES/stream_processing.py" "stream_generator" "Uses generators"
check_syntax "$ASYNC_EXAMPLES/stream_processing.py" "Syntax check"
echo "--- Job Management ---"
check_file_exists "$ASYNC_EXAMPLES/async_job_polling.py" "Job polling example"
check_file_contains "$ASYNC_EXAMPLES/async_job_polling.py" "wait_for_job" "Handles job polling"
check_syntax "$ASYNC_EXAMPLES/async_job_polling.py" "Syntax check"
check_file_exists "$ASYNC_EXAMPLES/concurrent_execution.py" "Concurrent execution example"
check_file_contains "$ASYNC_EXAMPLES/concurrent_execution.py" "asyncio.gather" "Uses asyncio.gather"
check_syntax "$ASYNC_EXAMPLES/concurrent_execution.py" "Syntax check"
check_file_exists "$ASYNC_EXAMPLES/sync_blocking_usage.py" "Sync/blocking usage example"
check_file_contains "$ASYNC_EXAMPLES/sync_blocking_usage.py" "detect_language" "Uses helper functions"
check_syntax "$ASYNC_EXAMPLES/sync_blocking_usage.py" "Syntax check"
echo ""
##
# Documentation checks
##
echo "=== Documentation ==="
check_file_exists "$PROJECT_ROOT/EXAMPLES.md" "Examples documentation"
check_file_contains "$PROJECT_ROOT/EXAMPLES.md" "Synchronous Examples" "Documents sync examples"
check_file_contains "$PROJECT_ROOT/EXAMPLES.md" "Asynchronous Examples" "Documents async examples"
echo ""
##
# Optional execution tests
##
if [[ "$RUN_TESTS" == "--run" ]]; then
echo "=== Execution Tests (Credentials Required) ==="
if [[ -z "${UNSANDBOX_PUBLIC_KEY:-}" ]] || [[ -z "${UNSANDBOX_SECRET_KEY:-}" ]]; then
echo -e "${YELLOW}${NC} Credentials not provided, skipping execution tests"
echo " Set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY to enable"
else
echo "Running with credentials..."
run_example "$SYNC_EXAMPLES/hello_world_client.py" "Sync hello world"
run_example "$SYNC_EXAMPLES/fibonacci_client.py" "Sync fibonacci"
run_example "$ASYNC_EXAMPLES/hello_world_async.py" "Async hello world"
fi
echo ""
fi
##
# Summary
##
echo "=== Summary ==="
TOTAL=$((PASSED_CHECKS + FAILED_CHECKS))
echo "Checks: $TOTAL"
echo -e "Passed: ${GREEN}$PASSED_CHECKS${NC}"
echo -e "Failed: ${RED}$FAILED_CHECKS${NC}"
echo ""
if [[ $FAILED_CHECKS -eq 0 ]]; then
echo -e "${GREEN}✓ All validations passed!${NC}"
exit 0
else
echo -e "${RED}✗ Some validations failed!${NC}"
exit 1
fi