yorillow 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
yorillow-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yorillow contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,423 @@
1
+ Metadata-Version: 2.4
2
+ Name: yorillow
3
+ Version: 1.0.0
4
+ Summary: Zero-dependency Python chart renderer — works offline, in APIs, and in serverless functions
5
+ Author: yorillow contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/harshi79/yorillow
8
+ Project-URL: Repository, https://github.com/harshi79/yorillow
9
+ Project-URL: Issues, https://github.com/harshi79/yorillow/issues
10
+ Keywords: charts,plotting,lightweight,png,svg,serverless,api
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Multimedia :: Graphics
21
+ Classifier: Framework :: Flask
22
+ Classifier: Framework :: FastAPI
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # Yorillow
31
+
32
+ **Lightweight, zero-dependency Python chart renderer that generates PNG and SVG charts entirely in Python.**
33
+
34
+ Runs offline, inside Python applications, behind APIs, in Docker, on VPS servers, or in serverless environments.
35
+
36
+ ```python
37
+ from yorillow import render
38
+
39
+ png = render({
40
+ "type": "line",
41
+ "x": [1, 2, 3, 4],
42
+ "y": [[10, 20, 15, 30]],
43
+ "title": "Sales",
44
+ })
45
+
46
+ with open("sales.png", "wb") as f:
47
+ f.write(png)
48
+ ```
49
+
50
+ No Pillow. No NumPy. No matplotlib. No Chromium. No Node.js. No browser. No database.
51
+
52
+ ---
53
+
54
+ ## Why Yorillow?
55
+
56
+ | | Yorillow | matplotlib | Chart.js |
57
+ |---|---|---|---|
58
+ | Runtime dependencies | **0** | numpy, Pillow, … | Node/browser |
59
+ | Returns | **bytes directly** | figure objects | HTML/JS |
60
+ | Serverless | **native** | requires setup | needs browser |
61
+ | Import time | **~27 ms** | seconds | N/A |
62
+ | Memory (800×600) | **~1.8 MiB** | ~50 MiB | N/A |
63
+
64
+ ---
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ python -m pip install yorillow
70
+ ```
71
+
72
+ Then:
73
+
74
+ ```python
75
+ from yorillow import render
76
+ ```
77
+
78
+ **Package name:** `yorillow` (PyPI) / **Import name:** `yorillow` (Python)
79
+
80
+ ---
81
+
82
+ ## Quick Start
83
+
84
+ ### Render to bytes
85
+
86
+ ```python
87
+ from yorillow import render
88
+
89
+ png = render(config, format="png") # bytes
90
+ svg = render(config, format="svg") # str
91
+ ```
92
+
93
+ ### Save to file
94
+
95
+ ```python
96
+ from yorillow import render_to_file
97
+
98
+ render_to_file(config, "chart.png")
99
+ render_to_file(config, "chart.svg")
100
+ ```
101
+
102
+ ### HTTP response helper
103
+
104
+ ```python
105
+ from yorillow import render_response
106
+
107
+ resp = render_response(config, format="png")
108
+ # resp["status_code"] → 200
109
+ # resp["content_type"] → "image/png"
110
+ # resp["body"] → bytes
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Offline Usage
116
+
117
+ After installation, rendering requires **no internet, no API key, no external service**.
118
+
119
+ ```python
120
+ from yorillow import render
121
+
122
+ png = render({"type": "line", "x": [1, 2, 3], "y": [[10, 20, 30]]})
123
+ ```
124
+
125
+ ### Completely offline installation
126
+
127
+ On an internet-connected machine:
128
+
129
+ ```bash
130
+ python -m pip download yorillow
131
+ ```
132
+
133
+ Transfer the downloaded file to the offline machine, then:
134
+
135
+ ```bash
136
+ python -m pip install --no-index --find-links . yorillow
137
+ ```
138
+
139
+ Since yorillow has zero runtime dependencies, only the yorillow package itself needs to be transferred.
140
+
141
+ ---
142
+
143
+ ## Chart Types
144
+
145
+ ### Line
146
+
147
+ ```python
148
+ render({
149
+ "type": "line",
150
+ "x": [1, 2, 3, 4, 5],
151
+ "y": [[10, 20, 15, 25, 30], [5, 15, 10, 20, 25]],
152
+ "labels": ["Revenue", "Profit"],
153
+ "title": "Monthly Performance",
154
+ "legend": True,
155
+ "fill": True,
156
+ })
157
+ ```
158
+
159
+ ### Bar
160
+
161
+ ```python
162
+ render({
163
+ "type": "bar",
164
+ "categories": ["Q1", "Q2", "Q3", "Q4"],
165
+ "values": [[120, 150, 170, 200], [90, 130, 140, 180]],
166
+ "labels": ["Product A", "Product B"],
167
+ "stacked": False,
168
+ })
169
+ ```
170
+
171
+ ### Scatter
172
+
173
+ ```python
174
+ render({
175
+ "type": "scatter",
176
+ "x": [1.0, 2.5, 3.7, 4.2, 5.8],
177
+ "y": [10.0, 20.5, 15.3, 25.1, 30.0],
178
+ "sizes": [5, 8, 6, 10, 4],
179
+ })
180
+ ```
181
+
182
+ ### Pie / Donut
183
+
184
+ ```python
185
+ render({
186
+ "type": "pie",
187
+ "values": [35, 25, 20, 12, 8],
188
+ "labels": ["Chrome", "Firefox", "Safari", "Edge", "Other"],
189
+ "donut": True,
190
+ })
191
+ ```
192
+
193
+ ### Area
194
+
195
+ ```python
196
+ render({
197
+ "type": "area",
198
+ "x": [1, 2, 3, 4, 5],
199
+ "y": [[10, 20, 15, 25, 30], [5, 10, 8, 12, 15]],
200
+ "labels": ["Downloads", "Installs"],
201
+ "stacked": True,
202
+ })
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Themes
208
+
209
+ Built-in: `default`, `dark`, `minimal`, `neon`
210
+
211
+ ```python
212
+ render({**config, "theme": "dark"})
213
+ ```
214
+
215
+ ---
216
+
217
+ ## JSON Configuration
218
+
219
+ Chart configurations are plain JSON — no Python objects required.
220
+
221
+ ```json
222
+ {
223
+ "type": "line",
224
+ "x": [1, 2, 3, 4],
225
+ "y": [[10, 20, 15, 30]],
226
+ "title": "Sales"
227
+ }
228
+ ```
229
+
230
+ ```python
231
+ import json
232
+ from yorillow import render
233
+
234
+ with open("chart.json") as f:
235
+ config = json.load(f)
236
+
237
+ png = render(config)
238
+ ```
239
+
240
+ This makes Yorillow useful when configuration comes from another program, a database, an API, or another language.
241
+
242
+ ---
243
+
244
+ ## CLI
245
+
246
+ ```bash
247
+ yorillow chart.json -o chart.png # render PNG
248
+ yorillow chart.json -o chart.svg # render SVG
249
+ cat chart.json | yorillow -o chart.png # stdin
250
+ yorillow chart.json --base64 # JSON with base64 data
251
+ yorillow chart.json --validate-only # validate only
252
+ yorillow chart.json -o out.png --bench # show timing
253
+ yorillow --version
254
+ yorillow --help
255
+ ```
256
+
257
+ PowerShell:
258
+
259
+ ```powershell
260
+ Get-Content chart.json -Raw | yorillow -o chart.png
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Build an API
266
+
267
+ Yorillow is the renderer, not the server.
268
+
269
+ ```
270
+ Client → JSON → HTTP Server → yorillow.render() → PNG/SVG → HTTP Response
271
+ ```
272
+
273
+ ### stdlib (zero dependencies)
274
+
275
+ ```bash
276
+ python examples/api/simple_http_server.py
277
+ ```
278
+
279
+ ```bash
280
+ curl -X POST http://localhost:8080/chart \
281
+ -H "Content-Type: application/json" \
282
+ -d '{"type":"line","x":[1,2,3],"y":[[10,20,30]]}' \
283
+ --output chart.png
284
+ ```
285
+
286
+ ### Flask
287
+
288
+ ```bash
289
+ pip install flask yorillow
290
+ python examples/api/flask_app.py
291
+ ```
292
+
293
+ ### FastAPI
294
+
295
+ ```bash
296
+ pip install fastapi uvicorn yorillow
297
+ python -m uvicorn examples.api.fastapi_app:app
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Deploy
303
+
304
+ | Environment | Guide | Status |
305
+ |---|---|---|
306
+ | Local Python | [Offline Usage](#offline-usage) | ✓ Tested |
307
+ | CLI | [CLI](#cli) | ✓ Tested |
308
+ | VPS | [docs/deployment/vps.md](docs/deployment/vps.md) | ✓ Tested |
309
+ | Docker | [docs/deployment/docker.md](docs/deployment/docker.md) | ✓ Tested |
310
+ | Flask | [examples/api/flask_app.py](examples/api/flask_app.py) | Example |
311
+ | FastAPI | [examples/api/fastapi_app.py](examples/api/fastapi_app.py) | Example |
312
+ | Render | [docs/deployment/render.md](docs/deployment/render.md) | Example |
313
+ | Railway | [docs/deployment/railway.md](docs/deployment/railway.md) | Example |
314
+ | Vercel | [docs/deployment/vercel.md](docs/deployment/vercel.md) | Example |
315
+ | Netlify | [docs/deployment/netlify.md](docs/deployment/netlify.md) | Example |
316
+ | AWS Lambda | [docs/deployment/aws-lambda.md](docs/deployment/aws-lambda.md) | Example |
317
+
318
+ ---
319
+
320
+ ## Serverless Architecture
321
+
322
+ The core renderer is stateless and dependency-free, making it suitable for Python-compatible serverless runtimes.
323
+
324
+ ```
325
+ Request → render() → PNG/SVG → Response
326
+ ```
327
+
328
+ No persistent process. No database. No filesystem. No browser.
329
+
330
+ See [docs/architecture/serverless.md](docs/architecture/serverless.md).
331
+
332
+ ---
333
+
334
+ ## Performance
335
+
336
+ | Metric | Value |
337
+ |---|---|
338
+ | Import | ~27 ms |
339
+ | PNG 800×600 | ~60–90 ms |
340
+ | SVG 800×600 | <0.1 ms |
341
+ | PNG 1920×1080 | ~240 ms |
342
+ | Canvas 800×600 | 1.8 MiB |
343
+
344
+ Run `python benchmarks/bench.py` to reproduce.
345
+
346
+ See [docs/performance.md](docs/performance.md).
347
+
348
+ ---
349
+
350
+ ## Security
351
+
352
+ Yorillow validates all inputs: max dimensions, data point limits, NaN/Infinity rejection, type checking.
353
+
354
+ When exposing publicly, add authentication, rate limiting, and request size limits at the HTTP layer.
355
+
356
+ See [docs/security.md](docs/security.md).
357
+
358
+ ---
359
+
360
+ ## API Reference
361
+
362
+ | Function | Returns | Description |
363
+ |---|---|---|
364
+ | `render(config, format, encoding)` | `bytes`/`str` | Stateless chart renderer |
365
+ | `render_to_file(config, path)` | `None` | Render and save to file |
366
+ | `render_response(config, format)` | `dict` | HTTP response helper |
367
+
368
+ | Class | Description |
369
+ |---|---|
370
+ | `Canvas` | Low-level drawing surface |
371
+ | `LineChart` | Line chart |
372
+ | `BarChart` | Bar chart |
373
+ | `ScatterChart` | Scatter plot |
374
+ | `PieChart` | Pie / donut chart |
375
+ | `AreaChart` | Area chart |
376
+
377
+ | Exception | Description |
378
+ |---|---|
379
+ | `YorillowError` | Base exception |
380
+ | `ValidationError` | Invalid input |
381
+ | `RenderError` | Internal error |
382
+
383
+ Full reference: [docs/api/](docs/api/)
384
+
385
+ ---
386
+
387
+ ## Examples
388
+
389
+ | Example | Description |
390
+ |---|---|
391
+ | [examples/python/basic_png.py](examples/python/basic_png.py) | Basic PNG |
392
+ | [examples/python/basic_svg.py](examples/python/basic_svg.py) | Basic SVG |
393
+ | [examples/python/multiple_series.py](examples/python/multiple_series.py) | Multiple series |
394
+ | [examples/python/themes.py](examples/python/themes.py) | Theme demo |
395
+ | [examples/python/save_to_file.py](examples/python/save_to_file.py) | Save to file |
396
+ | [examples/python/json_config.py](examples/python/json_config.py) | JSON config |
397
+ | [examples/api/simple_http_server.py](examples/api/simple_http_server.py) | stdlib HTTP API |
398
+ | [examples/api/flask_app.py](examples/api/flask_app.py) | Flask API |
399
+ | [examples/api/fastapi_app.py](examples/api/fastapi_app.py) | FastAPI API |
400
+ | [examples/client/remote_client.py](examples/client/remote_client.py) | Python HTTP client |
401
+ | [examples/serverless/](examples/serverless/) | Serverless handlers |
402
+ | [examples/docker/](examples/docker/) | Docker |
403
+
404
+ ---
405
+
406
+ ## Development
407
+
408
+ ```bash
409
+ git clone https://github.com/harshi79/yorillow.git
410
+ cd yorillow
411
+ python -m venv .venv
412
+ source .venv/bin/activate
413
+ pip install -e ".[dev]"
414
+ python -m pytest tests/ -v
415
+ ```
416
+
417
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
418
+
419
+ ---
420
+
421
+ ## License
422
+
423
+ [MIT](LICENSE)