Metadata-Version: 2.4
Name: yorillow
Version: 1.0.0
Summary: Zero-dependency Python chart renderer — works offline, in APIs, and in serverless functions
Author: yorillow contributors
License: MIT
Project-URL: Homepage, https://github.com/harshi79/yorillow
Project-URL: Repository, https://github.com/harshi79/yorillow
Project-URL: Issues, https://github.com/harshi79/yorillow/issues
Keywords: charts,plotting,lightweight,png,svg,serverless,api
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Framework :: Flask
Classifier: Framework :: FastAPI
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# Yorillow

**Lightweight, zero-dependency Python chart renderer that generates PNG and SVG charts entirely in Python.**

Runs offline, inside Python applications, behind APIs, in Docker, on VPS servers, or in serverless environments.

```python
from yorillow import render

png = render({
    "type": "line",
    "x": [1, 2, 3, 4],
    "y": [[10, 20, 15, 30]],
    "title": "Sales",
})

with open("sales.png", "wb") as f:
    f.write(png)
```

No Pillow. No NumPy. No matplotlib. No Chromium. No Node.js. No browser. No database.

---

## Why Yorillow?

| | Yorillow | matplotlib | Chart.js |
|---|---|---|---|
| Runtime dependencies | **0** | numpy, Pillow, … | Node/browser |
| Returns | **bytes directly** | figure objects | HTML/JS |
| Serverless | **native** | requires setup | needs browser |
| Import time | **~27 ms** | seconds | N/A |
| Memory (800×600) | **~1.8 MiB** | ~50 MiB | N/A |

---

## Installation

```bash
python -m pip install yorillow
```

Then:

```python
from yorillow import render
```

**Package name:** `yorillow` (PyPI) / **Import name:** `yorillow` (Python)

---

## Quick Start

### Render to bytes

```python
from yorillow import render

png = render(config, format="png")   # bytes
svg = render(config, format="svg")   # str
```

### Save to file

```python
from yorillow import render_to_file

render_to_file(config, "chart.png")
render_to_file(config, "chart.svg")
```

### HTTP response helper

```python
from yorillow import render_response

resp = render_response(config, format="png")
# resp["status_code"]  → 200
# resp["content_type"] → "image/png"
# resp["body"]         → bytes
```

---

## Offline Usage

After installation, rendering requires **no internet, no API key, no external service**.

```python
from yorillow import render

png = render({"type": "line", "x": [1, 2, 3], "y": [[10, 20, 30]]})
```

### Completely offline installation

On an internet-connected machine:

```bash
python -m pip download yorillow
```

Transfer the downloaded file to the offline machine, then:

```bash
python -m pip install --no-index --find-links . yorillow
```

Since yorillow has zero runtime dependencies, only the yorillow package itself needs to be transferred.

---

## Chart Types

### Line

```python
render({
    "type": "line",
    "x": [1, 2, 3, 4, 5],
    "y": [[10, 20, 15, 25, 30], [5, 15, 10, 20, 25]],
    "labels": ["Revenue", "Profit"],
    "title": "Monthly Performance",
    "legend": True,
    "fill": True,
})
```

### Bar

```python
render({
    "type": "bar",
    "categories": ["Q1", "Q2", "Q3", "Q4"],
    "values": [[120, 150, 170, 200], [90, 130, 140, 180]],
    "labels": ["Product A", "Product B"],
    "stacked": False,
})
```

### Scatter

```python
render({
    "type": "scatter",
    "x": [1.0, 2.5, 3.7, 4.2, 5.8],
    "y": [10.0, 20.5, 15.3, 25.1, 30.0],
    "sizes": [5, 8, 6, 10, 4],
})
```

### Pie / Donut

```python
render({
    "type": "pie",
    "values": [35, 25, 20, 12, 8],
    "labels": ["Chrome", "Firefox", "Safari", "Edge", "Other"],
    "donut": True,
})
```

### Area

```python
render({
    "type": "area",
    "x": [1, 2, 3, 4, 5],
    "y": [[10, 20, 15, 25, 30], [5, 10, 8, 12, 15]],
    "labels": ["Downloads", "Installs"],
    "stacked": True,
})
```

---

## Themes

Built-in: `default`, `dark`, `minimal`, `neon`

```python
render({**config, "theme": "dark"})
```

---

## JSON Configuration

Chart configurations are plain JSON — no Python objects required.

```json
{
    "type": "line",
    "x": [1, 2, 3, 4],
    "y": [[10, 20, 15, 30]],
    "title": "Sales"
}
```

```python
import json
from yorillow import render

with open("chart.json") as f:
    config = json.load(f)

png = render(config)
```

This makes Yorillow useful when configuration comes from another program, a database, an API, or another language.

---

## CLI

```bash
yorillow chart.json -o chart.png          # render PNG
yorillow chart.json -o chart.svg          # render SVG
cat chart.json | yorillow -o chart.png    # stdin
yorillow chart.json --base64              # JSON with base64 data
yorillow chart.json --validate-only       # validate only
yorillow chart.json -o out.png --bench    # show timing
yorillow --version
yorillow --help
```

PowerShell:

```powershell
Get-Content chart.json -Raw | yorillow -o chart.png
```

---

## Build an API

Yorillow is the renderer, not the server.

```
Client → JSON → HTTP Server → yorillow.render() → PNG/SVG → HTTP Response
```

### stdlib (zero dependencies)

```bash
python examples/api/simple_http_server.py
```

```bash
curl -X POST http://localhost:8080/chart \
  -H "Content-Type: application/json" \
  -d '{"type":"line","x":[1,2,3],"y":[[10,20,30]]}' \
  --output chart.png
```

### Flask

```bash
pip install flask yorillow
python examples/api/flask_app.py
```

### FastAPI

```bash
pip install fastapi uvicorn yorillow
python -m uvicorn examples.api.fastapi_app:app
```

---

## Deploy

| Environment | Guide | Status |
|---|---|---|
| Local Python | [Offline Usage](#offline-usage) | ✓ Tested |
| CLI | [CLI](#cli) | ✓ Tested |
| VPS | [docs/deployment/vps.md](docs/deployment/vps.md) | ✓ Tested |
| Docker | [docs/deployment/docker.md](docs/deployment/docker.md) | ✓ Tested |
| Flask | [examples/api/flask_app.py](examples/api/flask_app.py) | Example |
| FastAPI | [examples/api/fastapi_app.py](examples/api/fastapi_app.py) | Example |
| Render | [docs/deployment/render.md](docs/deployment/render.md) | Example |
| Railway | [docs/deployment/railway.md](docs/deployment/railway.md) | Example |
| Vercel | [docs/deployment/vercel.md](docs/deployment/vercel.md) | Example |
| Netlify | [docs/deployment/netlify.md](docs/deployment/netlify.md) | Example |
| AWS Lambda | [docs/deployment/aws-lambda.md](docs/deployment/aws-lambda.md) | Example |

---

## Serverless Architecture

The core renderer is stateless and dependency-free, making it suitable for Python-compatible serverless runtimes.

```
Request → render() → PNG/SVG → Response
```

No persistent process. No database. No filesystem. No browser.

See [docs/architecture/serverless.md](docs/architecture/serverless.md).

---

## Performance

| Metric | Value |
|---|---|
| Import | ~27 ms |
| PNG 800×600 | ~60–90 ms |
| SVG 800×600 | <0.1 ms |
| PNG 1920×1080 | ~240 ms |
| Canvas 800×600 | 1.8 MiB |

Run `python benchmarks/bench.py` to reproduce.

See [docs/performance.md](docs/performance.md).

---

## Security

Yorillow validates all inputs: max dimensions, data point limits, NaN/Infinity rejection, type checking.

When exposing publicly, add authentication, rate limiting, and request size limits at the HTTP layer.

See [docs/security.md](docs/security.md).

---

## API Reference

| Function | Returns | Description |
|---|---|---|
| `render(config, format, encoding)` | `bytes`/`str` | Stateless chart renderer |
| `render_to_file(config, path)` | `None` | Render and save to file |
| `render_response(config, format)` | `dict` | HTTP response helper |

| Class | Description |
|---|---|
| `Canvas` | Low-level drawing surface |
| `LineChart` | Line chart |
| `BarChart` | Bar chart |
| `ScatterChart` | Scatter plot |
| `PieChart` | Pie / donut chart |
| `AreaChart` | Area chart |

| Exception | Description |
|---|---|
| `YorillowError` | Base exception |
| `ValidationError` | Invalid input |
| `RenderError` | Internal error |

Full reference: [docs/api/](docs/api/)

---

## Examples

| Example | Description |
|---|---|
| [examples/python/basic_png.py](examples/python/basic_png.py) | Basic PNG |
| [examples/python/basic_svg.py](examples/python/basic_svg.py) | Basic SVG |
| [examples/python/multiple_series.py](examples/python/multiple_series.py) | Multiple series |
| [examples/python/themes.py](examples/python/themes.py) | Theme demo |
| [examples/python/save_to_file.py](examples/python/save_to_file.py) | Save to file |
| [examples/python/json_config.py](examples/python/json_config.py) | JSON config |
| [examples/api/simple_http_server.py](examples/api/simple_http_server.py) | stdlib HTTP API |
| [examples/api/flask_app.py](examples/api/flask_app.py) | Flask API |
| [examples/api/fastapi_app.py](examples/api/fastapi_app.py) | FastAPI API |
| [examples/client/remote_client.py](examples/client/remote_client.py) | Python HTTP client |
| [examples/serverless/](examples/serverless/) | Serverless handlers |
| [examples/docker/](examples/docker/) | Docker |

---

## Development

```bash
git clone https://github.com/harshi79/yorillow.git
cd yorillow
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
python -m pytest tests/ -v
```

See [CONTRIBUTING.md](CONTRIBUTING.md).

---

## License

[MIT](LICENSE)
