Metadata-Version: 2.5
Name: runlight
Version: 0.1.1
Summary: Privacy friendly web analytics that lives inside your Python app. Mount a route, add a script tag, read your stats at /runlight.
Project-URL: Homepage, https://runlight.sh
Project-URL: Documentation, https://runlight.sh/docs/python/
Project-URL: Source, https://github.com/runlightsh/runlight/tree/main/packages/python
Project-URL: Issues, https://github.com/runlightsh/runlight/issues
Author: Jon C. Phillips
License-Expression: MIT
License-File: LICENSE
Keywords: analytics,django,fastapi,flask,privacy,short links,web analytics
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: FastAPI
Classifier: Framework :: Flask
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: Log Analysis
Classifier: Typing :: Typed
Requires-Python: >=3.11
Provides-Extra: mysql
Requires-Dist: pymysql>=1.1; extra == 'mysql'
Provides-Extra: postgres
Requires-Dist: psycopg>=3.2; extra == 'postgres'
Provides-Extra: tzdata
Requires-Dist: tzdata; extra == 'tzdata'
Description-Content-Type: text/markdown

# runlight

Runlight is privacy friendly web analytics that runs inside your own Python app. It counts visitors without cookies and without storing anyone’s IP address. The numbers stay in your database, and the dashboard is served from your domain at `/runlight`.

This package is the Python version of [Runlight](https://runlight.sh). It works in Django, Flask, FastAPI, or any WSGI or ASGI app on Python 3.11 or later, and it can also run on its own domain as a standalone server. It answers every request the way the TypeScript library does and uses the same tables, so either one can read the other’s database.

## Get started

Install it with pip.

```bash
pip install runlight
```

SQLite comes with Python. For Postgres, install `runlight[postgres]`, and for MySQL or MariaDB, `runlight[mysql]`. On Windows, add the `tzdata` extra for time zones.

Create one instance for your app.

```python
from runlight import Runlight
from runlight.store import Stores

rl = Runlight(
    store=Stores.sqlite("data/runlight.db"),
    site={"name": "example.com", "hostnames": ["example.com"], "timezone": "Europe/London"},
)
```

If nothing sits in front of your app (no load balancer, CDN, or reverse proxy), add `trust_proxy=False`, so a visitor cannot pick their own address with an `X-Forwarded-For` header. Runlight logs a warning once when it sees requests arrive that way with the default left on.

Put it in front of your app. In Flask that is one line.

```python
import runlight.flask

runlight.flask.init_app(app, rl)
```

Add the script to every page, just before `</head>`.

```html
<script defer src="/runlight/s.js"></script>
```

Set `RUNLIGHT_TOKEN` to a long random string, then open `/runlight/?token=` followed by that string to sign in.

A `token` passed to `rl.routes()` works the same way. `None` counts as not given, so `os.environ.get()` of a variable that is not set falls back to `RUNLIGHT_TOKEN` and never opens the dashboard. To leave it open on purpose, behind your own sign-in, pass `token=runlight.OPEN`.

The [Python guide](https://runlight.sh/docs/python/) has the code for Django, FastAPI, and plain WSGI or ASGI apps, the Postgres, MySQL, and MariaDB stores, the scheduled check, and the standalone server.

## License

Runlight is MIT licensed.
