# python-editor Browser-based Python editing: **FastAPI** serves static assets, stores workspace files, and optional **API key auth**. **Pyodide** runs your scripts and **Jedi** (inside Pyodide) powers completions — no server-side Python execution or Jedi. ## Run ```bash cp .env.example .env # optional: set WORKSPACE_ROOT, EDITOR_API_KEY, etc. pipenv install pipenv run dev ``` Configuration is read from **`.env`** at the repo root (see `.env.example`). Values there are applied when the app loads unless the variable is already set in your shell. [Pipenv](https://pipenv.pypa.io/) also loads `.env` for `pipenv run` commands. Tests (includes **pytest** and **selenium** in dev dependencies): ```bash pipenv run test pipenv run test-integration # Playwright; optional ``` ### Selenium Selenium talks to a **real browser** against a **running server** (not the in-process `TestClient`). 1. Install **Google Chrome** or Chromium on the machine (Selenium 4 uses [Selenium Manager](https://www.selenium.dev/documentation/selenium_manager/) to resolve a matching driver). 2. In one terminal, start the app (default `http://127.0.0.1:8080`): ```bash pipenv run dev ``` 3. In another terminal: ```bash pipenv run test-selenium ``` If the app listens elsewhere, set **`SELENIUM_BASE_URL`** (e.g. `http://127.0.0.1:9000`) before running. Or run only Selenium-marked tests: ```bash cd src && PYTHONPATH=. pipenv run pytest ../tests -m selenium -v ``` If nothing is listening, the smoke test **skips** with a short message instead of failing. Open [http://localhost:8080](http://localhost:8080). ## Deploy with Docker Build and run with Docker Compose: ```bash cp .env.example .env mkdir -p data docker compose up --build ``` Then open [http://localhost:8080](http://localhost:8080). Notes: - `workspace/` is mounted to `/app/workspace` so your code persists locally. - `data/` is mounted to `/app/data` for the SQLite auth DB. - In container mode, `WORKSPACE_ROOT` and `AUTH_DATABASE_PATH` are set by `docker-compose.yml`. **User accounts** — Set `AUTH_ENABLED=true` in `.env` to require sign-in for workspace APIs. Users live in a SQLite file (`AUTH_DATABASE_PATH`, default `./data/editor.db`). Use `/register` (if `AUTH_REGISTER_OPEN=true`) or `BOOTSTRAP_ADMIN_USERNAME` / `BOOTSTRAP_ADMIN_PASSWORD` for the first superuser. Superusers can **GET/POST/DELETE `/api/users`** to list, create, or remove accounts. **API key** — If `EDITOR_API_KEY` is set, requests may use `Authorization: Bearer …` instead of a session (useful for automation). When `AUTH_ENABLED=true`, a valid session *or* API key is accepted. The home page can store the API key in `sessionStorage` when you are not using cookie login, or use `?api_key=` on `/editor`. ## Layout - `src/` — FastAPI app and static UI (`src/static/`) - `workspace/` — default tree: `code/` (editable), `lib/` (read-only via API) ## ESP32 / NeoPixel mock The browser runtime now includes MicroPython-style mocks in `workspace/lib`: - `machine.Pin` - `neopixel.NeoPixel` Use them from scripts in `workspace/code` exactly like ESP32 examples: ```python from machine import Pin import neopixel np = neopixel.NeoPixel(Pin(4), 8) np[0] = (255, 0, 0) np.write() ``` `write()` updates the NeoPixel simulator window so you can verify behavior visually. Tutorial files: - `LED_TUTORIAL.md` - step-by-step NeoPixel tutorial - `workspace/code/led_tutorial.py` - runnable guided LED example - `workspace/code/led_patterns.py` - reusable pattern helpers (`rainbow_frame`, `chase_frame`, `twinkle_frame`) - `workspace/code/pattern_rainbow_demo.py` - rainbow animation demo - `workspace/code/pattern_chase_demo.py` - chase animation demo - `workspace/code/pattern_twinkle_demo.py` - twinkle animation demo - `workspace/code/panel16_utils.py` - helpers for 16x16 serpentine mapping - `workspace/code/panel16_rainbow_wave.py` - 16x16 rainbow wave - `workspace/code/panel16_bounce.py` - 16x16 bouncing pixel with trail - `workspace/code/panel16_matrix_rain.py` - 16x16 matrix rain effect ## Dev auto-reload hook Project hook files are included in `.cursor/`: - `.cursor/hooks.json` - `.cursor/hooks/dev-reload-touch.sh` When files are edited through Cursor tools, the hook updates `src/static/.reload-token`. The editor (on localhost) polls that token and auto-reloads the browser when it changes.