Name | plua JSON |
Version |
1.0.99
JSON |
| download |
home_page | None |
Summary | Python-Lua async runtime with timer support |
upload_time | 2025-07-26 21:55:58 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.8 |
license | None |
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"
}