Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
67bb09f
Add Building Comfort tutorial (Python + Streamlit)
danielgerlag Jul 30, 2026
9f4231c
Make queries.py read as a plain, self-contained list
danielgerlag Jul 31, 2026
8d01987
Add Curbside Pickup tutorial (Python, cross-DB, single Streamlit UI)
danielgerlag Jul 31, 2026
a782c0b
Fix Streamlit startup in a fresh container (headless mode)
danielgerlag Jul 31, 2026
837124b
Give each Curbside panel its own bordered box
danielgerlag Jul 31, 2026
82efaa9
Highlight Cypher code blocks in the docs
danielgerlag Jul 31, 2026
299cf01
Add Getting Started tutorial (Python console app)
danielgerlag Jul 31, 2026
36131cb
Standardize Getting Started on docker exec (drop message scripts)
danielgerlag Jul 31, 2026
3173893
Use structural pattern matching in the Python reactions
danielgerlag Jul 31, 2026
c86bff9
Make the code-block copy button always visible
danielgerlag Jul 31, 2026
9f228da
Add getting-started devcontainer lock file
danielgerlag Jul 31, 2026
43e83e4
Consolidate Getting Started into a single app.py
danielgerlag Jul 31, 2026
6f38a14
Serve the docs at the root URL in local dev
danielgerlag Jul 31, 2026
f49b84d
Collapse Curbside demo/ into a single engine.py
danielgerlag Jul 31, 2026
b59e7f3
Inline the PICKUP_BY synthetic join in the curbside tutorial
danielgerlag Jul 31, 2026
5c13132
Add the getting-started queries inline instead of a dict loop
danielgerlag Jul 31, 2026
dcdd107
Collapse the building-comfort demo package into a single engine.py
danielgerlag Jul 31, 2026
c59a37b
Fix broken drasi.io PostgreSQL source reference link
danielgerlag Jul 31, 2026
b24a2f5
Address PR review: fail-fast DB readiness, modern asyncio, README gra…
danielgerlag Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .devcontainer/building-comfort/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"version": "2.5.9",
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "2.17.0",
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
"integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "1.3.8",
"resolved": "ghcr.io/devcontainers/features/git@sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2",
"integrity": "sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "1.8.0",
"resolved": "ghcr.io/devcontainers/features/python@sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511",
"integrity": "sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511"
}
}
}
60 changes: 60 additions & 0 deletions .devcontainer/building-comfort/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "Building Comfort Tutorial (Python)",
"image": "mcr.microsoft.com/devcontainers/base:bookworm@sha256:9e35ebf156350ba25b117da6869907034b6e2437b1891e3a43395af0b7d3eda4",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "29",
"moby": false
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12",
"installTools": true
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"configureZshAsDefaultShell": true
}
},
"postCreateCommand": "bash ../../.devcontainer/building-comfort/post-create.sh",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/tutorials/building-comfort",
"runArgs": [
"--privileged",
"--init",
"--ipc=host"
],
"forwardPorts": [
8501,
5732
],
"portsAttributes": {
"8501": {
"label": "Streamlit UI",
"onAutoForward": "notify"
},
"5732": {
"label": "PostgreSQL",
"onAutoForward": "silent"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"remoteUser": "vscode",
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
},
"containerEnv": {
"POSTGRES_HOST": "localhost",
"POSTGRES_PORT": "5732",
"POSTGRES_HOST_PORT": "5732",
"STREAMLIT_PORT": "8501"
}
}
24 changes: 24 additions & 0 deletions .devcontainer/building-comfort/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
# Post-create script for the Building Comfort tutorial (Python).

set -e

echo "🔧 Initializing the Building Comfort (Python) tutorial environment..."

# Resolve the tutorial directory from this script's location so the script works
# regardless of the current working directory.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TUTORIAL_DIR="$REPO_ROOT/tutorials/building-comfort"

# Install the tutorial's Python dependencies (drasi-lib, streamlit, psycopg).
# The devcontainer's Python feature provides a pip that is not externally
# managed, so a plain install works and puts `streamlit` on PATH.
echo "🐍 Installing Python dependencies..."
cd "$TUTORIAL_DIR"
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

echo ""
echo "✅ Building Comfort (Python) tutorial environment is ready!"
echo " Next: run 'bash scripts/start-demo.sh' (you are already in tutorials/building-comfort)"
24 changes: 24 additions & 0 deletions .devcontainer/curbside-pickup/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"version": "2.5.9",
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "2.17.0",
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
"integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "1.3.8",
"resolved": "ghcr.io/devcontainers/features/git@sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2",
"integrity": "sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "1.8.0",
"resolved": "ghcr.io/devcontainers/features/python@sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511",
"integrity": "sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511"
}
}
}
68 changes: 68 additions & 0 deletions .devcontainer/curbside-pickup/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "Curbside Pickup Tutorial (Python)",
"image": "mcr.microsoft.com/devcontainers/base:bookworm@sha256:9e35ebf156350ba25b117da6869907034b6e2437b1891e3a43395af0b7d3eda4",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "29",
"moby": false
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12",
"installTools": true
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"configureZshAsDefaultShell": true
}
},
"postCreateCommand": "bash ../../.devcontainer/curbside-pickup/post-create.sh",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/tutorials/curbside-pickup",
"runArgs": [
"--privileged",
"--init",
"--ipc=host"
],
"forwardPorts": [
8501,
5742,
3309
],
"portsAttributes": {
"8501": {
"label": "Streamlit UI",
"onAutoForward": "notify"
},
"5742": {
"label": "PostgreSQL (orders)",
"onAutoForward": "silent"
},
"3309": {
"label": "MySQL (vehicles)",
"onAutoForward": "silent"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"remoteUser": "vscode",
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
},
"containerEnv": {
"POSTGRES_HOST": "localhost",
"POSTGRES_PORT": "5742",
"POSTGRES_HOST_PORT": "5742",
"MYSQL_HOST": "localhost",
"MYSQL_PORT": "3309",
"MYSQL_HOST_PORT": "3309",
"STREAMLIT_PORT": "8501"
}
}
24 changes: 24 additions & 0 deletions .devcontainer/curbside-pickup/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
# Post-create script for the Curbside Pickup tutorial (Python).

set -e

echo "🔧 Initializing the Curbside Pickup (Python) tutorial environment..."

# Resolve the tutorial directory from this script's location so the script works
# regardless of the current working directory.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TUTORIAL_DIR="$REPO_ROOT/tutorials/curbside-pickup"

# Install the tutorial's Python dependencies (drasi-lib, streamlit, psycopg,
# PyMySQL). The devcontainer's Python feature provides a pip that is not
# externally managed, so a plain install works and puts `streamlit` on PATH.
echo "🐍 Installing Python dependencies..."
cd "$TUTORIAL_DIR"
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

echo ""
echo "✅ Curbside Pickup (Python) tutorial environment is ready!"
echo " Next: run 'bash scripts/start-demo.sh' (you are already in tutorials/curbside-pickup)"
24 changes: 24 additions & 0 deletions .devcontainer/getting-started/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"version": "2.5.9",
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "2.17.0",
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
"integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "1.3.8",
"resolved": "ghcr.io/devcontainers/features/git@sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2",
"integrity": "sha256:fd75977de13a9979000e0e78baf949adb0ca71d2398995fa22e0a36d7e7e7fe2"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "1.8.0",
"resolved": "ghcr.io/devcontainers/features/python@sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511",
"integrity": "sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511"
}
}
}
54 changes: 54 additions & 0 deletions .devcontainer/getting-started/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "Getting Started Tutorial (Python)",
"image": "mcr.microsoft.com/devcontainers/base:bookworm@sha256:9e35ebf156350ba25b117da6869907034b6e2437b1891e3a43395af0b7d3eda4",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "29",
"moby": false
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12",
"installTools": true
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"configureZshAsDefaultShell": true
}
},
"postCreateCommand": "bash ../../.devcontainer/getting-started/post-create.sh",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/tutorials/getting-started",
"runArgs": [
"--privileged",
"--init",
"--ipc=host"
],
"forwardPorts": [
5752
],
"portsAttributes": {
"5752": {
"label": "PostgreSQL",
"onAutoForward": "silent"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"remoteUser": "vscode",
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
},
"containerEnv": {
"POSTGRES_HOST": "localhost",
"POSTGRES_PORT": "5752",
"POSTGRES_HOST_PORT": "5752"
}
}
23 changes: 23 additions & 0 deletions .devcontainer/getting-started/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
# Post-create script for the Getting Started tutorial (Python).

set -e

echo "🔧 Initializing the Getting Started (Python) tutorial environment..."

# Resolve the tutorial directory from this script's location so the script works
# regardless of the current working directory.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TUTORIAL_DIR="$REPO_ROOT/tutorials/getting-started"

# Install the tutorial's Python dependency (drasi-lib). The devcontainer's Python
# feature provides a pip that is not externally managed, so a plain install works.
echo "🐍 Installing Python dependencies..."
cd "$TUTORIAL_DIR"
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

echo ""
echo "✅ Getting Started (Python) tutorial environment is ready!"
echo " Next: run 'bash scripts/start-demo.sh' (you are already in tutorials/getting-started)"
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ jobs:
- name: Python formatting
run: .venv/bin/ruff format --check .

- name: Tutorial READMEs are current
run: python3 scripts/render-tutorials.py --check

# This went unrun for long enough to accumulate 1653 errors from a single
# misconfiguration, which is exactly the kind of rot a gate is meant to
# prevent. pyright resolves `drasi` from the source tree, so the
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ on:
branches: [main]
paths:
- "website/**"
- "tutorials/**"
- ".github/workflows/website.yml"
pull_request:
branches: [main]
paths:
- "website/**"
- "tutorials/**"
- ".github/workflows/website.yml"

# Allow the deploy job to publish to GitHub Pages via OIDC.
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ make venv && make develop
.venv/bin/python examples/python_source.py
```

## Tutorials

Longer, hands-on walkthroughs live in [`tutorials/`](https://github.com/drasi-project/drasi-python/tree/main/tutorials).
The [Building Comfort](https://github.com/drasi-project/drasi-python/tree/main/tutorials/building-comfort)
tutorial builds a smart-building monitor from PostgreSQL CDC, six continuous
queries with synthetic joins, and a Python reaction that drives a live Streamlit
UI. The tutorials also render on the [documentation site](https://drasi-project.github.io/drasi-python/docs/tutorials/).

## Development

```bash
Expand Down
Loading
Loading