Wallypub: A (part-time) Year in Python
December 29th, 2025
At the end of 2024, I had a problem I wanted to solve. I found that the way I engaged with news was wanting; it felt shallow. I skimmed articles on my phone, scrolled posts on the fediverse, and sent a ton of articles to Wallabag.
Previously, I made earnest strides and set up Wallabag on my e-reader through KOReader. That sort of worked. I always had something to read, but my backlog grew faster than I was tackling my article reading. That in and of itself was not a problem. What I did find, though, is that every time I refreshed Wallabag my selection of reads would be clustered, a sort of last-in-first out pull.
I endeavored to do something else. What if snapshots of my backlog could become an artifact, like a newspaper? I poked around my Wallabag account and found an API, and the gears started turning. I got started in earnest; January 7th was my first commit. I worked a few hours a week at this problem,and by February 7th, I had my first digest created with what would become Wallypub, a small CLI companion client to generate epub files from my Wallabag backlog.
With a mass of content, there is always the discovery problem. I kept the last-in-first-out approach to reading, but I noticed a few things. Anything with less than a one-minute read time, usually meant Wallabag failed to capture the text of the article. I set up a filter that allowed a user to configure the minimum and maximum read time that would get pulled into the digest. The articles that were filtered out would simply be archived.
Sometimes this filtering would lead to only having three or four articles in the digest. I ended up configuring it so that the number of articles requested on the first pull (under the settings, this is ArticleParameters -> perPage) would be the number of articles that needed to be present in the digest. When there are missing articles, Wallypub pulls the oldest articles from the backlog to fill out the remaining slots. With this pattern, I was able to get a more balanced mix of news in my digests, because usually for every 10 URLs, I save at least one that is paywalled or otherwise inaccessible to Wallabag.
My early digests had custom-made covers that I made with the Gnu Image Manipulation Program. Looking back, I quite like these, but I did not want to spend 15 minutes creating a cover every time I wanted to read some news. What I ended up with is writing a small utility that relies on PIL to create an image with the name of the digest, the date, and a background color. The colors are randomly generated. There is a simple function to ensure the colors contrast and should generally be readable on a screen. The generated cover makes the artifact feel more disposable than I would like, but form follows function, as they say. The function here is to build digests that I would intentionally read.
The project grew in ambition and started spiraling into a bigger project, despite me using the terminal application regularly. I started building out a desktop application that supported more information sources. The project was becoming quite the undertaking, but I still used my base CLI application regularly. In December of this year, I decided I would pause development of that larger initiative so that I could sand off the edges and open source the tool that I was already using.
During the past two weeks, I've polished Wallypub and done some ancillary tasks to get it ready. The best way to learn about Wallypub is to visit the website to install it and read the user-guide
Over the past year this project got a smattering of my attention, and it encompasses just shy of 200 hours of work. Were I doing this as a full-time job, I probably could have gotten it live in about a month, maybe less, because, with a day job, most of the tasks are top of mind. Releasing this into the wild is a weight off my mind and I would like to do a retrospective on elements of the work that were new to me.
Retrospective
Python
My only dives into Python were little scripts I would come across and a small web scraping project I did. I wanted to try creating a full-fledged app with it. It helped that there was already a library to convert HTML to EPUBs, so that locked me in.
Will I use Python again? Publishing Wallypub allows me the mental space to start my other project from scratch, and I think I will use something else. Python is nice; it allowed me to quickly get something working, but I found myself fighting the language and build process. It seemed that every time there was something I enjoyed and made my life easier that was in the Python ecosystem, it was actually written in Rust. In this case, PyApp and UV. UV gave me sanity for managing packages, and PyApp allowed me to get a binary made with relatively no pain. Both of these things are something that I think the language should handle well within the language's standard library.
Being able to move fast and not think about types was nice for the first week, but after that, if I didn't do it, it made testing and refactoring a larger mental load. I am glad for the time I spent with Python and will reach for it more quickly when it is the appropriate tool for me, but I missed so much from my statically typed, compiled languages that I think I'll be sticking with those for the bulk of my programming.
Generating Images
I mentioned the rudimentary image generation for the cover pages. I enjoyed this foray into what can generously be called 2D graphics programming and having access to PIL and a wealth of online tutorials made short work of that task. If you take a look at the package, it is dead simple but it was enough of a taste that I would be interested in gaining a better understanding of programmatic 2D graphics.
User Spaces
The challenge of going from just running the main.py file to writing an actual user script let me learn more about getting programs to work on other people's machines. I was deeply thankful that the platformdirs package exists; it made something I was dreading dead simple. A greater challenge would have been understanding how to ensure that this CLI tool works on Mac and Windows machines as well, but I do not have any current-generation versions of those machines to work on. Couple that with the direction Microsoft is taking Windows and the gate you have to clear to develop for Apple, and neither seemed like an interesting prospect. I'm getting too long in the tooth to spend time learning systems that will only lock me in.
Keyring
I had a goal of not making this terminal app super reliant on programmer conventions, so I resolved that there would be no .env files for secrets. I got to dive into how keyrings work and was able to securely store the password there. Again, the heavy lifting was done by an existing library, but I spent a good hour using the command line tools and reading the man pages to get an understanding.
Publishing
PyPi
Using UV, this was incredibly straightforward. I feel like I set a single environment variable and ran uv publish after having built it. I did have one hiccup where I wanted to reuse a package version because I messed something up, and PyPi does not allow reuse of version numbers. This is a sensible guardrail that I should have seen coming. I had to push a patch version as the main release, which is a bummer. I should have kept the practice I do at my day job, which is to rely on beta or rc tags before trying to send up the actual version. There's always next time!
Arch User Repository (AUR)
I only started with EndeavorOS a few months back, and I've fallen in love with Arch. The Arch Wiki is excellent; between the core packages and the user repository, I have what I need, and everything feels snappy. From the moment I started with EndeavorOS, I knew I wanted Wallypub to end up in the AUR.
Testing your package on your system and getting it uploaded is a breeze. I did rely on a few other sources besides the wiki because I didn't understand that you could do a git clone command with a brand new repo, so it took me a second to figure out how I would actually create a repo within the AUR, but once that was done, I was off to the races.
Looking Forward
The above sections are the standout moments, and I am surely skipping paths partially treaded. I hope the fruits of my extremely part-time year of Python are useful to more than just me.
There is still some lightning in the bottle for this project. My top concerns center on improving the cover generation and the parsing of HTML files, as well as refactoring a lot of code to make it cleaner. Additionally, I created an opportunities section of the docs so that would-be contributors would have an idea of the kind of contributions I would eagerly collaborate on.
Over the next year, I hope to polish the other projects I worked on in 2025 for release and kick around a few ideas. Most of all, though, I hope to spend much-needed time with my non-programming projects.