The config

This story is about an accomplishment at work. Due to it being work-specific I won't go into too much detail, so it won't be necessarily useful. It's just a personal piece. For various reasons (such as changing places, raising a child, workplace politics, poor luck) I haven't got any clear wins under my belt for quite some time, probably since building a Python team at Yandex 15 years ago. So this one feels a little special.

Trie in Python

A post about Haskell vs. Python readability came onto my radar the other day. It compares two implementations of a trie structure, and after looking upon the Python version I wanted to make my own attempt. I didn't make it to necessarily compare or "battle" against the other solutions, it's more of an exercise in the vein of "how would I do it".


When last time I lamented the unoriginality of my tool nfp I also entertained the idea of salvaging some value from it by extracting the event debouncing part into a stand-alone tool. So that's what I did.

Meet debounce, a Rust library and a prototype command-line tool.


So what happened was, I fed up manually uploading pictures I export from Darktable to my Flickr photo stream using the browser's file picker. So I decided to do something about it. The initial idea was to craft a FUSE file system which would automatically upload new files, but this turned out to be hard, so I switched to a much simpler solution: a little inotify watcher handing over new files to an upload script. I managed to code up a working solution over a weekend!

More interestingly, I made the watcher part — "nfp", for "New File Processor" — as a generic configurable tool which I published. It was only when I started writing this very blog post that I stumbled upon a standard Linux tool that does it, inotifywait :-)

Still, I hope there's something to be salvaged from this project. Read on!

New pet project

So anyway, I'm making a shopping list app for Android. As I understand, "shopping list" is something of a hello-world exercise of Android development, which may explain why there are so many rudimentary ones in Google Play. Only in my case I actually need one, and I know exactly what I want from it.

See, for the past 10 years or so I've been in charge of food supply in our family, which includes everything from grocery shopping logistics, to cooking, to arranging dishes in the dishwasher. And the app is an essential part of the first stage of that chain.

Status update: 2020

Pretty sure I'm in the minority on this one, but this year was actually a good one for me! One of the best in a while, to be honest…

Server upgrade 2020

Regular readers of this blog have probably noticed that it is now served from a different IP address… Okay, okay, I'm kidding! This blog doesn't have any regular readers, of course.

Anyway, what I'm trying to say is that I recently spent quite some effort to move all my stuff —,, their supporting databases and, most importantly, my personal email — to a new and shiny Linode instance under control of an up-to-date Ubuntu.

Here's the (heavily compressed) war story.

On Kotlin

I've been writing code in Kotlin on and off over a few months, and I think I'm now at this unique stage of learning something new when I already have a sense of what's what, but not yet so far advanced so I don't remember beginner's pain points.

Here's a dump of some of my impressions, good and bad.

Dicts are now ordered, get used to it

There were several moments over the last few weeks when I heard people discuss differences between Python lists and dicts and one of the first ones mentioned was that lists are ordered and dicts are not.

Well, not anymore. Quoting the docs referenced above:

Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was an implementation detail of CPython from 3.6.

So if you want to discuss fundamental differences you can pretty much only point out that dict values are accessible by keys, which could be of any immutable type, while list values are indexed with integers. That's it :-)

Python stdlib gems: collections.Counter

Here's a toy problem. Given a corpus of phone numbers for different countries determine a most prevalent display format in each country and use it to re-format an arbitrary phone number for its country. For example, if most US numbers in our data corpus are written like xxx-xxx-xxxx then the string (206) 1234567 should be converted to 206-123-4567.

For simplicity, let's assume that all numbers are local so we don't have to deal with the complexity of international prefixes.