Skip to main content

Python wrapper library for static PHP binaries with pre-built distribution support crazywhalecc/static-php-cli

Project description

static-php-py

Python wrapper library for static-php-cli, inspired by the static-php-cli project with pre-built binary distribution support.

Features

  • Zero-configuration PHP execution: Install and run PHP scripts immediately
  • Pre-built static binaries: No compilation required, binaries from static-php-cli 2.7.10
  • Platform-specific wheels: Automatic platform detection via pip
  • Flexible installation: Choose between API-only or bundled binary
  • Remote binary support: Download and cache PHP binaries from custom URLs
  • Type-safe API: Full type hints for better IDE support

Installation

Light (API only)

pip install static-php-py

Requires PHP available in system PATH or explicit binary path.

Installation

pip install static-php-py

Pip automatically selects the appropriate wheel for your platform. Platform-specific wheels include pre-built PHP binaries.

Includes pre-built PHP 8.3 binary for your platform (Linux x86_64/aarch64, macOS x86_64/arm64, Windows x64).

Development

# Clone repository
git clone https://github.com/samhsu-dev/static-php-py.git
cd static-php-py

# Create virtual environment with uv
uv venv
source .venv/bin/activate  # or `.venv\Scripts\activate` on Windows

# Install with dev dependencies (includes Jupyter for demo notebook)
uv pip install -e ".[dev]"

# Register Jupyter kernel (optional, for running demo.ipynb)
python -m ipykernel install --user --name=static-php-py --display-name="static-php-py (.venv)"

Quick Start

Basic Usage

from static_php_py import PHP

# Use built-in PHP binary (from platform-specific wheel)
php = PHP.builtin()

# Or use local PHP binary
php = PHP.local("/usr/bin/php")

# Or download from remote URL
php = PHP.remote("https://example.com/php-8.4.zip")

# Execute PHP script
result = php.run("script.php")
if result.success:
    print(result.stdout)
else:
    print(f"Error: {result.stderr}")

# Evaluate PHP code
result = php.eval("echo 'Hello from PHP!';")
print(result.stdout)  # Hello from PHP!

# Get PHP version
print(php.version())  # 8.4.0

# Get PHP binary path
print(php.path())  # /path/to/php

Usage

Load Local PHP Binary

from static_php_py import PHP

# Use local PHP binary with string path
php = PHP.local("/usr/local/bin/php")
result = php.run("script.php")

# Or use Path object
from pathlib import Path
php = PHP.local(Path("/usr/local/bin/php"))

Download Remote PHP Binary

from static_php_py import PHP

# Download binary directly
php = PHP.remote("https://example.com/php-8.4-cli")

# Download and extract archive (tar.gz, tgz, or zip)
php = PHP.remote("https://example.com/php-8.4.tar.gz")
php = PHP.remote("https://example.com/php-8.4.zip")

# Force re-download (ignore cache)
php = PHP.remote("https://example.com/php.tar.gz", force=True)

# Custom timeout (default: 300 seconds)
php = PHP.remote("https://example.com/php.tar.gz", timeout=600.0)

Execute PHP Scripts

from static_php_py import PHP

php = PHP.builtin()

# Run script with arguments
result = php.run("script.php", args=["--verbose", "--debug"])

# Run with timeout
result = php.run("long_script.php", timeout=30.0)

# Check result
if result.success:
    print(f"Output: {result.stdout}")
else:
    print(f"Error (code {result.return_code}): {result.stderr}")

Evaluate PHP Code

from static_php_py import PHP

php = PHP.builtin()

# Evaluate PHP code string
result = php.eval("echo 2 + 2;")  # Output: 4
print(result.stdout)

# With timeout
result = php.eval("sleep(5); echo 'Done';", timeout=10.0)

Exception Handling

from static_php_py import PHP
from static_php_py.exceptions import (
    BinaryNotFoundError,
    DownloadError,
    ExecutionError,
    InvalidArchiveError,
)

# Handle binary not found
try:
    php = PHP.builtin()
except BinaryNotFoundError:
    print("PHP binary not found. Install platform-specific wheel or use PHP.local(path).")

# Handle download errors
try:
    php = PHP.remote("https://example.com/php.zip")
except DownloadError as e:
    print(f"Download failed: {e}")
except InvalidArchiveError as e:
    print(f"Invalid archive: {e}")

# Handle execution errors
try:
    result = php.run("script.php")
except ExecutionError as e:
    print(f"Execution failed: {e}")

API Reference

PHP Class

Static Methods

PHP.builtin() -> PHP

Load built-in PHP binary from package resources.

Returns: PHP instance

Raises: BinaryNotFoundError if built-in binary not found (not installed via platform-specific wheel)

PHP.local(path: Path | str) -> PHP

Load PHP binary from local file system path.

Parameters:

  • path: Path to PHP binary (required, string or Path object)

Returns: PHP instance

Raises: BinaryNotFoundError if binary not found at specified path

PHP.remote(url: str, force: bool = False, timeout: float = 300.0) -> PHP

Download PHP binary from remote URL and return PHP instance.

Parameters:

  • url: Remote URL to PHP binary or archive (tar.gz, tgz, or zip)
  • force: Force re-download ignoring cache (default: False)
  • timeout: Download timeout in seconds (default: 300.0)

Returns: PHP instance

Raises: DownloadError on network failure, InvalidArchiveError on archive error

Instance Methods

  • run(script: Path | str, args: list[str] | None = None, timeout: float | None = None) -> ExecutionResult
  • eval(code: str, timeout: float | None = None) -> ExecutionResult
  • version() -> str
  • path() -> Path

ExecutionResult

Result of PHP script execution.

Properties:

  • success: bool - True if exit code is 0
  • return_code: int - Process exit code
  • stdout: str - Standard output
  • stderr: str - Standard error

Exceptions

  • PHPError - Base exception for all static-php-py errors
  • BinaryNotFoundError - PHP binary not found
  • ExecutionError - PHP execution failure
  • DownloadError - Network/download failure
  • InvalidArchiveError - Invalid tar.gz archive

Project Structure

static-php-py/
├── static_php_py/          # Main package
│   ├── __init__.py         # Public API exports
│   ├── exceptions.py       # Exception classes
│   ├── php.py              # PHP class (includes create, download, cache_dir)
│   ├── models.py           # ExecutionResult model
│   └── providers.py        # Internal providers
├── resources/              # Resources package (PHP binaries)
│   ├── __init__.py
│   └── pyproject.toml
├── scripts/                # Build scripts
│   └── build_binaries.py   # Binary wheel builder
├── tests/                  # Test suite
│   ├── test_exceptions.py
│   ├── test_factory.py
│   ├── test_integration.py
│   ├── test_models.py
│   ├── test_php.py
│   └── test_providers.py
├── docs/                   # Documentation
│   ├── idea.md            # Architecture concepts
│   ├── design.md          # Detailed design specification
│   └── todo.md            # Implementation tasks
├── pyproject.toml         # Project configuration
└── README.md              # This file

Development

Run Tests

pytest tests/ -v

Code Quality

# Linting
ruff check static_php_py/

# Formatting
ruff format static_php_py/ tests/

# Type checking
mypy static_php_py/

Interactive Demo

# Open the demo notebook
jupyter notebook docs/demo.ipynb
# or
jupyter lab docs/demo.ipynb

The demo notebook (docs/demo.ipynb) demonstrates all public APIs with interactive examples.

Troubleshooting

PHP Binary Not Found

If you get BinaryNotFoundError:

  1. Ensure platform-specific wheel is installed:

    pip install --force-reinstall static-php-py
    
  2. Or specify explicit path:

    php = PHP.create(path="/usr/bin/php")
    
  3. Or ensure PHP is in system PATH:

    which php  # Check if PHP is available
    

Download Failures

If download() fails:

  • Check network connectivity
  • Verify URL is accessible
  • Try with force=True to bypass cache
  • Increase timeout for slow connections

Archive Extraction Errors

If InvalidArchiveError is raised:

  • Verify URL points to valid tar.gz file
  • Check archive contains php executable
  • Ensure archive is not corrupted

Architecture

For detailed architecture and design information, see:

Publishing

For information on publishing to PyPI, see:

  • Publishing Guide - Instructions for publishing to Test PyPI and production PyPI

Status

✅ Phase 1-8: Complete
⏳ Phase 9: CI/CD and Publishing (in progress)

License

Apache License 2.0 - See LICENSE file for details.

Acknowledgments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

static_php_py-0.1.0-py3-none-win_amd64.whl (5.1 MB view details)

Uploaded Python 3Windows x86-64

static_php_py-0.1.0-py3-none-manylinux_2_17_x86_64.whl (4.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

static_php_py-0.1.0-py3-none-manylinux_2_17_aarch64.whl (5.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

static_php_py-0.1.0-py3-none-macosx_11_0_x86_64.whl (4.8 MB view details)

Uploaded Python 3macOS 11.0+ x86-64

static_php_py-0.1.0-py3-none-macosx_11_0_arm64.whl (4.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

static_php_py-0.1.0-py3-none-any.whl (26.9 kB view details)

Uploaded Python 3

File details

Details for the file static_php_py-0.1.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for static_php_py-0.1.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 fa5671e6ec6893e83fd9609726c54099b8fdca48ef0570f148e322baac74fe23
MD5 90a1ecca094075037fdee10f68f1078e
BLAKE2b-256 fd45cdbdb3938053ee1d49b236d71aca330fb450fcc2ac0d62bb10f1fce05036

See more details on using hashes here.

File details

Details for the file static_php_py-0.1.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for static_php_py-0.1.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 d84b8cf3d1f985e24d97bc12b93839ba9f552f933b88e782b7f78255cf60e438
MD5 854a6b258538dbfbb0d87e78b53e9495
BLAKE2b-256 4d55a6c414728e9e681d9e6b74c7db75cc1e7c9d66222d7fc94334c4648293e6

See more details on using hashes here.

File details

Details for the file static_php_py-0.1.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for static_php_py-0.1.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 242158f93e52dd9f716ec8cbd4d09d5a5637784cc3c5f173b6708d51f80d11c8
MD5 26b0862477079f095a2cf833ccee8ab9
BLAKE2b-256 fb84abba3df6e07707671b9776142a24324b681801be9b08e5700cf1f6163cb1

See more details on using hashes here.

File details

Details for the file static_php_py-0.1.0-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for static_php_py-0.1.0-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 090586eb3ee36ea2df73bb26c8d3456c8c025f48a6946ff455acd22a1dc4ffd5
MD5 a68bfd1ac27c4f6d54e5e4896f976b80
BLAKE2b-256 3532d748315feb8ae0a50bf80a4a8a43e7202e744cf0b2c7d6efd5dc20b63643

See more details on using hashes here.

File details

Details for the file static_php_py-0.1.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for static_php_py-0.1.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2c4110c83bfcc29e591ffcac78b4d8fcabb1fadd4b6d76c7156614aa41eb4acf
MD5 d264cbd55a81068773ad5b1a85c37669
BLAKE2b-256 986ef2cdc2b011e16c9cadf9976544f86b37c501e55463eab44cb73d8a527c49

See more details on using hashes here.

File details

Details for the file static_php_py-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: static_php_py-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for static_php_py-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b2601b5cbc3051f24eb69766a1a0b6042d919758afb4a30bb345867ca019076
MD5 edf438d69436736e894975b8ac0343e1
BLAKE2b-256 30a6c0d896f46668eab321a5b300d1878868ae9a382f360d283e0f2b5000fcab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page