plua


Nameplua JSON
Version 1.0.99 PyPI version JSON
download
home_pageNone
SummaryPython-Lua async runtime with timer support
upload_time2025-07-26 21:55:58
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords lua async timer coroutine
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # plua

Python-Lua async runtime with timer support

## Overview

plua is a Python package that provides an async runtime environment for executing Lua scripts with JavaScript-like timer functionality. It bridges Python's asyncio with Lua's coroutines, allowing for sophisticated async programming patterns.

## Features

- **Interactive REPL**: Lua-like interactive prompt with plua features
- **JavaScript-like timers**: `setTimeout()`, `setInterval()`, `clearTimeout()`, `clearInterval()` in Lua
- **Async/await bridge**: Python asyncio integrated with Lua coroutines  
- **Context safety**: All Lua execution happens in the same Python context
- **Timer management**: Named asyncio tasks with cancellation support
- **Built-in REST API**: Automatic web server with REPL interface on port 8888
- **Network support**: HTTP client/server, WebSocket, TCP/UDP socket support
- **JSON support**: Built-in JSON encoding/decoding in Lua
- **Fibaro HC3 API**: Complete Home Center 3 API emulation with 267+ endpoints
- **MobDebug support**: Remote debugging with IDE integration
- **Coroutine support**: Full Lua coroutine functionality with yielding
- **Multi-platform executables**: Standalone binaries for Linux, Windows, macOS

## Installation

### For End Users (Recommended)

```bash
# Install plua globally (includes the 'plua' command)
pip install plua

# Verify installation
plua --version

# Start the interactive REPL
plua

# Run a Lua script
plua myscript.lua
```

After installation, the `plua` command will be available system-wide in your terminal/command prompt.

### Alternative: Standalone Executables

For users who prefer not to install Python dependencies, standalone executables are available:

```bash
# Download from GitHub Releases
# https://github.com/jangabrielsson/plua/releases

# Windows: plua-windows.exe
# macOS Intel: plua-macos-intel  
# macOS ARM: plua-macos-arm
# Linux: plua-linux

# Make executable and run (macOS/Linux)
chmod +x plua-linux
./plua-linux --version

# Windows: just run the .exe
plua-windows.exe --version
```

These executables include everything needed and don't require Python installation.

### For Developers

```bash
# Clone and install in development mode
git clone https://github.com/jangabrielsson/plua
cd plua
pip install -e .

# Install with development dependencies for testing/building
pip install -e ".[dev]"
```

### Troubleshooting Installation

#### Command Not Found (Windows)
If `plua` command is not recognized after installation on Windows:

1. **Check if pip installed to user directory:**
   ```cmd
   # Find where pip installed plua
   pip show -f plua
   
   # Check if Python Scripts directory is in PATH
   python -m site --user-base
   ```

2. **Add Python Scripts to PATH:**
   - Add `%APPDATA%\Python\Python3X\Scripts` to your PATH environment variable
   - Or use the full path: `python -m plua` instead of just `plua`

3. **Alternative installation methods:**
   ```cmd
   # Install system-wide (may require admin privileges)
   pip install --system plua
   
   # Force reinstall to ensure all dependencies are installed
   pip install --force-reinstall plua
   
   # Or use python -m to run without PATH issues
   python -m plua --version
   python -m plua script.lua
   ```

#### Missing Dependencies Error
If you get `ModuleNotFoundError` (e.g., "No module named 'aiomqtt'"):

```bash
# Force reinstall with all dependencies
pip install --force-reinstall plua

# Or install dependencies manually if needed
pip install aiomqtt>=2.0.0
```

#### FileNotFoundError on Windows
If you get `FileNotFoundError: [Errno 2] No such file or directory: 'src/plua/fibaro_api_models.py'`:

This was a bug in versions 1.0.57-1.0.59. Update to the latest version:

```bash
pip install --upgrade plua
```

#### Missing init.lua Error
If you get `FileNotFoundError: init.lua not found at: ...`:

This was a packaging issue in versions 1.0.57-1.0.68 where Lua files weren't included or couldn't be found properly. Update to the latest version:

```bash
pip install --upgrade plua
```

If you still get this error after updating to v1.0.69+, please run the command again to see detailed debug output and report the issue on GitHub.

#### Command Not Found (macOS/Linux)
```bash
# Check installation location
pip show plua

# Add pip's bin directory to PATH if needed
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Or use python -m
python -m plua --version
```

## Quick Start

### Command Line Usage

```bash
# Interactive REPL (no file specified)
plua

# Run a Lua file directly (API server starts automatically on port 8888)
plua script.lua

# Run without API server
plua --noapi script.lua

# Run with time limit
plua --duration 10 script.lua

# Custom API server settings
plua --api-port 9000 script.lua              # Custom port
plua --api-host 127.0.0.1 script.lua         # Custom host
plua --api-port 9000 --api-host 0.0.0.0 script.lua  # Custom host and port

# Run inline Lua code
plua -e 'print("Hello from Lua")'
plua -e 'print("start")' -e 'x=42' -e 'print(x)'     # Multiple -e fragments
plua -e 'print("setup")' script.lua                  # Combine -e and file

# Fibaro HC3 API support
plua --fibaro script.lua

# Debugging support
plua --debugger script.lua                           # Enable MobDebug
plua --debugger --debug script.lua                   # Verbose debug logging
plua --debugger --debugger-host 192.168.1.100 script.lua  # Remote debugger

# Utility commands
plua --cleanup-port                                   # Clean up stuck API port
plua --version                                        # Show version
```

### Interactive REPL

plua provides an interactive REPL (Read-Eval-Print Loop) when no Lua file is specified:

```bash
$ plua
Plua v1.0.54 Interactive REPL
Running Lua 5.4 with async runtime support

Quick start:
  help()                           - Show available commands
  print('Hello, plua!')           - Basic Lua
  json.encode({name='test'})       - JSON encoding
  setTimeout(function() print('Hi!') end, 2000) - Async timer

Type 'exit()' or press Ctrl+D to quit

plua> print("Hello, world!")
Hello, world!
plua> x = 42
plua> x + 10
52
plua> client = net.HTTPClient()
plua> setTimeout(function() print("Timer fired!") end, 2000)
plua> -- Timer fires after 2 seconds
Timer fired!
plua> exit()
Goodbye!
```

The REPL supports:
- All plua features (timers, JSON, networking)
- Built-in `json` and `net` modules (no require needed)
- Persistent variables and functions
- Background async operations
- Built-in help and state inspection
- Error recovery

### Python API Usage

```python
import asyncio
from plua import LuaAsyncRuntime

async def main():
    runtime = LuaAsyncRuntime()
    
    script = """
    print("Starting...")
    setTimeout(function() 
        print("Timer 1 fired!")
        setTimeout(function() print("Timer 2 fired!") end, 500)
    end, 1000)
    """
    
    await runtime.start(script=script, duration=5)

asyncio.run(main())
```

### REST API Server

plua includes a built-in REST API server that **starts automatically by default** on port 8888:

```bash
# API server starts automatically
plua script.lua

# Disable API server  
plua --noapi script.lua

# Custom API server settings
plua --api-port 9000 script.lua
plua --api-host 127.0.0.1 --api-port 8877 script.lua

# Access the web REPL interface
# Open browser to: http://localhost:8888/static/plua_main_page.html
```

#### API Endpoints

- `GET /` - API information and available endpoints
- `GET /static/plua_main_page.html` - Web-based REPL interface  
- `POST /plua/execute` - Execute Lua code remotely
- `GET /plua/status` - Get runtime status
- `GET /plua/info` - Get API and runtime information
- `GET /docs` - Swagger/OpenAPI documentation (if Fibaro API enabled)

#### Web REPL

The web REPL provides a modern browser-based interface for plua:

- **HTML Rendering**: Supports HTML tags in output for colored and formatted text
- **Real-time Execution**: Share interpreter state with local REPL
- **Timer Support**: Background timers work seamlessly
- **Modern UI**: Responsive design with syntax highlighting

Example HTML output in web REPL:
```lua
print("<font color='red'>Red text</font>")
print("<b>Bold text</b> | <i>Italic text</i>")
print("<span style='background-color: yellow;'>Highlighted</span>")
```

#### Remote Code Execution

```bash
# Execute Lua code via API
curl -X POST http://localhost:8888/plua/execute \
  -H 'Content-Type: application/json' \
  -d '{"code":"return 2 + 2", "timeout": 10.0}'
```

Response:
```json
{
  "success": true,
  "result": 4,
  "output": "",
  "error": null,
  "execution_time_ms": 0.123,
  "request_id": "uuid-here"
}
```

The API server and local REPL share the same Lua interpreter instance, so:
- Variables persist between API calls and REPL commands
- Timers set via API continue running in the background
- State is shared seamlessly between web and terminal interfaces

## VSCode launch
Setup launch tasks in .vscode/launch.json
The executable is either `plua` if installed and accesible globally,
or if running from the plua repo, `${workspaceFolder}/run.sh`

Running current lua file, with or without Fibaro support loaded.
```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "plua: Run Current Lua file with Debugger", 
            "type": "luaMobDebug",
            "request": "launch",
            "workingDirectory": "${workspaceFolder}",
            "sourceBasePath": "${workspaceFolder}",
            "listenPort": 8172,
            "listenPublicly": false,
            "stopOnEntry": false,
            "sourceEncoding": "UTF-8",
            "executable": "plua",
            "arguments": [
                "--debugger",
                "--debugger-host",
                "localhost",
                "--debugger-port",
                "8172",
                "${file}"
            ]
        },
        {
            "name": "plua: Run Current Fibaro file with Debugger", 
            "type": "luaMobDebug",
            "request": "launch",
            "workingDirectory": "${workspaceFolder}",
            "sourceBasePath": "${workspaceFolder}",
            "listenPort": 8172,
            "listenPublicly": false,
            "stopOnEntry": false,
            "sourceEncoding": "UTF-8",
            "executable": "plua",
            "arguments": [
                "--debugger",
                "--debugger-host",
                "localhost",
                "--debugger-port",
                "8172",
                "--fibaro",
                "${file}"
            ]
        }
    ]
}
```

## Lua API

### Timer Functions

```lua
-- Set a timer (JavaScript-like)
local timer_id = setTimeout(function() 
    print("This runs after 1 second") 
end, 1000)

-- Set an interval timer
local interval_id = setInterval(function()
    print("This repeats every 2 seconds")
end, 2000)

-- Cancel timers
clearTimeout(timer_id)
clearInterval(interval_id)

-- Sleep (yields current coroutine)
sleep(500)  -- Sleep for 500ms
```

### Built-in Modules

```lua
-- JSON support (no require needed)
local data = {name = "test", value = 42}
local json_str = json.encode(data)
local parsed = json.decode(json_str)

-- HTTP client
local client = net.HTTPClient()
client:get("https://api.github.com/users/octocat", function(response)
    print("Status:", response.status)
    print("Body:", response.body)
end)

-- WebSocket client
local ws = net.WebSocketClient()
ws:connect("wss://echo.websocket.org/", {
    on_message = function(message)
        print("Received:", message)
    end
})
```

### Fibaro HC3 API Integration

```lua
-- Enable Fibaro API support
-- Run with: plua --fibaro script.lua

-- Use standard Fibaro API functions
fibaro.call(123, "turnOn")
local value = fibaro.getValue(456, "value") 
fibaro.sleep(1000)

-- QuickApp development
function QuickApp:onInit()
    self:debug("QuickApp started")
    self:updateProperty("value", 42)
end
```

### Coroutines

```lua
local function asyncFunction()
    print("Start")
    local co = coroutine.running()
    
    setTimeout(function() 
        coroutine.resume(co, "result") 
    end, 1000)
    
    local result = coroutine.yield()
    print("Got result:", result)
end

coroutine.wrap(asyncFunction)()
```

## Examples

### Example 1: HTTP Client with Timers

```lua
local client = net.HTTPClient()

-- Make HTTP request with timer fallback
local timer_id = setTimeout(function()
    print("Request timeout!")
end, 5000)

client:get("https://httpbin.org/delay/2", function(response)
    clearTimeout(timer_id)
    print("Response status:", response.status)
    print("Response time was acceptable")
end)
```

### Example 2: Interval Timer with Cancellation

```lua
local count = 0
local interval_id = setInterval(function()
    count = count + 1
    print("Ping", count)
    
    if count >= 5 then
        print("Stopping interval")
        clearInterval(interval_id)
    end
end, 1000)
```

### Example 3: Coroutine with Async Operations

```lua
local function asyncTask()
    print("Task starting...")
    
    -- Simulate async work
    local co = coroutine.running()
    setTimeout(function() 
        coroutine.resume(co, "async result") 
    end, 2000)
    
    local result = coroutine.yield()
    print("Task completed with:", result)
end

coroutine.wrap(asyncTask)()
```

## Architecture

### Components

- **`LuaInterpreter`**: Manages Lua runtime and script execution
- **`LuaAsyncRuntime`**: Handles asyncio integration and timer management
- **Timer System**: Maps Lua timer calls to Python asyncio tasks
- **Callback Loop**: Executes Lua callbacks in the correct context

### Flow

1. Lua calls `setTimeout(callback, delay)`
2. Python creates an asyncio task that waits for `delay`
3. When timer fires, Python queues the callback ID
4. Callback loop executes the Lua callback in the same context
5. Lua coroutines can yield and be resumed by timers

## 📚 Documentation

Comprehensive documentation is available in the `docs/` directory:

- **[Documentation Index](docs/README.md)** - Complete documentation overview
- **[Web REPL HTML Examples](docs/WEB_REPL_HTML_EXAMPLES.md)** - HTML rendering guide for web interface
- **[REST API Documentation](docs/api/README.md)** - Complete API reference and examples
- **[Developer Documentation](docs/dev/README.md)** - Implementation details and development guides

### Quick Links
- 🚀 **Getting Started**: This README
- 🌐 **Web Interface**: [Web REPL Examples](docs/WEB_REPL_HTML_EXAMPLES.md)
- 📡 **API Integration**: [REST API Docs](docs/api/README.md)
- 🔧 **Contributing**: [Developer Docs](docs/dev/README.md)

## Fibaro HC3 API Integration

plua includes a comprehensive Fibaro Home Center 3 API emulator with full type safety and documentation:

### Generated API Endpoints

The Fibaro API endpoints are auto-generated from official Swagger/OpenAPI specifications:

```bash
# Regenerate Fibaro API endpoints and models
python src/plua/generate_typed_fibaro_api.py

# Generate with custom paths
python src/plua/generate_typed_fibaro_api.py --docs-dir fibaro_api_docs --output-dir src/plua
```

This generates:
- **`fibaro_api_models.py`**: 305+ Pydantic models with full type validation
- **`fibaro_api_endpoints.py`**: 267+ FastAPI endpoints with proper documentation

### Fibaro API Features

- **Complete Coverage**: All major Fibaro HC3 API endpoints
- **Type Safety**: Full Pydantic validation for request/response data
- **Swagger Documentation**: Auto-generated API docs at `/docs`
- **Lua Integration**: All calls delegate to `_PY.fibaro_api_hook(method, path, data)`
- **Easy Testing**: Use web interface or curl to test endpoints

```bash
# Start server with Fibaro API
plua --api-port 8888 --fibaro

# Test an endpoint
curl -X GET "http://localhost:8888/devices" -H "accept: application/json"
```

### HC3 Configuration with .env File

To connect plua to a real Fibaro Home Center 3 device, create a `.env` file with your HC3 credentials. plua searches for `.env` files in the following order:

1. **Current directory** (project-specific): `./.env`
2. **Home directory** (user-global): `~/.env` 
3. **Config directory** (platform-specific):
   - Linux/macOS: `~/.config/plua/.env`
   - Windows: `%APPDATA%\plua\.env`

```bash
# Option 1: Project-specific .env (recommended for development)
cd /path/to/your/fibaro/project
cat > .env << EOF
HC3_URL=https://192.168.1.100
HC3_USER=admin
HC3_PASSWORD=your_password_here
EOF

# Option 2: User-global .env (works from any directory)
cat > ~/.env << EOF
HC3_URL=https://192.168.1.100
HC3_USER=admin
HC3_PASSWORD=your_password_here
EOF
```

The `.env` file should contain:
- **`HC3_URL`**: Your Home Center 3 IP address or hostname (without trailing slash)
- **`HC3_USER`**: HC3 username (usually 'admin')  
- **`HC3_PASSWORD`**: HC3 password

Example `.env` file:
```env
# Fibaro HC3 Connection Settings
HC3_URL=https://192.168.1.100
HC3_USER=admin
HC3_PASSWORD=mySecretPassword123

# Optional: Add other environment variables your scripts might need
DEBUG=true
LOG_LEVEL=info
```

**Security Notes:**
- Project-specific `.env` files: Add `.env` to your `.gitignore` file to prevent committing credentials
- User-global `~/.env` file: Set appropriate file permissions (`chmod 600 ~/.env` on Unix systems)
- Use HTTPS URLs when possible
- Consider using environment variables directly in production environments

**Usage Examples:**
```bash
# Works from any directory if you have ~/.env configured
cd /any/directory
plua --fibaro my_script.lua

# Works from project directory with local .env
cd /my/fibaro/project
plua --fibaro script.lua   # Uses ./env (takes precedence over ~/.env)
```

**Usage in Lua Scripts:**
```lua
-- Access environment variables in your Lua code
local hc3_url = os.getenv("HC3_URL")
local debug_mode = os.getenv("DEBUG") == "true"

-- Environment variables are automatically loaded by the Fibaro emulator
-- when you use --fibaro flag
```

When you run plua with the `--fibaro` flag, it automatically reads these environment variables and configures the HC3 connection for API calls.

## Development

### Setup Development Environment

```bash
# Clone and setup
git clone https://github.com/jangabrielsson/plua
cd plua
pip install -e ".[dev]"

# Setup HC3 credentials (optional, for Fibaro integration)
cp .env.example .env
# Edit .env with your HC3 credentials

# Install GitHub CLI for releases
brew install gh
gh auth login
```

### Run Tests

```bash
pytest
```

### Code Formatting

```bash
black src/ tests/
```

### Type Checking

```bash
mypy src/
```

### Creating Releases

The project uses automated GitHub Releases with PyPI publishing and executable building:

```bash
# Quick patch release (1.0.54 → 1.0.55)
./scripts/create-release.sh patch

# Interactive release (choose patch/minor/major)  
./scripts/create-release.sh

# Custom version
./scripts/create-release.sh "2.0.0" "Major release with breaking changes"
```

Each release automatically:
- Publishes to PyPI
- Builds executables for Linux, Windows, macOS (Intel + ARM)
- Attaches binaries to GitHub release
- Updates documentation

## License

MIT License

## Requirements

- Python 3.8+
- lupa (Python-Lua bridge)
- asyncio (built-in)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "plua",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "lua, async, timer, coroutine",
    "author": null,
    "author_email": "Jan Gabrielsson <jan@gabrielsson.com>",
    "download_url": "https://files.pythonhosted.org/packages/5a/1a/5a1273a6a86b52c9b83ab6ed1b4cdb22a9cc0dfca6191c0890dd38f122c5/plua-1.0.99.tar.gz",
    "platform": null,
    "description": "# plua\n\nPython-Lua async runtime with timer support\n\n## Overview\n\nplua is a Python package that provides an async runtime environment for executing Lua scripts with JavaScript-like timer functionality. It bridges Python's asyncio with Lua's coroutines, allowing for sophisticated async programming patterns.\n\n## Features\n\n- **Interactive REPL**: Lua-like interactive prompt with plua features\n- **JavaScript-like timers**: `setTimeout()`, `setInterval()`, `clearTimeout()`, `clearInterval()` in Lua\n- **Async/await bridge**: Python asyncio integrated with Lua coroutines  \n- **Context safety**: All Lua execution happens in the same Python context\n- **Timer management**: Named asyncio tasks with cancellation support\n- **Built-in REST API**: Automatic web server with REPL interface on port 8888\n- **Network support**: HTTP client/server, WebSocket, TCP/UDP socket support\n- **JSON support**: Built-in JSON encoding/decoding in Lua\n- **Fibaro HC3 API**: Complete Home Center 3 API emulation with 267+ endpoints\n- **MobDebug support**: Remote debugging with IDE integration\n- **Coroutine support**: Full Lua coroutine functionality with yielding\n- **Multi-platform executables**: Standalone binaries for Linux, Windows, macOS\n\n## Installation\n\n### For End Users (Recommended)\n\n```bash\n# Install plua globally (includes the 'plua' command)\npip install plua\n\n# Verify installation\nplua --version\n\n# Start the interactive REPL\nplua\n\n# Run a Lua script\nplua myscript.lua\n```\n\nAfter installation, the `plua` command will be available system-wide in your terminal/command prompt.\n\n### Alternative: Standalone Executables\n\nFor users who prefer not to install Python dependencies, standalone executables are available:\n\n```bash\n# Download from GitHub Releases\n# https://github.com/jangabrielsson/plua/releases\n\n# Windows: plua-windows.exe\n# macOS Intel: plua-macos-intel  \n# macOS ARM: plua-macos-arm\n# Linux: plua-linux\n\n# Make executable and run (macOS/Linux)\nchmod +x plua-linux\n./plua-linux --version\n\n# Windows: just run the .exe\nplua-windows.exe --version\n```\n\nThese executables include everything needed and don't require Python installation.\n\n### For Developers\n\n```bash\n# Clone and install in development mode\ngit clone https://github.com/jangabrielsson/plua\ncd plua\npip install -e .\n\n# Install with development dependencies for testing/building\npip install -e \".[dev]\"\n```\n\n### Troubleshooting Installation\n\n#### Command Not Found (Windows)\nIf `plua` command is not recognized after installation on Windows:\n\n1. **Check if pip installed to user directory:**\n   ```cmd\n   # Find where pip installed plua\n   pip show -f plua\n   \n   # Check if Python Scripts directory is in PATH\n   python -m site --user-base\n   ```\n\n2. **Add Python Scripts to PATH:**\n   - Add `%APPDATA%\\Python\\Python3X\\Scripts` to your PATH environment variable\n   - Or use the full path: `python -m plua` instead of just `plua`\n\n3. **Alternative installation methods:**\n   ```cmd\n   # Install system-wide (may require admin privileges)\n   pip install --system plua\n   \n   # Force reinstall to ensure all dependencies are installed\n   pip install --force-reinstall plua\n   \n   # Or use python -m to run without PATH issues\n   python -m plua --version\n   python -m plua script.lua\n   ```\n\n#### Missing Dependencies Error\nIf you get `ModuleNotFoundError` (e.g., \"No module named 'aiomqtt'\"):\n\n```bash\n# Force reinstall with all dependencies\npip install --force-reinstall plua\n\n# Or install dependencies manually if needed\npip install aiomqtt>=2.0.0\n```\n\n#### FileNotFoundError on Windows\nIf you get `FileNotFoundError: [Errno 2] No such file or directory: 'src/plua/fibaro_api_models.py'`:\n\nThis was a bug in versions 1.0.57-1.0.59. Update to the latest version:\n\n```bash\npip install --upgrade plua\n```\n\n#### Missing init.lua Error\nIf you get `FileNotFoundError: init.lua not found at: ...`:\n\nThis was a packaging issue in versions 1.0.57-1.0.68 where Lua files weren't included or couldn't be found properly. Update to the latest version:\n\n```bash\npip install --upgrade plua\n```\n\nIf you still get this error after updating to v1.0.69+, please run the command again to see detailed debug output and report the issue on GitHub.\n\n#### Command Not Found (macOS/Linux)\n```bash\n# Check installation location\npip show plua\n\n# Add pip's bin directory to PATH if needed\necho 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.bashrc\nsource ~/.bashrc\n\n# Or use python -m\npython -m plua --version\n```\n\n## Quick Start\n\n### Command Line Usage\n\n```bash\n# Interactive REPL (no file specified)\nplua\n\n# Run a Lua file directly (API server starts automatically on port 8888)\nplua script.lua\n\n# Run without API server\nplua --noapi script.lua\n\n# Run with time limit\nplua --duration 10 script.lua\n\n# Custom API server settings\nplua --api-port 9000 script.lua              # Custom port\nplua --api-host 127.0.0.1 script.lua         # Custom host\nplua --api-port 9000 --api-host 0.0.0.0 script.lua  # Custom host and port\n\n# Run inline Lua code\nplua -e 'print(\"Hello from Lua\")'\nplua -e 'print(\"start\")' -e 'x=42' -e 'print(x)'     # Multiple -e fragments\nplua -e 'print(\"setup\")' script.lua                  # Combine -e and file\n\n# Fibaro HC3 API support\nplua --fibaro script.lua\n\n# Debugging support\nplua --debugger script.lua                           # Enable MobDebug\nplua --debugger --debug script.lua                   # Verbose debug logging\nplua --debugger --debugger-host 192.168.1.100 script.lua  # Remote debugger\n\n# Utility commands\nplua --cleanup-port                                   # Clean up stuck API port\nplua --version                                        # Show version\n```\n\n### Interactive REPL\n\nplua provides an interactive REPL (Read-Eval-Print Loop) when no Lua file is specified:\n\n```bash\n$ plua\nPlua v1.0.54 Interactive REPL\nRunning Lua 5.4 with async runtime support\n\nQuick start:\n  help()                           - Show available commands\n  print('Hello, plua!')           - Basic Lua\n  json.encode({name='test'})       - JSON encoding\n  setTimeout(function() print('Hi!') end, 2000) - Async timer\n\nType 'exit()' or press Ctrl+D to quit\n\nplua> print(\"Hello, world!\")\nHello, world!\nplua> x = 42\nplua> x + 10\n52\nplua> client = net.HTTPClient()\nplua> setTimeout(function() print(\"Timer fired!\") end, 2000)\nplua> -- Timer fires after 2 seconds\nTimer fired!\nplua> exit()\nGoodbye!\n```\n\nThe REPL supports:\n- All plua features (timers, JSON, networking)\n- Built-in `json` and `net` modules (no require needed)\n- Persistent variables and functions\n- Background async operations\n- Built-in help and state inspection\n- Error recovery\n\n### Python API Usage\n\n```python\nimport asyncio\nfrom plua import LuaAsyncRuntime\n\nasync def main():\n    runtime = LuaAsyncRuntime()\n    \n    script = \"\"\"\n    print(\"Starting...\")\n    setTimeout(function() \n        print(\"Timer 1 fired!\")\n        setTimeout(function() print(\"Timer 2 fired!\") end, 500)\n    end, 1000)\n    \"\"\"\n    \n    await runtime.start(script=script, duration=5)\n\nasyncio.run(main())\n```\n\n### REST API Server\n\nplua includes a built-in REST API server that **starts automatically by default** on port 8888:\n\n```bash\n# API server starts automatically\nplua script.lua\n\n# Disable API server  \nplua --noapi script.lua\n\n# Custom API server settings\nplua --api-port 9000 script.lua\nplua --api-host 127.0.0.1 --api-port 8877 script.lua\n\n# Access the web REPL interface\n# Open browser to: http://localhost:8888/static/plua_main_page.html\n```\n\n#### API Endpoints\n\n- `GET /` - API information and available endpoints\n- `GET /static/plua_main_page.html` - Web-based REPL interface  \n- `POST /plua/execute` - Execute Lua code remotely\n- `GET /plua/status` - Get runtime status\n- `GET /plua/info` - Get API and runtime information\n- `GET /docs` - Swagger/OpenAPI documentation (if Fibaro API enabled)\n\n#### Web REPL\n\nThe web REPL provides a modern browser-based interface for plua:\n\n- **HTML Rendering**: Supports HTML tags in output for colored and formatted text\n- **Real-time Execution**: Share interpreter state with local REPL\n- **Timer Support**: Background timers work seamlessly\n- **Modern UI**: Responsive design with syntax highlighting\n\nExample HTML output in web REPL:\n```lua\nprint(\"<font color='red'>Red text</font>\")\nprint(\"<b>Bold text</b> | <i>Italic text</i>\")\nprint(\"<span style='background-color: yellow;'>Highlighted</span>\")\n```\n\n#### Remote Code Execution\n\n```bash\n# Execute Lua code via API\ncurl -X POST http://localhost:8888/plua/execute \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"code\":\"return 2 + 2\", \"timeout\": 10.0}'\n```\n\nResponse:\n```json\n{\n  \"success\": true,\n  \"result\": 4,\n  \"output\": \"\",\n  \"error\": null,\n  \"execution_time_ms\": 0.123,\n  \"request_id\": \"uuid-here\"\n}\n```\n\nThe API server and local REPL share the same Lua interpreter instance, so:\n- Variables persist between API calls and REPL commands\n- Timers set via API continue running in the background\n- State is shared seamlessly between web and terminal interfaces\n\n## VSCode launch\nSetup launch tasks in .vscode/launch.json\nThe executable is either `plua` if installed and accesible globally,\nor if running from the plua repo, `${workspaceFolder}/run.sh`\n\nRunning current lua file, with or without Fibaro support loaded.\n```json\n{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"plua: Run Current Lua file with Debugger\", \n            \"type\": \"luaMobDebug\",\n            \"request\": \"launch\",\n            \"workingDirectory\": \"${workspaceFolder}\",\n            \"sourceBasePath\": \"${workspaceFolder}\",\n            \"listenPort\": 8172,\n            \"listenPublicly\": false,\n            \"stopOnEntry\": false,\n            \"sourceEncoding\": \"UTF-8\",\n            \"executable\": \"plua\",\n            \"arguments\": [\n                \"--debugger\",\n                \"--debugger-host\",\n                \"localhost\",\n                \"--debugger-port\",\n                \"8172\",\n                \"${file}\"\n            ]\n        },\n        {\n            \"name\": \"plua: Run Current Fibaro file with Debugger\", \n            \"type\": \"luaMobDebug\",\n            \"request\": \"launch\",\n            \"workingDirectory\": \"${workspaceFolder}\",\n            \"sourceBasePath\": \"${workspaceFolder}\",\n            \"listenPort\": 8172,\n            \"listenPublicly\": false,\n            \"stopOnEntry\": false,\n            \"sourceEncoding\": \"UTF-8\",\n            \"executable\": \"plua\",\n            \"arguments\": [\n                \"--debugger\",\n                \"--debugger-host\",\n                \"localhost\",\n                \"--debugger-port\",\n                \"8172\",\n                \"--fibaro\",\n                \"${file}\"\n            ]\n        }\n    ]\n}\n```\n\n## Lua API\n\n### Timer Functions\n\n```lua\n-- Set a timer (JavaScript-like)\nlocal timer_id = setTimeout(function() \n    print(\"This runs after 1 second\") \nend, 1000)\n\n-- Set an interval timer\nlocal interval_id = setInterval(function()\n    print(\"This repeats every 2 seconds\")\nend, 2000)\n\n-- Cancel timers\nclearTimeout(timer_id)\nclearInterval(interval_id)\n\n-- Sleep (yields current coroutine)\nsleep(500)  -- Sleep for 500ms\n```\n\n### Built-in Modules\n\n```lua\n-- JSON support (no require needed)\nlocal data = {name = \"test\", value = 42}\nlocal json_str = json.encode(data)\nlocal parsed = json.decode(json_str)\n\n-- HTTP client\nlocal client = net.HTTPClient()\nclient:get(\"https://api.github.com/users/octocat\", function(response)\n    print(\"Status:\", response.status)\n    print(\"Body:\", response.body)\nend)\n\n-- WebSocket client\nlocal ws = net.WebSocketClient()\nws:connect(\"wss://echo.websocket.org/\", {\n    on_message = function(message)\n        print(\"Received:\", message)\n    end\n})\n```\n\n### Fibaro HC3 API Integration\n\n```lua\n-- Enable Fibaro API support\n-- Run with: plua --fibaro script.lua\n\n-- Use standard Fibaro API functions\nfibaro.call(123, \"turnOn\")\nlocal value = fibaro.getValue(456, \"value\") \nfibaro.sleep(1000)\n\n-- QuickApp development\nfunction QuickApp:onInit()\n    self:debug(\"QuickApp started\")\n    self:updateProperty(\"value\", 42)\nend\n```\n\n### Coroutines\n\n```lua\nlocal function asyncFunction()\n    print(\"Start\")\n    local co = coroutine.running()\n    \n    setTimeout(function() \n        coroutine.resume(co, \"result\") \n    end, 1000)\n    \n    local result = coroutine.yield()\n    print(\"Got result:\", result)\nend\n\ncoroutine.wrap(asyncFunction)()\n```\n\n## Examples\n\n### Example 1: HTTP Client with Timers\n\n```lua\nlocal client = net.HTTPClient()\n\n-- Make HTTP request with timer fallback\nlocal timer_id = setTimeout(function()\n    print(\"Request timeout!\")\nend, 5000)\n\nclient:get(\"https://httpbin.org/delay/2\", function(response)\n    clearTimeout(timer_id)\n    print(\"Response status:\", response.status)\n    print(\"Response time was acceptable\")\nend)\n```\n\n### Example 2: Interval Timer with Cancellation\n\n```lua\nlocal count = 0\nlocal interval_id = setInterval(function()\n    count = count + 1\n    print(\"Ping\", count)\n    \n    if count >= 5 then\n        print(\"Stopping interval\")\n        clearInterval(interval_id)\n    end\nend, 1000)\n```\n\n### Example 3: Coroutine with Async Operations\n\n```lua\nlocal function asyncTask()\n    print(\"Task starting...\")\n    \n    -- Simulate async work\n    local co = coroutine.running()\n    setTimeout(function() \n        coroutine.resume(co, \"async result\") \n    end, 2000)\n    \n    local result = coroutine.yield()\n    print(\"Task completed with:\", result)\nend\n\ncoroutine.wrap(asyncTask)()\n```\n\n## Architecture\n\n### Components\n\n- **`LuaInterpreter`**: Manages Lua runtime and script execution\n- **`LuaAsyncRuntime`**: Handles asyncio integration and timer management\n- **Timer System**: Maps Lua timer calls to Python asyncio tasks\n- **Callback Loop**: Executes Lua callbacks in the correct context\n\n### Flow\n\n1. Lua calls `setTimeout(callback, delay)`\n2. Python creates an asyncio task that waits for `delay`\n3. When timer fires, Python queues the callback ID\n4. Callback loop executes the Lua callback in the same context\n5. Lua coroutines can yield and be resumed by timers\n\n## \ud83d\udcda Documentation\n\nComprehensive documentation is available in the `docs/` directory:\n\n- **[Documentation Index](docs/README.md)** - Complete documentation overview\n- **[Web REPL HTML Examples](docs/WEB_REPL_HTML_EXAMPLES.md)** - HTML rendering guide for web interface\n- **[REST API Documentation](docs/api/README.md)** - Complete API reference and examples\n- **[Developer Documentation](docs/dev/README.md)** - Implementation details and development guides\n\n### Quick Links\n- \ud83d\ude80 **Getting Started**: This README\n- \ud83c\udf10 **Web Interface**: [Web REPL Examples](docs/WEB_REPL_HTML_EXAMPLES.md)\n- \ud83d\udce1 **API Integration**: [REST API Docs](docs/api/README.md)\n- \ud83d\udd27 **Contributing**: [Developer Docs](docs/dev/README.md)\n\n## Fibaro HC3 API Integration\n\nplua includes a comprehensive Fibaro Home Center 3 API emulator with full type safety and documentation:\n\n### Generated API Endpoints\n\nThe Fibaro API endpoints are auto-generated from official Swagger/OpenAPI specifications:\n\n```bash\n# Regenerate Fibaro API endpoints and models\npython src/plua/generate_typed_fibaro_api.py\n\n# Generate with custom paths\npython src/plua/generate_typed_fibaro_api.py --docs-dir fibaro_api_docs --output-dir src/plua\n```\n\nThis generates:\n- **`fibaro_api_models.py`**: 305+ Pydantic models with full type validation\n- **`fibaro_api_endpoints.py`**: 267+ FastAPI endpoints with proper documentation\n\n### Fibaro API Features\n\n- **Complete Coverage**: All major Fibaro HC3 API endpoints\n- **Type Safety**: Full Pydantic validation for request/response data\n- **Swagger Documentation**: Auto-generated API docs at `/docs`\n- **Lua Integration**: All calls delegate to `_PY.fibaro_api_hook(method, path, data)`\n- **Easy Testing**: Use web interface or curl to test endpoints\n\n```bash\n# Start server with Fibaro API\nplua --api-port 8888 --fibaro\n\n# Test an endpoint\ncurl -X GET \"http://localhost:8888/devices\" -H \"accept: application/json\"\n```\n\n### HC3 Configuration with .env File\n\nTo connect plua to a real Fibaro Home Center 3 device, create a `.env` file with your HC3 credentials. plua searches for `.env` files in the following order:\n\n1. **Current directory** (project-specific): `./.env`\n2. **Home directory** (user-global): `~/.env` \n3. **Config directory** (platform-specific):\n   - Linux/macOS: `~/.config/plua/.env`\n   - Windows: `%APPDATA%\\plua\\.env`\n\n```bash\n# Option 1: Project-specific .env (recommended for development)\ncd /path/to/your/fibaro/project\ncat > .env << EOF\nHC3_URL=https://192.168.1.100\nHC3_USER=admin\nHC3_PASSWORD=your_password_here\nEOF\n\n# Option 2: User-global .env (works from any directory)\ncat > ~/.env << EOF\nHC3_URL=https://192.168.1.100\nHC3_USER=admin\nHC3_PASSWORD=your_password_here\nEOF\n```\n\nThe `.env` file should contain:\n- **`HC3_URL`**: Your Home Center 3 IP address or hostname (without trailing slash)\n- **`HC3_USER`**: HC3 username (usually 'admin')  \n- **`HC3_PASSWORD`**: HC3 password\n\nExample `.env` file:\n```env\n# Fibaro HC3 Connection Settings\nHC3_URL=https://192.168.1.100\nHC3_USER=admin\nHC3_PASSWORD=mySecretPassword123\n\n# Optional: Add other environment variables your scripts might need\nDEBUG=true\nLOG_LEVEL=info\n```\n\n**Security Notes:**\n- Project-specific `.env` files: Add `.env` to your `.gitignore` file to prevent committing credentials\n- User-global `~/.env` file: Set appropriate file permissions (`chmod 600 ~/.env` on Unix systems)\n- Use HTTPS URLs when possible\n- Consider using environment variables directly in production environments\n\n**Usage Examples:**\n```bash\n# Works from any directory if you have ~/.env configured\ncd /any/directory\nplua --fibaro my_script.lua\n\n# Works from project directory with local .env\ncd /my/fibaro/project\nplua --fibaro script.lua   # Uses ./env (takes precedence over ~/.env)\n```\n\n**Usage in Lua Scripts:**\n```lua\n-- Access environment variables in your Lua code\nlocal hc3_url = os.getenv(\"HC3_URL\")\nlocal debug_mode = os.getenv(\"DEBUG\") == \"true\"\n\n-- Environment variables are automatically loaded by the Fibaro emulator\n-- when you use --fibaro flag\n```\n\nWhen you run plua with the `--fibaro` flag, it automatically reads these environment variables and configures the HC3 connection for API calls.\n\n## Development\n\n### Setup Development Environment\n\n```bash\n# Clone and setup\ngit clone https://github.com/jangabrielsson/plua\ncd plua\npip install -e \".[dev]\"\n\n# Setup HC3 credentials (optional, for Fibaro integration)\ncp .env.example .env\n# Edit .env with your HC3 credentials\n\n# Install GitHub CLI for releases\nbrew install gh\ngh auth login\n```\n\n### Run Tests\n\n```bash\npytest\n```\n\n### Code Formatting\n\n```bash\nblack src/ tests/\n```\n\n### Type Checking\n\n```bash\nmypy src/\n```\n\n### Creating Releases\n\nThe project uses automated GitHub Releases with PyPI publishing and executable building:\n\n```bash\n# Quick patch release (1.0.54 \u2192 1.0.55)\n./scripts/create-release.sh patch\n\n# Interactive release (choose patch/minor/major)  \n./scripts/create-release.sh\n\n# Custom version\n./scripts/create-release.sh \"2.0.0\" \"Major release with breaking changes\"\n```\n\nEach release automatically:\n- Publishes to PyPI\n- Builds executables for Linux, Windows, macOS (Intel + ARM)\n- Attaches binaries to GitHub release\n- Updates documentation\n\n## License\n\nMIT License\n\n## Requirements\n\n- Python 3.8+\n- lupa (Python-Lua bridge)\n- asyncio (built-in)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Python-Lua async runtime with timer support",
    "version": "1.0.99",
    "project_urls": {
        "Documentation": "https://github.com/jangabrielsson/plua/docs",
        "Homepage": "https://github.com/jangabrielsson/plua",
        "Issues": "https://github.com/jangabrielsson/plua/issues",
        "Repository": "https://github.com/jangabrielsson/plua.git"
    },
    "split_keywords": [
        "lua",
        " async",
        " timer",
        " coroutine"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e4441488fbb6f55b5dff46c31a8ed2813c7a8e2e5a7cab5fb1dda8e5921c4582",
                "md5": "2b679397d63af67c3b8b7efdeecade91",
                "sha256": "d5a127fd4633b15c735d53b866f6dbce28cadf010c54ceb2938861c38b0d81c6"
            },
            "downloads": -1,
            "filename": "plua-1.0.99-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2b679397d63af67c3b8b7efdeecade91",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 234851,
            "upload_time": "2025-07-26T21:55:56",
            "upload_time_iso_8601": "2025-07-26T21:55:56.863795Z",
            "url": "https://files.pythonhosted.org/packages/e4/44/1488fbb6f55b5dff46c31a8ed2813c7a8e2e5a7cab5fb1dda8e5921c4582/plua-1.0.99-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5a1a5a1273a6a86b52c9b83ab6ed1b4cdb22a9cc0dfca6191c0890dd38f122c5",
                "md5": "b4c2b295dbefc844cad937527d66add6",
                "sha256": "220d5d406a61dd3339cdec0f5a2f4371597645bf1283ad628763d872662fb07c"
            },
            "downloads": -1,
            "filename": "plua-1.0.99.tar.gz",
            "has_sig": false,
            "md5_digest": "b4c2b295dbefc844cad937527d66add6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 242509,
            "upload_time": "2025-07-26T21:55:58",
            "upload_time_iso_8601": "2025-07-26T21:55:58.690976Z",
            "url": "https://files.pythonhosted.org/packages/5a/1a/5a1273a6a86b52c9b83ab6ed1b4cdb22a9cc0dfca6191c0890dd38f122c5/plua-1.0.99.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-26 21:55:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jangabrielsson",
    "github_project": "plua",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "plua"
}
        
Elapsed time: 1.88145s