FastAPI [1].">Starlette has a head request that works right along side your get requests.
This morning I fiddled around with custom routes for GET and HEAD, but had
to manually set some things about the file, and was still missing e-tag in
the end. Turns out as a developer you can just [2] add a head route to
your get routes and starlette will strip the content for you, while
preserving all of those good headers that fastapi FileResponse created
automatically for you.
from fastapi import APIRouter
from fastapi.response import FileResponse
from fastapi import Request
from pathlib import Path
router = APIRouter()
@router.get("/file/{filename}")
@router.head("/file/{filename}")
async def get_file(filename: str, request: Request,):
headers = {
"Cache-Control": "no-cache, no-store, must-revalidate",
}
from pathlib import Path
filename = Path(f"data/{filename}")
if not filename.exists():
raise HTTPException(status_code=404, detail="File not found")
return FileResponse(filename, headers=headers)
Here is an example of the response with curl.
❯ curl -I -L "http://localhost:8100/api/file/e5523925-1565-454c-bab3-c70c4deabc83.webp?width=250"
HTTP/1.1 200 OK
date: Wed, 22 Oct 202...
Posts tagged: python
All posts with the tag "python"
310 posts
latest post 2026-05-06
Publishing rhythm
python extras are for shipping
Python has two ways of adding optional dependencies to your projects
pyproject.toml file dependency-groups and optional-dependencies.
dependency-groups # [1]
for development
Dependency grooups are used when working on the project, they do not ship with
the project, users cannot select to install them with the project. These are
for things like running tests, linting, or docs. You might want to run these
in ci, or keep your dev machines tight. For the most part you can probably
keep these in dev. Depending on your team, fluency, and tolerance for slower
installs extra packages. Adding too many tight groups might make it hard for
the team to remember all the groups and which one to use and end up with them
using --all-groups anyways.
optional-dependencies # [2]
for users
Optional dependencies are for shipping. These are for your users, not your
development team. This is used for dependencies that are clearly not needed
for all or main use cases. It is annoying to use projects th...
-
anthony has some of the best python highlight videos each year. This might be a good sign, but each year there seems to be less and less that I am chomping at the bit to get to. I thought the remote debugger looked every interesting, his use case for babi seemed very interesting. I wonder what textual would look like built in a 3.14 world, would it still have built its own debugger/console?
uv tool run --python=3.14 babi
Without a process flag you need sudo permissions to attach a pdb debugger similar to gdb.
ps -ef | grep babi
uv tool run --python=3.14 python -m pdb -p8605
[1]
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://dropper.waylonwalker.com/api/file/b5e1a34d-c198-440a-ab30-4498bfa6962a.png
[2]: /thoughts/
Kraft-Coordinates
Handy reference for coordinates in the kraft [1] world.
Home # [2]
Overworld:-208 71 -291
Nether:-26 9 -36
Ocean Monument # [3]
Overworld: 209 62 -752
Nether:26 1 -94
References:
[1]: /kraft/
[2]: #home
[3]: #ocean-monument
PEP 735 – Dependency Groups in pyproject.toml | peps.python.org
This PEP specifies a mechanism for storing package requirements in pyproject.toml files such that they are not included in any built distribution of the project.
Python Enhancement Proposals (PEPs) · peps.python.org [1]
PEP 735 describes dependency groups as sets of optional dependencies that are not shipped with the package but intended for development purposes.
The PEP includes an example for groups that include test, docs, typing, and a combo typing-test.
[dependency-groups]
test = ["pytest", "coverage"]
docs = ["sphinx", "sphinx-rtd-theme"]
typing = ["mypy", "types-requests"]
typing-test = [{include-group = "typing"}, {include-group = "test"}, "useful-types"]
This is implemented in uv and can be used by several of their commands.
uv sync --group test
uv run --group test
uv add --group test pytest
uv remove --group test pytest
uv export --group test
uv tree --group test
Dependency Groups are not Extras # [2]
The docs describe extras as being intended to ship with the application and dependency groups intended for development. The spec allows both to exist with the same name, but care should be taken as too...
TIL: Loading .env files with uv run
Replacing python-dotenv with uv
https://daniel.feldroy.com · daniel.feldroy.com [1]
I smell a dependency to python-dotenv dying in my workflow. I originally read the title of the post and thought, “I know how to manage .env and almost skipped it”. I’m leaning more and more on uv run these days, so this should just [2] go in my [[ just file ]] to make it easy to run.
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://daniel.feldroy.com/posts/til-2025-09-env-files-with-uv-run
[2]: /just/
[3]: /thoughts/
Shots Get An Upgrade To the Main Feed
Today I updated my jinja templates and feeds to include shots posts in the main
feed. These posts will prominently show the image in the feed with a small
post for each one.
[1]
Shots [2] are instagram style imge posts
inspired by https://justin.searls.co/shots/.
References:
[1]: https://dropper.waylonwalker.com/api/file/37dea007-e66f-42a5-bd90-6722dd1084dd.png
[2]: https://waylonwalker.com/shots/
zmk two hand hold down
I don’t know about you, but I don’t re-flash my keyboard enough to ever remember
where I put the bootloader. Sometimes its the last thing I think about in a
refactor and I end up cornering myself into a place where I cant get into that
layer anymore. I’ve started putting hardware switches on my newer builds, but
some older builds don’t have a hardware one, so it requires disassembly and
jumping the microcontroller. Even when I have one though, I gotta flip my
board over and its annoying sometimes, so I prefer to have a keystroke for it.
Two Hand hold down # [1]
What I’ve landed on recently is the idea of a two hand hold down combo for the
bootloader. These combos are ones that there is no way I can hit without
picking my hands up from their normal homerow position and pressing four keys
simultaneously with pointer and thumbs.
Here are some example layouts from keymap-editor [2]
[3]
40% layout - similar to corne
[4]
Here it is on my Son’s 3x5 macropad
[5]
Here it is on my 3x...
I’ve been leaning on
lazy-self-installing-python-scripts [1]
more and more, but I did not realize how much tooling that
uv [2]
gives you to help manage your scripts.
uv init --script up
uv add --script up typer rich
uv remove --script up rich
sed -i '1i #!/usr/bin/env -S uv run --script' up
chmod +x up
./up
The result is a script that looks like this, its executable as what looks like
regular command in your shell.
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "typer",
# ]
# ///
def main() -> None:
print("Hello from up!")
if __name__ == "__main__":
main()
References:
[1]: https://treyhunner.com/2024/12/lazy-self-installing-python-scripts-with-uv/
[2]: https://docs.astral.sh/uv/getting-started/installation/
Keycap Cut Away
I was curious how/if my custom keycap design was hitting my switches. So I set
out to find out what the fitup inside of this assembly looks like, but not
theoretically, a fully sliced view into their fit up in the flesh.
The set up # [1]
To setup for this cut, I flooded the edge of a 2x4 with hot glue, and inserted
the cap such that the step was tangent with the edge. This way I could use the
edge as a guide to cut one side off and leave the stem in tact. I took a
handsaw to it and filed it smooth.
[2]
Removal was applying some isopropyl alcohol and it popped right off.
Results # [3]
Actually the results aren’t that interesting. I found that the pictures turned
out really good, but nothing was touching and it sits in the stem exactly as I
thought it did. I had a thought, what if the cap is not allowing the switch to
reach it’s full travel, and had no way to know, but now I know.
[4]
Key Up
[5]
Key Down
References:
[1]: #the-set-up
[2]: https://dropper.waylonwalker.com/ap...
I have a couple of use cases for simple qr codes in python coming up. One is
for blog posts, the other is for auth into a new server application logged to a
terminal. I tried the qrcode [1] library
and it does not look as nice to me and I found
pyqrcode [2] to be quite nice.
import pyqrcode
url = pyqrcode.create('https://waylonwalker.com/qr-codes-in-python')
url.svg('qr-codes-in-python.svg', scale=8)
print(url.terminal(quiet_zone=1))
url.svg('qr-codes-in-python.svg', scale=12)
url.svg('qr-codes-in-python.svg', omithw=True) # width is controlled by the container
url.svg('qr-codes-in-python.svg', omithw=True, module_color='#ffd119')
url.svg('qr-codes-in-python.svg', omithw=True, module_color='#ff69b4', background='#2b034c')
result # [3]
Here is the final svg result.
Here is what it looks like in the terminal.
[4]
If you want fancier qrcodes check out https://mydigitalharbor.com/
References:
[1]: https://pypi.org/project/qrcode/
[2]: https://pypi.org/project/pyqrcode/
[3]: #result
[4]: https://dropper.waylonwalker.com/api/file/c644bd34-b5da-48a3-b6cf-c89efb546114.png
GitHub - rushter/selectolax: Python binding to Modest and Lexbor engines. Fast HTML5 parser with CSS selectors for Python.
Python binding to Modest and Lexbor engines. Fast HTML5 parser with CSS selectors for Python. - rushter/selectolax
GitHub · github.com [1]
Selectolax you have my attention! I will be giving this a try for markata which often suffers from slow beautifulsoup. It appears to have everything I need for my simple use cases.
[2]
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/rushter/selectolax
[2]: https://dropper.waylonwalker.com/api/file/b5d8930f-59e0-4947-9500-717f66ce33dc.png
[3]: /thoughts/
uv run for running tests on versions of Python
Using uv run with make to replace tox or nox for testing multiple versions of Python locally.
https://daniel.feldroy.com · daniel.feldroy.com [1]
Such a fantastic use of uv, its so fast and flexible and does everything I need that next time I go to set up some more complex testing like this I’m going to lean towards it more than i would something like tox. In the post Daniel sets up matrix testing for testing out different versions of python with the same pytest test suite.
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://daniel.feldroy.com/posts/2025-07-uv-run-for-testing-python-versions
[2]: /thoughts/
I’ve been a long user of pygments, it’s been the thing that injects <spans>
with funny little class names like sc and si into the code blocks of my
website. I’ve even gone as far as implementing a plugin for
md-it [1],
but I had no idea how to re-style it. I long ago got a theme that looked good
enough from somewhere and just used it, maybe I pulled something from their
docs site and forgot. Today I learned you can list all the themes easily from
the library itself, and render out new css.
from pygments.styles import get_all_styles
list(get_all_styles())
# [
# 'abap',
# 'algol_nu',
# 'algol',
# 'arduino',
# 'autumn',
# 'borland',
# 'bw',
# 'colorful',
# 'default',
# 'dracula',
# 'emacs',
# 'friendly_grayscale',
# 'friendly',
# 'fruity',
# 'github-dark',
# 'gruvbox-dark',
# 'gruvbox-light',
# 'igor',
# 'inkpot',
# 'lightbulb',
# 'lilypond',
# 'lovelace',
# 'manni',
# 'material',
# 'monokai',
# 'murphy',
# 'native',
# 'nord-darker',
# 'nord',
# 'one-dark',
# 'paraiso-dark',
# 'paraiso-light',
# 'pastie',
# 'perldoc',
# 'rainbow_dash',
# 'rrt',
# 'sas',
# 'solarized-dark',
# 'solarized-light',
# 'staroffice',
# 'stata-dark',
# 'stata-light',
# 'stata',
# 'tango',
# 'trac',
# 'vim'...
uv cache prune
If you're running low on disk space and are a uv user, don't forget about uv cache prune: uv cache prune removes all unused cache entries. For example, the cache …
Simon Willison’s Weblog · simonwillison.net [1]
Good point to check on your uv cache if you are running low on disk space. I checked mine today, and it wasn’t too bad so I left it alone.
du -sh `uv cache dir`
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://simonwillison.net/2025/Jul/8/uv-cache-prune/#atom-everything
[2]: /thoughts/
markata parallel render
_._ __/__ __ __ _/_ Recorded: 07:53:56 Samples: 71681
/_//_/// /_\ / //_// / //_'/ // Duration: 92.741 CPU time: 91.748
/_/ v4.5.1
Program: /home/waylon/git/waylonwalker.com/.venv/bin/markata build --pdb
92.740 Markata.run markata/__init__.py:443
`- 92.714 HookCaller.__call__ pluggy/_hooks.py:479
[2 frames hidden] pluggy
92.714 PluginManager._hookexec pluggy/_manager.py:106
|- 38.207 wrapper_register markata/hookspec.py:265
| |- 26.105 render plugins/link_collector.py:59
| | |- 10.012 BeautifulSoup.__init__ bs4/__init__.py:122
| | | [14 frames hidden] bs4, html
| | |- 5.599 <listcomp> plugins/link_collector.py:181
| | |- 4.050 <listcomp> plugins/link_collector.py:173
| | |- 3.466 Markata.map markata/__init__.py:565
| | |`- 2.092 markata/__init__.py
| | `- 0.942 BeautifulSoup.find_all bs4/element.py:2008
| | [2 frames hidden] bs4
| |- 9.107 render markata/plugins/render_markdown.py:260
| |`- 8.902 result_iterator concurrent/futures/_base.py:612
| | [5 frames hidden]...
csv
name,age,city
Alice,30,New York
Bob,25,San Francisco
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
name,age,city
Alice,30,New York
Bob,25,San Francisco
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
Charlie,35,Chicago
graph TD
A-->B
A-->C
A-->D
D-->E
document.addEventListener('DOMContentLoaded', function() {
(function() {
const ctx = document.getElementById('chartjs-1');
new Chart(ctx, {
"type": "bar",
"data": {
"labels": ["Red", "Blue"],
"datasets": [{ "label": "Votes", "data": [12, 19] }]
},
"options": {
"responsive": true
}
});
})();
(function() {
const ctx = document.getElementById('chartjs-2');
new Chart(ctx, {
"type": "line",
"data": {
"labels": [
65,
59,
80,
81,
56,
55,
40
],
"datasets": [
{
"label": "My First Dataset",
"data": [
65,
59,
80,
81,
56,
55,
40
],
"fill": false,
"bord...
Notes – 09:32 Thu 19 Jun 2025
Notes – 09:32 Thu 19 Jun 2025
dbushell.com · dbushell.com [1]
David’s design on his blog is fantastic likely from years of small improvements like this converting ugly quotes to pretty quotes and optimizing fonts.
It’s common for markdown libraries to convert the first to the second like my build script does.
This is new to me, I had no idea that markdown libraries did this, I’m now interested if markdown-it does it.
For subsetting I use the fontTools library but I’ve no idea how to setup Python environments. I got it working once and failed to document the process.
David, David, David, I’m sorry python has done you this dirty. I should do a post on making python environments in the age of Posts tagged: uv [2]. You got options to run in docker/podman, a whole ass vm, uv venv, uvx, uv run, uv script, python -m venv, virtualenv, poetry, hatch, and too many more. The ones that matter are containers or uv.
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://dbushell.com/notes/2025-06-19T09:32Z/
[2]: /tags/uv/
[3]: /thoughts/
Copier has a few quirks with vcs that I just discovered by trying to test out
some changes. I may have some config that I have long forgotten about
somewhere deep in my dotfiles, I don’t think so, but id love to be wrong and
corrected, please reach out.
What Doesn’t Work # [1]
I tried throwing everything at this template to make it work. I tried a bunch
of flags that did not work. I tried making commits to the local repo to get rid
of the dirty warning. I really wanted to test new changes locally without
committing and pushing untested and potentially broken changes.
uvx copier copy ../markata-blog-starter .
uvx copier copy gh:waylonwalker/markata-blog-starter@develop .
uvx copier copy ../markata-blog-starter . -wlg --trust
What Works - –vcs-ref # [2]
Finally after trying everything to get the local copy to work, and my guess of
@branch not working I found this to work. It does require me to go to the repo
on my develop branch.
uvx copier copy gh:waylonwalker/markata-blog-starter --vcs-ref develop .
What Works - delete .git # [4]
Really this might be my best option to make quick changes and test them locally
without going through a version control system. It is not ideal, ...
-
The ability to query s3 buckets so seamless looks like such a pleasure to work with if you have a use case for that. Kedro catalog takes care of this most of the time for me, but I wonder if there are some cross project searching use cases I might find for this.
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/