Skip to content

Actually start a repo #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 27 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Code Checks

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10']

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install Testing Dependencies
run: make install
- name: Unittest
run: make test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.sesskey
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
install:
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
python -m pip install wheel twine

pypi:
python setup.py sdist
python setup.py bdist_wheel --universal
twine upload dist/*

test:
pytest
76 changes: 74 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,74 @@
# fh-matplotlib
Making it easier to show matplotlib charts in FastHTML
### fh-matplotlib

Making it easier to show matplotlib charts in FastHTML.

## Usage

You can install this tool by running:

```
python -m pip install fh-matplotlib
```

After this step, it is ready for use! At the moment this package merely contains a decorator. You can use it to wrap any function that generates a matplotlib chart in order for it to return an `Img` for FastHTML to render. In, short you would typically use it like this:

```python
import numpy as np
import matplotlib.pylab as plt
from fh_matplotlib import matplotlib2fasthtml

# This function will return a proper Img that can be rendered
@matplotlib2fasthtml
def matplotlib_function():
plt.plot(np.arange(25), np.random.exponential(1, size=25))
```

<details>
<summary><b>Want to see a full example that you could copy and paste directly?</b></summary>

```python
from fh_matplotlib import matplotlib2fasthtml
from fasthtml.common import *
import numpy as np
import matplotlib.pylab as plt

app, rt = fast_app()


count = 0
plotdata = []

@matplotlib2fasthtml
def generate_chart():
global plotdata
plt.plot(range(len(plotdata)), plotdata)


@app.get("/")
def home():
return Title("Matplotlib Demo"), Main(
H1("Matplotlib Demo"),
P("Nothing too fancy, but still kind of fancy."),
Div(f"You have pressed the button {count} times.", id="chart"),
Button("Increment", hx_get="/increment", hx_target="#chart", hx_swap="innerHTML"),
style="margin: 20px"
)


@app.get("/increment/")
def increment():
global plotdata, count
count += 1
plotdata.append(np.random.exponential(1))
return Div(
generate_chart(),
P(f"You have pressed the button {count} times."),
)

serve()
```
</details>

## Roadmap

This repository is originally meant to be simple helper, but if there are more advanced use-cases to consider I will gladly consider them. Please start a conversation by opening up an issue before starting a PR though.
39 changes: 39 additions & 0 deletions examples/clicker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from fh_matplotlib import matplotlib2fasthtml
from fasthtml.common import *
import numpy as np
import matplotlib.pylab as plt

app, rt = fast_app()


count = 0
plotdata = []

@matplotlib2fasthtml
def generate_chart():
global plotdata
plt.plot(range(len(plotdata)), plotdata)


@app.get("/")
def home():
return Title("Matplotlib Demo"), Main(
H1("Matplotlib Demo"),
P("Nothing too fancy, but still kind of fancy."),
Div(f"You have pressed the button {count} times.", id="chart"),
Button("Increment", hx_get="/increment", hx_target="#chart", hx_swap="innerHTML"),
style="margin: 20px"
)


@app.get("/increment/")
def increment():
global plotdata, count
count += 1
plotdata.append(np.random.exponential(1))
return Div(
generate_chart(),
P(f"You have pressed the button {count} times."),
)

serve()
37 changes: 37 additions & 0 deletions fh_matplotlib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from fasthtml.common import Img
import matplotlib.pylab as plt
import io
import base64


def matplotlib2fasthtml(func):
'''
Ensure that matplotlib yielding function returns a renderable item for FastHTML.

Usage:

```python
import numpy as np
import matplotlib.pylab as plt
from fh_matplotlib import matplotlib2fasthtml

# This function will return a proper Img that can be rendered
@matplotlib2fasthtml
def matplotlib_function():
plt.plot(np.arange(25), np.random.exponential(1, size=25))
```
'''
def wrapper(*args, **kwargs):
# Reset the figure to prevent accumulation. Maybe we need a setting for this?
plt.figure()

# Run function as normal
func(*args, **kwargs)

# Store it as base64 and put it into an image.
my_stringIObytes = io.BytesIO()
plt.savefig(my_stringIObytes, format='jpg')
my_stringIObytes.seek(0)
my_base64_jpgData = base64.b64encode(my_stringIObytes.read()).decode()
return Img(src=f'data:image/jpg;base64, {my_base64_jpgData}')
return wrapper
11 changes: 11 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from setuptools import setup, find_packages

setup(
name="fh-matplotlib",
version="0.0.1",
packages=find_packages(),
install_requires=["matplotlib", "python-fasthtml"],
extras_require={
"dev": ["pytest"],
},
)
Empty file added tests/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions tests/test_basics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import numpy as np
import matplotlib.pylab as plt
from fh_matplotlib import matplotlib2fasthtml

# This function will return a proper Img that can be rendered
@matplotlib2fasthtml
def matplotlib_function():
plt.plot(np.arange(25), np.random.exponential(1, size=25))

def test_no_err():
matplotlib_function()
Loading