Skip to content

Commit

Permalink
batman
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverlambson committed Aug 10, 2024
0 parents commit 4d037b6
Show file tree
Hide file tree
Showing 31 changed files with 1,212 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.venv/
.env
__pycache__
.mypy_cache
.ruff_cache
.pytest_cache
*.py[cod]
25 changes: 25 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# EditorConfig is awesome: https://editorconfig.org

# top-most EditorConfig file
root = true

[*]
end_of_line = lf
insert_final_newline = true

[*.{js,py}]
charset = utf-8

[*.py]
indent_style = space
indent_size = 4

[*.{yaml,toml}]
indent_style = space
indent_size = 2

[pyproject.toml]
indent_size = 4

[Makefile]
indent_style = tab
12 changes: 12 additions & 0 deletions .github/actions/setup-node/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Setup node
description: Setup node (including caching)

runs:
using: "composite"
steps:
- uses: actions/setup-node@v4
with:
node-version: "20"

- run: npm i
shell: bash
43 changes: 43 additions & 0 deletions .github/actions/setup-python/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Setup python (rye)
description: Setup python with rye (including caching)

inputs:
python-version:
description: python version
default: "3.12"
extra-cache:
description: extra globs to cache
default: ""

runs:
using: "composite"
steps:
- uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}

- run: >
[ -f .python-version ] || echo "${{ inputs.python-version }}" > .python-version
shell: bash
- id: setup-rye
uses: eifinger/setup-rye@v4
with:
enable-cache: true

- run: rye sync
shell: bash

- name: set-cache-name
id: set-cache-name
run: |
cache_name="$(echo '${{ inputs.extra-cache }}' | tr '\n' '-')"
echo "cache-name=$cache_name" >>$GITHUB_OUTPUT
shell: bash

- if: ${{ 'inputs.extra-cache' != '' }}
name: extra-cache
uses: actions/cache@v4
with:
path: ${{ inputs.extra-cache }}
key: ${{ runner.os }}-${{ steps.set-cache-name.outputs.cache-name }}
45 changes: 45 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: test

on:
push:
branches:
- main
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review

concurrency:
group: ${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup python
uses: ./.github/actions/setup-python
with:
extra-cache: .ruff_cache
- name: Setup node
uses: ./.github/actions/setup-node
- name: lint
run: make lint

test:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup python
uses: ./.github/actions/setup-python
with:
extra-cache: |
.mypy_cache
.pytest_cache
- name: test
run: |
make test
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dist/
.venv/
.env
__pycache__
.mypy_cache
.ruff_cache
.pytest_cache
*.py[cod]
node_modules/
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.min.js
*.min.css
15 changes: 15 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"plugins": ["prettier-plugin-jinja-template", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
},
{
"files": ["*.html"],
"options": {
"parser": "jinja-template"
}
}
]
}
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM python:3.12-slim AS base

RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/* && \
useradd --uid 1001 --user-group --home-dir=/home/bored-charts --create-home --shell=/bin/false bored-charts

# ------------------------------------------------------------------------------
FROM base AS app

WORKDIR /app
RUN chown bored-charts:bored-charts /app

COPY --chown=bored-charts requirements.lock pyproject.toml ./
RUN mkdir -p src/boredcharts/ && \
touch README.md src/boredcharts/__init__.py && \
pip install -r requirements.lock

COPY --chown=bored-charts ./ /app/

WORKDIR /app

ENV PYTHONUNBUFFERED=1
USER bored-charts
EXPOSE 4000
CMD ["boredcharts"]
HEALTHCHECK CMD ["curl", "--fail", "http://localhost:4000/healthz"]
7 changes: 7 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright 2024 Oliver Lambson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
60 changes: 60 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.DEFAULT_GOAL := help

YELLOW := \033[0;33m
RESET := \033[0m

.PHONY: help
## Prints this help
help:
@echo "\nUsage: make ${YELLOW}[arg=value] <target>${RESET}\n\nThe following targets are available:\n";
@awk -v skip=1 \
'/^##/ { sub(/^[#[:blank:]]*/, "", $$0); doc_h=$$0; doc=""; skip=0; next } \
skip { next } \
/^#/ { doc=doc "\n" substr($$0, 2); next } \
/:/ { sub(/:.*/, "", $$0); printf "\033[34m%-30s\033[0m\033[1m%s\033[0m %s\n", $$0, doc_h, doc; skip=1 }' \
$(MAKEFILE_LIST)

.PHONY: env
## (Re-)create virtual environment
env:
rm -rf .venv
rm -rf node_modules
rye sync
npm i

.PHONY: test
## Run test
test:
rye run mypy .
rye run pytest

.PHONY: lint
## Run linting
lint:
rye run ruff check .
rye run ruff format . --check
rye run mdformat README.md boredcharts/ --check
npx prettier . --check

.PHONY: fmt
## Run linting
fmt:
rye run ruff check . --fix
rye run ruff format .
rye run mdformat README.md boredcharts/
npx prettier . --write

.PHONY: dev
## Run locally
dev:
UVICORN_RELOAD=true rye run boredcharts

.PHONY: d.up
## Start docker compose
d.up:
docker compose up --build

.PHONY: d.down
## Stop docker compose
d.down:
docker compose down --remove-orphans
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# bored-charts

Build easy, minimal, PDF-able data reports with markdown and python.

## Roadmap

- [ ] custom figures for individual reports using path parameters
- [ ] installable as a framework
- [ ] example with database
- [ ] authentication
- [ ] pdf exports
- [ ] cli?

## Setup

You'll need [rye](https://rye.astral.sh/guide/installation/).
(and [node](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs)
for linting/formatting, sorry)

```bash
make env # sets up python virtual environment
make dev # runs bored-charts at http://localhost:4000
```

## Development

```bash
make dev # runs bored-charts at http://localhost:4000
make test # runs tests
make lint # runs linting
make fmt # runs formatting
```

## Built with

- [fastapi](https://fastapi.tiangolo.com/)
- [htmx](https://htmx.org/)
- [jinja](https://jinja.palletsprojects.com/en/3.1.x/)
- [tailwindcss](https://tailwindcss.com/)
- [plotly](https://plotly.com/python/)

## References

Inspired by [evidence.dev](https://github.com/evidence-dev/evidence),
[observable framework](https://github.com/observablehq/framework), and
[rill](https://github.com/rilldata/rill), but:
(1) I wanted to use python for data analysis and charting,
(2) I didn't want a static site, and
(3) I didn't want to pay for deployment.
1 change: 1 addition & 0 deletions boredcharts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.1.0"
21 changes: 21 additions & 0 deletions boredcharts/figures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import plotly.express as px
from plotly.graph_objects import Figure


async def example(country: str) -> Figure:
df = px.data.gapminder().query(f"country=='{country}'")
fig = px.bar(df, x="year", y="pop")
fig.update_layout(
plot_bgcolor="white",
xaxis=dict(
title="",
tickangle=-45,
),
yaxis=dict(
gridcolor="lightgrey",
title="Population",
minor=dict(ticks="inside"),
),
legend=dict(title=""),
)
return fig
1 change: 1 addition & 0 deletions boredcharts/static/htmx-2.0.1.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit 4d037b6

Please sign in to comment.