External Link
X (formerly Twitter) · twitter.com [1]
Fastapi [2] passes flask in GitHub stars!
[1]
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://twitter.com/tiangolo/status/1729153717956715007
[2]: /fastapi/
[3]: /thoughts/
Posts tagged: python
All posts with the tag "python"
312 posts
latest post 2026-05-06
Publishing rhythm
Hosted Platform Brainstorm
[1]
[1]
- shots
- shots templates
- gradient backgrounds
- premium feature upload your own background
- ogs
- scrape og [2] info, generate og image
- og’s build on shots, they are just hosted template endpoints that get a screenshots
- potentially auto approve og’s from rss
- drops
- drop a file to share
- limited size, limited upload MB’s / month
- archives
- deep permalink a website
- https://pypi.org/project/pywebcopy/
- og-links
- ai-covers
- give me an url, and a selector, I will read your article and give you an ai generated cover image
- ai-summaries
- give me an url, and a selector, I will read your article and give you an ai generated summary
- ai-voice - voices
- give me an url, and a selector, I will read your article and give you an ai generated voice
- image-optimization
- use the image optimization pipelie for shots to give you an optimized image
- blur ups
Community # [3]
host it yourself
- reader
- markata
Limits # [4]
cloudflare file ...
Litestar: Effortlessly Build Performant APIs
We all know about Flask and Django. And of course FastAPI made a huge splash when it came on the scene a few years ago. But new web frameworks are being created all the time. And they have these ea...
talkpython.fm [1]
Litestar is an interesting api framework similar to fastpi, that I am interested to check out to see if it fits into some project scope. It sounds like it comes with a lot more batteries included for things like auth, but does not have hard opinions like django. At this point I’m not jumping off of fastapi [2], but its something I want to try.
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://talkpython.fm/episodes/show/433/litestar-effortlessly-build-performant-apis
[2]: /fastapi/
[3]: /thoughts/
GitHub - florimondmanca/arel: Lightweight browser hot reload for Python ASGI web apps
Lightweight browser hot reload for Python ASGI web apps - florimondmanca/arel
GitHub · github.com [1]
arel is a “Lightweight browser hot reload for Python ASGI web apps”
I just implemented this on my thoughts website using fastapi [2], and it’s incredibly fast and lightweight. There just two lines of js that make a web socket connection back to the backend that watches for changes.
When in development mode, this snippet gets injected directly on the page and does a refresh when arel detects a change.
const ws = new WebSocket("ws://localhost:5000/hot-reload");
ws.onmessage = () => window.location.reload();
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://github.com/florimondmanca/arel
[2]: /fastapi/
[3]: /thoughts/
main.py [1]
python
import os
import arel
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
app = FastAPI()
templates = Jinja2Templates("templates")
if _debug := os.getenv("DEBUG"):
hot_reload = arel.HotReload(paths=[arel.Path(".")])
app.add_websocket_route("/hot-reload", route=hot_reload, name="hot-reload")
app.add_event_handler("startup", hot_reload.startup)
app.add_event_handler("shutdown", hot_reload.shutdown)
templates.env.globals["DEBUG"] = _debug
templates.env.globals["hot_reload"] = hot_reload
@app.get("/")
def index(request: Request):
return templates.TemplateResponse("index.html", context={"request": request})
# run:
# DEBUG=true uvicorn main:app --reload
I just discovered arel [2] for hot reloading python applications when content changes from this snippet that implements it for fatapi.
On app startup add the /hot-reload routes if in DEBUG mode.
import os
import arel
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
app = FastAPI()
templates = Jinja2Templates("templates")
if _debug := os.getenv("DEBUG"):
hot_reload = arel.HotReload(paths=[arel.Path(".")])
app.add_websocket_route("...
Open source, not open contribution with Ben Johnson (Changelog Interviews #433)
This week we're talking with Ben Johnson. Ben is known for his work on BoltDB, his work in open source, and as a freelance Go developer. Late January when Ben open sourced his newest project Litest...
Changelog · changelog.com [1]
Ben Johnson was on the Changelog a few years back covering his work on litestream, and talks about why he chose to go open source, but not open contribution.
You should have a good reason to move off of sqlite.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://changelog.com/podcast/433
[2]: /thoughts/
I wanted to host some static files through fastapi [1]. Typical use cases for this
might be some static web content like html [2]/css/js. It could also be images or
some data that doesn’t need dynamically rendered.
From the Docs # [3]
The docs cover how to host static files, and give this solution that is built
into fastapi.
https://fastapi.tiangolo.com/tutorial/static-files/
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
Authenticated Static Files # [4]
Thanks to #858 [5].
OscartGiles [6] posted this solution to add
authentication to static files. I tried this out on my
thoughts [7] and it worked flawlessly.
import typing
from pathlib import Path
import secrets
from fastapi import FastAPI, Request, HTTPException, status
from fastapi.staticfiles import StaticFiles
from fastapi.security import HTTPBasic, HTTPBasicCredentials
PathLike = typing.Union[str, "os.PathLike[str]"]
app = FastAPI()
security = HTTPBasic()
async def verify_username(request: Request) -> HTTPBasicCredentials:
credentials = await security(request)
correct_username = secrets.compare_diges...
-
Very inspiring talk, TLDR, you probably don’t need a database server. sqlite will probably be faster, simpler to maintain, and simpler to test your application.
Note
This post is a thought [1]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: /thoughts/
I recently se tup minio object storage in my homelab [1] for litestream sqlite
backups. The litestream quickstart made it easy to get everything up and
running on localhost, but I hit a wall when dns was involved to pull it from a
different machine.
Here is what I got to work # [2]
First I had to configure the Key ID and Secret Access Key generated in the
minio ui.
❯ aws configure
AWS Access Key ID [****************VZnD]:
AWS Secret Access Key [****************xAm8]:
Default region name [us-east-1]:
Default output format [None]:
Then set the the s3 signature_version to s3v4.
aws configure set default.s3.signature_version s3v4
Now when I have minio running on https://my-minio-endpoint.com I can use the
aws cli to access the bucket.
Note that https://my-minio-endpoint.com resolves to the bucket endpoint
(default 9000) not the ui (default 9001).
aws --endpoint-url https://my-minio-endpoint.com s3 ls my_bucket
Now Configuring Litestream # [3]
Litestream also accepts the endpoint argument via config. I could not get it
to work just with the ui.
Note the aws configure step above is not required for litestream, only the
aws cli.
dbs:
- path: /path/to/database.db
replicas:
-...
GitHub - benbjohnson/litestream: Streaming replication for SQLite.
Streaming replication for SQLite. Contribute to benbjohnson/litestream development by creating an account on GitHub.
GitHub · github.com [1]
`litestream` is a sick cli tool for steaming replicas of sqlite. It automatically does daily snapshots, and streams all of the writes to the replica live.
install # [2]
Install is fast using installer, no compilation, just copy the binary and run.
curl https://i.wayl.one/benbjohnson/litestream
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://github.com/benbjohnson/litestream
[2]: #install
[3]: /thoughts/
why-is-postgres-default
Serious question.
No one ever got fired for choosing PostgreSQL # [1]
But, why. It’s the most loved db, right? Right? Maybe it’s time to rethink
it.
Don’t get me wrong, if I need a relational db as a service, PostgreSQL is going
to be my first choice, but why do I need to run a separate application for it?
Tutorials use sqlite # [2]
Why is that? Because there is nothing else to stand up. Nothing else to
maintain. And you probably already have it installed on just about anything
that has a battery.
SQLite runs in memory # [3]
Don’t need, or maybe don’t want to persist state. Run it in memory. This is a
nice feature for running tests.
Less exposure # [4]
SQLite is a file on your filesystem. It’s not a web service. It’s not a cloud
service. Not that postgres is insecure, but it is one more endpoint that you
have to think about securing.
this means that is probably also cheaper 🤑
SQLite is easy to replicate # [5]
Want to run your new feature with prod data? Pull a replica or...
Why I Built Litestream - Litestream
Despite an exponential increase in computing power, our applications require more machines than ever because of architectural decisions made 25 years ago. You can eliminate much of your complexity ...
litestream.io [1]
As applications scale to the edge, to put compute as close to the user as possible, database queries back to the master node get slower and slower. Enter sqlite replication, put the database wtih the application code and replicate from master.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://litestream.io/blog/why-i-built-litestream/
[2]: /thoughts/
I'm All-In on Server-Side SQLite
Ben Johnson has joined Fly.io
Fly · fly.io [1]
SQLite is the next big database trend. with more horizontal scaling, close to user read heavy applications, having your database in the same application stack makes a lot of sense. Tools like litestream are going to enable global distribution in an impressive way.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://fly.io/blog/all-in-on-sqlite-litestream/
[2]: /thoughts/
LiteFS Cloud: Distributed SQLite with Managed Backups
Documentation and guides from the team at Fly.io.
Fly · fly.io [1]
Fly.io’s solution to sqlite managed backups.I definitely want to look into this a bit, but moreso the tech under the hook litestream.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://fly.io/blog/litefs-cloud/
[2]: /thoughts/
I’ve recently given tailwindcss a second chance and am really liking it. Here
is how I set it up for my python based projects.
https://waylonwalker.com/a-case-for-tailwindcss
Installation # [1]
npm is used to install the cli that you will need to configure and compile tailwindcss.
npm install -g tailwindcss-cli
Setup # [2]
You will need to create a tailwind.config.js file, to get this you can use the cli.
npx tailwindcss init
Using tailwind with jinja templates # [3]
To set up tailwind to work with jinja templates you will need to point the
tailwind config content to your jinja templates directory.
module.exports = {
content: ["templates/**/*.html"],
};
Setting up the base styles # [4]
I like to use the @tailwind base;, to do this I set up an input.css file.
@tailwind base;
@tailwind components;
@tailwind utilities;
Compiling # [5]
Now that it’s all setup you can run the tailwindcss command. You will get an
output.css with base tailwind plus any of the classes that you used.
tailwindcss -i ./input.css -o ./output.css --watch
References:
[1]: #installation
[2]: #setup
[3]: #using-tailwind-with-jinja-templates
[4]: #setting-up-the-base-styles
[5]: #compiling
Bigger Applications - Multiple Files - FastAPI
FastAPI framework, high performance, easy to learn, fast to code, ready for production
fastapi.tiangolo.com [1]
Fastapi [2] lets you tag your APIRouter’s so that the swagger docs are grouped according to the router.
router = APIRouter(tags=['router'])
Now all routes in router will appear in the router group in the swagger docs.
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://fastapi.tiangolo.com/tutorial/bigger-applications/#another-module-with-apirouter
[2]: /fastapi/
[3]: /thoughts/
[1]
sqlite has 3 different tokenizers, porter, ascii, trigram.
These can be used with sqlite-utils.
sqlite-utils enable-fts --tokenize porter database.db post title message tags
And with the python api.
db = Database('database.db')
db["post"].enable_fts(
["title", "message", "tags"], create_triggers=True, tokenize="trigram"
)
posts = list(db["post"].search(search))
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: /static/https://www.sqlite.org/fts5.html
[2]: /thoughts/
sqlite_utils Python library - sqlite-utils
sqlite-utils.datasette.io [1]
sqlite-utils is primarily a cli tool for sqlite operations such as enabling full text search, and executing searches, but it also has a nice python api that is exposed and pretty straightforward to use.
from sqlite_utils import Database
db = Database("database.db")
db["post"].enable_fts(["title", "message", "tags])
db["post"].search("water")
This returns a generator object that you can iterate over the row objects with.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://sqlite-utils.datasette.io/en/stable/python-api.html#full-text-search
[2]: /thoughts/
GitHub - simonw/datasette-render-markdown: Datasette plugin for rendering Markdown
Datasette plugin for rendering Markdown. Contribute to simonw/datasette-render-markdown development by creating an account on GitHub.
GitHub · github.com [1]
datasette really does everything doesn’t it!
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://github.com/simonw/datasette-render-markdown
[2]: /thoughts/
GitHub - simonw/shot-scraper: A command-line utility for taking automated screenshots of websites
A command-line utility for taking automated screenshots of websites - simonw/shot-scraper
GitHub · github.com [1]
> A command-line utility for taking automated screenshots of websites
Daaaang, this is such an elegantly simple way to get web screenshots with a cli. I was literally up and running with two commands on my arch linux machine (which it warned was unsupported by playwright).
pip install shot-scraper
# Now install the browser it needs:
shot-scraper install
shot-scraper waylonwalker.com
shot-scraper https://datasette.io/
shot-scraper https://datasette.io/ -h 1280 -w 1920
shot-scraper https://datasette.io/ -h 480 -w 720
shot-scraper shot --selector '#posts' https://thoughts.waylonwalker.com/post/89
Note shot-scraper https://datasette.io/ is a full length screenshot of the entire page.
Oh and its pretty dang fast, let alone the setup time, this crushes on startup time in my attempts to use a headless browser in the past.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://github.com/si...