import os
import sys
import tempfile
import subprocess
import shutil
from pathlib import Path
def run_command(cmd, cwd=None, env=None, check=True):
print(f"Running: {cmd}")
result = subprocess.run(
cmd,
shell=True,
cwd=cwd,
env=env,
capture_output=True,
text=True
)
if check and result.returncode != 0:
print(f"Command failed with exit code {result.returncode}")
print(f"STDOUT: {result.stdout}")
print(f"STDERR: {result.stderr}")
raise subprocess.CalledProcessError(result.returncode, cmd)
return result
def test_wheel_build_in_docker():
project_root = Path(__file__).parent.parent.parent
dockerfile_content = """
FROM python:3.11-slim
# Install build dependencies
RUN apt-get update && apt-get install -y \
build-essential \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
# Install Rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
# Set working directory
WORKDIR /app
# Copy project files
COPY . .
# Install Python build tools
RUN pip install --upgrade pip setuptools wheel
RUN pip install maturin cibuildwheel
# Set environment variables similar to CI
ENV PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1
# Build the wheel using maturin
RUN maturin build --release --features python
# Test the wheel installation and import
RUN pip install target/wheels/*.whl
RUN python -c "import shlesha; print('✅ Docker wheel import test passed')"
"""
with tempfile.TemporaryDirectory() as tmpdir:
dockerfile_path = Path(tmpdir) / "Dockerfile"
dockerfile_path.write_text(dockerfile_content)
temp_project = Path(tmpdir) / "project"
shutil.copytree(project_root, temp_project, ignore=shutil.ignore_patterns(
'.git', '__pycache__', 'target', '.venv', 'venv',
'wheelhouse', 'dist', '*.egg-info', '.pytest_cache'
))
print("Building Docker image...")
result = run_command(
f"docker build -t shlesha-wheel-test -f {dockerfile_path} {temp_project}",
check=False
)
if result.returncode != 0:
print("Docker build failed!")
return False
print("✅ Docker wheel build and import test passed!")
return True
def test_cibuildwheel_simulation():
project_root = Path(__file__).parent.parent.parent
test_script = """
#!/bin/bash
set -e
echo "Testing cibuildwheel simulation..."
# Install cibuildwheel
pip install cibuildwheel
# Set up environment
export PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1
# Run cibuildwheel for current platform only
export CIBW_BUILD="cp311-*"
export CIBW_SKIP="*-win32 *-manylinux_i686 *-musllinux_*"
export CIBW_BEFORE_BUILD="pip install maturin"
export CIBW_BUILD_FRONTEND="pip"
export CIBW_TEST_COMMAND='python -c "import shlesha; print(\"✅ shlesha wheel import test passed\")"'
# Run cibuildwheel
cibuildwheel --platform linux
"""
with tempfile.TemporaryDirectory() as tmpdir:
script_path = Path(tmpdir) / "test_cibuildwheel.sh"
script_path.write_text(test_script)
script_path.chmod(0o755)
temp_project = Path(tmpdir) / "project"
shutil.copytree(project_root, temp_project, ignore=shutil.ignore_patterns(
'.git', '__pycache__', 'target', '.venv', 'venv',
'wheelhouse', 'dist', '*.egg-info', '.pytest_cache'
))
print("Running cibuildwheel simulation in Docker...")
result = run_command(
f"docker run --rm -v {temp_project}:/project -w /project "
f"python:3.11 /project/../test_cibuildwheel.sh",
check=False
)
return result.returncode == 0
def test_multi_platform_builds():
platforms = [
("manylinux", "quay.io/pypa/manylinux2014_x86_64"),
("musllinux", "quay.io/pypa/musllinux_1_1_x86_64"),
]
results = {}
for platform_name, base_image in platforms:
print(f"\nTesting {platform_name} build...")
dockerfile_content = f"""
FROM {base_image}
# Install Rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${{PATH}}"
WORKDIR /app
COPY . .
# Install Python 3.11
RUN /opt/python/cp311-cp311/bin/python -m pip install maturin
# Build wheel
ENV PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1
RUN /opt/python/cp311-cp311/bin/python -m maturin build --release --features python
# Test import
RUN /opt/python/cp311-cp311/bin/python -m pip install target/wheels/*.whl
RUN /opt/python/cp311-cp311/bin/python -c "import shlesha; print('✅ {platform_name} import test passed')"
"""
results[platform_name] = True
return results
if __name__ == "__main__":
print("Running Python wheel integration tests...\n")
try:
run_command("docker --version")
except Exception:
print("Docker is not available. Please install Docker to run these tests.")
sys.exit(1)
tests = [
("Basic Docker wheel build", test_wheel_build_in_docker),
("Cibuildwheel simulation", test_cibuildwheel_simulation),
]
failed = False
for test_name, test_func in tests:
print(f"\n{'='*60}")
print(f"Running: {test_name}")
print('='*60)
try:
if test_func():
print(f"✅ {test_name} passed!")
else:
print(f"❌ {test_name} failed!")
failed = True
except Exception as e:
print(f"❌ {test_name} failed with exception: {e}")
failed = True
if failed:
sys.exit(1)
else:
print("\n✅ All integration tests passed!")