Computers and code
I’ve been a professional software developer since 2014, and a hobbyist for several years before that. This blog started as a way for me to share code snippets, and writing about my code has become a key part of how I learn and think about computers.
These entries cover the range of development work: from writing code to running it in production.
Sub-topics:
- AppleScript
- AWS
- Blogging about blogging
- Builds and CI
- Caddy
- Code crimes
- CSS
- Datetime shenanigans
- DNS
- Docker
- Error messages
- Flickr
- Git
- Go
- HTML
- HTTP
- Images and videos
- JavaScript
- jq
- LaTeK
- macOS
- Photo management
- Python
- Regular expressions
- Ruby
- Rust
- Scala
- Shell scripting
- Software testing
- Spreadsheets
- SQLite
- Swift
- Tailscale
- Terraform
- Text and Unicode
- Tumblr
- Wikimedia Commons
- YouTube

The Good, the Bad, and the Gutters
A step-by-step guide to a movie poster grid that uses CSS Grid, text-wrap balanced titles, and dynamic hover states.

Using vcrpy to test HTTP interactions in Python
How I record HTTP requests to get fast, reliable, and consistent tests, and the patterns I use in a production codebase.

Recreating the bird animation from Swift.org
The Swift.org website got a redesign, including an animation of a swooping bird, and I read the source code to understand how it works.

How I create static websites for tiny archives
Start with a simple HTML file, then add features like templates, sorting, and filtering as they become useful.

Not all blog posts are created equal
Splitting my site into “articles” and “today I learned” helped me overcome writer’s block and improve my writing.

How I name my computers
What do flaming birds, man-eating giants, and obscure deities have in common?

create_thumbnail: create smaller versions of images
I’ve made a new tool that allows me to reuse my thumbnailing code across all my projects.

emptydir: look for (nearly) empty directories and delete them
I’ve been writing tools in Rust again.

Making a PDF that’s larger than Germany
We’re gonna need a bigger printer.

Writing a Mac app to review my photos
Dipping my toes into SwiftUI to make a tool for reviewing my photos with just the keyboard.

Upward assignment in Ruby
A deep dive into the internals of Ruby and metaprogramming techniques, in a quest for a cursed operator.

Launching a rocket in the worst possible way
Taking the humble <marquee> tag where no HTML tag has gone before.

Finding a tricky bug in Elasticsearch 8.4.2
Gradually deleting more and more data helped me get a reliable repro for an elusive bug.

“Fixing” the rules of division
If we want to redefine how division works, Ruby is happy to oblige.

dominant_colours, a CLI tool for finding dominant colours in an image
A new tool for playing with images.

Illustrating lifecycle transitions in Amazon S3
A picture speaks a thousand words, which is why I always have pen and paper to hand.

Using DynamoDB as a calculator
Taking advantage of Amazon’s least-loved compute platform.

Adventures in Python with concurrent.futures
How I use concurrent.futures to speed up my batch scripting in Python.

Getting a tint colour from an image with Python and k‑means
I want to display text next to an image that looks visually similar to the image, so I need to extract a tint colour.

Four ways to underline text inLaTeK
I’m very picky about the way underlines look, and have spent a lot of time trying to get the perfect underline inLaTeK .
258 articles
Dreaming of a ten-year computer
Modern computers are more powerful than I know what to do with, but the norm is still to upgrade every few years. I want my current computer to last a decade, and I don’t think that’s unreasonable.
Gumdrop, a silly app for messing with my webcam
When it’s dark, a large computer monitor is a fun way to make the room change into different colours.
The bare minimum for syncing Git repos
I don’t need GitHub or a cloud service to keep my Git repos in sync – files and folders work just fine.
Creating Caddyfiles with Cog
Cog is a tool for doing in-place text generation for static files. It’s useful for generating repetitive config, like my web server redirects.
Swapping gems for tiles
I’ve replaced Jekyll with Mosaic, a Python-based static site generator that I wrote just for me.
Parody posters for made-up movies
I rented movies from Blockbuster, HBO Max-Width and Netflex.
The passwords I actually memorise
Password managers promise you only need to remember one password, but I keep eight of them in my head to avoid a single point of failure.
Where I store my multi-factor recovery codes
Most services give you MFA recovery codes but don’t tell you where to store them. I use an encrypted disk image and a simple HTML file.
Quick-and-dirty print debugging in Go
I wrote a Go module to help with my print debugging, which logs expressions and values to a separate file.
Adding a README to S3 buckets with Terraform
If you create an S3 bucket in Terraform, you can also create a README to help a future sysadmin understand what the bucket is for.
When square pixels aren’t square
When you want to get the dimensions of a video file, you probably want the display aspect ratio. Using the dimensions of a stored frame may result in a stretched or squashed video.
Cleaning up messy dates in JSON
I wrote a Python script to help me get timestamps in a consistent format in my JSON.
Detecting AV1-encoded videos with Python
I wrote a Python test to find videos that are encoded with AV1, so I can convert them to a codec my iPhone can play.
Why can’t my iPhone play that video?
The answer involves the AV1 video codec, Apple’s chips, and several new web APIs I learnt along the way.
Doing my own syntax highlighting (finally)
I’ve redesigned my syntax highlighting scheme to use a smaller colour palette. Here’s what I’ve changed, how it works, and why I think it’s better.
Creating a personal wrapper around yt-dlp
I’ve written a new script which calls yt-dlp with my preferred options, so I don’t have to copy my configuration across different projects.
Opening all the files that have been modified in a Git branch
You can use Git to find where a branch diverged from
main, what files have changed, then open those files in your editor.Linking to text fragments with a bookmarklet
I’ve written a bookmarklet that helps me link to specific text on a web page.
Resizing images in Rust, now with EXIF orientation support
A new version of Rust’s image crate has support for EXIF orientation, which allows me to resize images without mangling their rotation.
Create space-saving clones on macOS with Python
You can shell out to
cp -cusingsubprocess, or you can make aclonefile()syscall using thectypeslibrary.Minifying HTML on my Jekyll website
I compare three different approaches to minifying HTML.
Moving my Glitch apps to my own web server
I’ve moved almost all of my Glitch apps to websites running on my own web server, on this domain.
Handling JSON objects with duplicate names in Python
It’s possible, although uncommon, for a JSON object to contain the same name multiple times. Here are some ways to handle that in Python.
A faster way to copy SQLite databases between computers
Dumping a SQLite database to a text file can make it much smaller, which means you can download it faster.
A flash of light in the darkness
If you’re using an image as your background, remember to set a fallback colour as well, especially if you’re in dark mode.
Beyond
None: actionable error messages forkeyring.get_password()I have a wrapper for
get_password()so that if it can’t find a password, you get an error that explains how to set the password, and what password you should choose.Localising the
<time>with JavaScriptI’m using the
<time>element and some JavaScript to display timestamps as human-readable, localised timestamps. Something likeTue, 15 Apr 2025 at 20:45 BSTis easier to read than2025-04-15T19:45:00Z.Whose code am I running in GitHub Actions?
I wanted to know what third-party code I was using in my GitHub Actions. I was able to use standard text processing tools and shell pipelines to get a quick tally.
Fast and random sampling in SQLite
I tested four approaches, from
ORDER BY RANDOM()to picking randomrowidvalues in Python, and found one that’s both fast and diverse.An unexpected lesson in CSS stacking contexts
While trying to add some simple overlay labels, I stumbled into a sharp edge of a complex CSS feature called “stacking contexts”.
Creating static map images with OpenStreetMap, Web Mercator, and Pillow
I made some simple map visualisations by downloading tiles from OpenStreetMap, then annotating the tiles with Pillow.
Cosmetic updates to this site
I’ve simplified the palette, changed the font, and given several elements a more consistent visual appearance.
Good embedded toots
I replaced Mastodon’s native post embeds with lightweight HTML and CSS snippets that are faster to load, more resilient to outages, and support dark mode – and I had fun doing it.
Making inventory spreadsheets for my LEGO sets
Using the Rebrickable database downloads and sqlite-utils, I can quickly create spreadsheets that let me tick off the parts in each set.
Adding auto-generated cover images to EPUBs downloaded from AO3
I built a handy tool to generate cover images for stories downloaded from AO3, making them easier to browse. Along the way, I learnt about how EPUBs work, the power of static sites, and some gotchas of async JavaScript.
Looking at images in a spreadsheet
The
IMAGEandHYPERLINKfunctions allow me to use a spreadsheet as a lightweight, collaborative space for dealing with images.randline: get a random selection of lines in a file using reservoir sampling
I wrote a tiny Rust tool to get random samples in a memory-efficient way, and I learnt a lot while doing it.
How I test Rust command-line apps with
assert_cmdSome practical examples of how this handy crate lets me write clear, readable tests.
How I use the notes field in my password manager
I use notes as a mini-changelog to track the context and history of my online accounts. I write down why I created accounts, made changes, or chose particular settings.
Moving my website from Netlify to Caddy
To avoid getting stung by Netlify’s bandwidth charges, I moved this site to a Linux server running Caddy as my web server.
A script to verify my Netlify redirects
I wrote a script that reads my redirect rules, and checks that every redirect takes you to a page that actually exists on my site.
Making alt text more visible
I wrote a JavaScript snippet that shows alt text below all of my images, so I can see when it’s missing, and review it while I’m editing.
Two examples of hover styles on images
When I hover over an image, I can add a border to a link, or change the colours of an SVG icon.
Drawing a better bandwidth graph for Netlify
A two-part pie chart lets me see how much bandwidth I’ve used this month, and whether I’m on track to exceed my bandwidth allowance.
Going between Finder and the Terminal
A few shell scripts I use to go between the Finder and the Terminal.
Improving millions of files on Wikimedia Commons with Flickypedia Backfillr Bot
The new bot improves metadata for Flickr photos on Wikimedia Commons, and makes it easier to find out which photos have been copied across.
Documenting my DNS records
Exporting my DNS records as YAML gives me a plaintext file where I can track changes, add comments, and feel more confident about managing my DNS.
Creating a Safari webarchive from the command line
We can use the
createWebArchiveDatamethod onWKWebViewto write a Swift script that creates Safari webarchive files.What comes after AWS?
Whatever displaces public cloud as the default model for large-scale computing has to be more than “AWS, but 3% better”.
Getting faster Jekyll builds with caching in plugins
I was able to build my Jekyll site much faster by using the built-in caching API.
flapi.sh: a tiny command-line tool for exploring the Flickr API
Combining several existing tools to make something that allows for quick experiments and exploration.
Step… Step… Step…
Swing dancing and prompt engineering are pretty different. But could learning one help us learn the other?
Moving my YouTube Likes from one account to another
Some experimenting with the YouTube API to merge two accounts into one.
Getting the path to the note I have open in Obsidian
Although Obsidian doesn’t support AppleScript, I can use System Events to find out which note I have open.
Setting up Fish to make virtualenv easier
I wrote some shell config to smooth out the experience of using virtual environments in Python.
Making the fish shell more forgetful
A few commands that help me keep unwanted entries out of my shell’s autocomplete.
Finding the biggest items in my Photos Library
A quick script to help move the biggest items out of my main Photos Library.
Spotting spam in our CloudFront logs
Looking for search queries that came from robots, not real people.
Adding locations to my photos from my Apple Watch workouts
My Apple Watch knows where I am, which is handy when I have a camera that doesn’t.
How I set up my Obsidian vaults
The tags, folders, and themes I use to manage information in my Obsidian vaults.
Finding a mystery IAM access key
Using the GetAccessKeyInfo and GetAccessKeyLastUsed APIs can help us trace an IAM key back to its source.
Tag your infrastructure-as-code resources with a link to their definitions
Applying a default tag that points to the IaC definition makes it easy to go from the console to the code.
Parsing CloudFront logs with Python
A couple of functions I use to get access to CloudFront logs as easy-to-use iterators.
My Python snippet for walking a file tree
A function to find all the files in a directory is one of my most-used snippets.
My custom <picture> plugin for Jekyll
How I make images that load quickly and look good for readers, and which are easy for me to manage.
Turning off ECS tasks overnight using an EventBridge Schedule
Calling the UpdateService API on a fixed schedule allows us to turn services off in the evening, and back on again the next morning.
Preserving Dates during JSON serialisation with vanilla JS
How to make sure you get a
Dateback when you callJSON.parseandJSON.stringify.Have a single definition of “now”
Having one function that you always use to get the current time is super handy when debugging issues that only occur at specific times.
Starting Docker just before I need it
I don’t keep Docker running all the time, but intercepting the
dockercommand means it’s always running when I need it.Snippets to manage albums in Photos.app
AppleScript only allows us to add photos to an album; dipping into Swift and PhotoKit lets us both add and remove photos.
s3tree: viewing a tree of objects in S3 in my terminal
A script to give me a quick overview of some objects in a hierarchical view.
Getting alerts about flaky ECS tasks in Slack
When ECS is “unable to consistently start tasks successfully”, we get a Slack alert that tells us to investigate.
Using templates in Terraform to document a deployment
Terraform can fill in placeholders with exact values from your deployment, for easy copy/paste instructions.
Publishing lots and lots of messages to SNS
Careful use of the
PublishBatchAPI makes it quick and easy for me to send thousands of messages into SNS.Filtering AWS CLI output by tags using jq
Using
from_entriesis a nicer way to deal with the list of Name/Value pairs returned by the AWS CLI.Filtering out bogus requests from Netlify Analytics
Using redirects to filter out bots trying to hack my non-existent PHP installation.
Creating a Python dictionary with multiple, equivalent keys
Using collections.UserDict, we can create a dictionary where dict[key1] and dict[key2] always point to the same value.
Splitting a class into balanced groups
How do you make sure everyone gets to work with everyone else?
Testing JavaScript without a (third-party) framework
The browser can be a pretty good place to run your JavaScript tests.
CSS formatting in the console
Did you know you can use
%cto format yourconsole.logmessages?A Python function to iterate through an S3 Bucket Inventory
Getting something that looks more like the output of the ListObjectsV2 API.
A bookmarklet to show which responsive image was chosen
Debugging my <picture> and <source> tags.
Beware of transparent backgrounds when using AVIF with ImageMagick 6
You probably want to use version 7.
A script to get Live Text from images
Using Apple’s built-in tools to get OCR text from an image, but without going through a GUI.
Getting an Important Internet Checkmark to follow your cursor
Party like it’s 1996! A trailing checkmark cursor will make your Brand Website feel fun and authentic.
How we do bulk analysis of our Prismic content
By downloading all our Prismic documents, we can run validation rules, fix broken links, and find interesting examples.
Redacting sensitive query parameters with koa and koa-logger
Using a custom transporter to modify the log message and remove secret information.
Changing the macOS accent colour without System Preferences
Updating the accent colour everywhere, with immediate effect, using a script written in Swift.
Ten years of blogging
A decade ago, I registered a domain and started writing.
A simple gallery plugin for Obsidian
Making it easier to find all the images in my Obsidian vault.
My (tiny) contribution to Rust 1.64
A suggestion for a better error message to help people who work in multiple languages.
Finding redundant data in our Next.js props
A script that helps us optimise our
__NEXT_DATA__, which in turn helps reduce page size.I always want StrictUndefined in Jinja
When I’m writing templates with Jinja, strict behaviour is what I want, even if it’s not the default.
How to customise the title of Buildkite builds triggered from GitHub deployments
Getting a more descriptive build label than ‘Deployment’.
Cut the cutesy errors
If your app has just ruined my day, I need help, not humour.
A surprise smattering of stardom
My last post was surprisingly popular; a few reflections on the experience.
Creating an Alfred Workflow to open GitHub repos
Automations for my automations.
Experimenting with jq as a tool for filtering JSON
I wanted to learn jq’s more powerful features, so I tried to filter some JSON from the AWS Secrets Manager CLI.
Running a Rust binary in Glitch
Using different targets to build Rust binaries that will run in Glitch.
Illustrating the cipher wheels of a Lorenz machine
Some old code I wrote to draw cam-accurate illustrations of cipher wheels.
Creating a “simple” three-up image layout in CSS
A step-by-step breakdown of how I made a one-left, two-right layout for my images.
Checking lots of URLs with curl
A bash script to check the HTTP status code of a bunch of URLs, for simple and portable uptime checking.
Beware delays in SQS metric delivery
A mysterious problem with SQS-based autoscaling and an over-eager CloudWatch Alarm.
A tale of two Twitter cards
Some recent changes I’ve made to fix or improve my Twitter cards.
Closing lots of Safari tabs with JXA
To help me keep my tab count down, I wrote a JXA script to close tabs that can easily be recreated.
Why is Amazon Route 53 named that way?
Digging into the history of Route 53, DNS, and port number assignments.
Creating animated GIFs from fruit and veg
Some Python code for turning MRI scans of fruit and veg into animated GIFs.
Creating coloured bookshelf graphics in Rust
Explaining some code that draws coloured rectangles in a way that looks a bit like an upside-down bookshelf.
Why is os.sep insufficient for path operations?
Digging into a throwaway comment in the Python documentation.
The ever-improving error messages of Rust
An improvement to Rust’s error handling that I almost reported, until I realised it was fixed.
A tale of two path separators
macOS allows both the slash and colon as path separators, and this caused me no small amount of confusion.
Programatically finding the original filename of a photo in the macOS Photos Library
If you’re looking at a UUID’d file in the PhotosLibrary package, how do you find its original filename?
Prevent accidentally copying the prompt character in console code snippets
When I include console commands in a blog post, I don’t want somebody to accidentally copy the command prompt. CSS lets me avoid that.
Beware of incomplete PDF redactions
If you’re not careful when redacting PDFs, it’s possible to share more information than you intended.
An editing toolbar for alexwlchan.net
A bookmarklet that gives me a just-for-me toolbar to make changes to this site.
Getting a monthly cloud costs report in Slack
Sending the AWS bill to Slack, so everyone can be more informed and intentional about spending.
Operations on strings don’t always commute
Is uppercasing then reversing a string the same as reversing and then uppercasing? Of course not.
When is my EventBridge cron expression going to run next?
The AWS console will tell you when your EventBridge rule is going to run… if you know where to look.
Picking perfect planks with Python
How do you pick the right combination of planks to lay a wooden floor? Python and itertools to the rescue!
How to ignore lots of folders in Spotlight
A script that allows me to ignore folders like “target” and “node_modules”, so they don’t appear in search results.
Finding misconfigured or dangling CloudWatch Alarms
A Python script that finds CloudWatch Alarms which are based on a now non-existent source.
A few useful GitHub searches
I have hotkeys to search GitHub in several ways, including by user, by repo, and within the work organisation.
Listing deleted secrets in AWS Secrets Manager with boto3 and the AWS CLI
Diving into the internals of the AWS SDK to find deleted secrets.
Visualising how often I write in my journal
A Python script that shows me how often I’ve been journalling, so I can track my progress.
Downloading objects from/uploading files to S3 with progress bars in Python
Making it easier to see how long a file transfer will take, in the terminal.
Drawing coloured squares/text in my terminal with Python
Using AppleScript to detect if a Safari window uses Private Browsing
Finding the app/process that’s using Secure Input
A Python script that shows me the name of processes that have Secure Input enabled.
An AppleScript to toggle Voice Control
Making it slightly easier for me to enable and disable Voice Control quickly.
Screaming in the Cloud: Using the Cloud to Preserve the Future
I joined Corey Quinn to discuss my DynamoDB calculator and using the cloud to preserve digital collections.
What year is it? (A tale of ISO week dates)
If you use ICU date formatting, make sure you use the right format specifier for year.
Creating short-lived, temporary roles for experimenting with AWS IAM policy documents
Create short-lived, temporary roles for experimenting with AWS IAM policy documents
A script to copy images from Docker Hub to Amazon ECR
Remembering if a <details> element was opened
A JavaScript function that remembers if a details element was reopened, and keeps it open when you reload the page.
How do I use my iPhone cameras?
A script to work out which camera I use most often on my iPhone, and whether I’d miss a telephoto lens.
The danger of bad error messages
An Excel mistake shows why learning to write good error messages is a critical skill for software developers.
A new README for docstore, my tool for organising scanned paperwork
Although I don’t expect anyone to use it directly, there might be some interesting ideas that could apply elsewhere.
Using qlmanage to create thumbnails on macOS
How you can invoke Quick Look on the command-line to generate high-quality thumbnails.
Two Python functions for getting CloudTrail events
S3 prefixes are not directories
Although an S3 prefix looks a lot like a directory path, they aren’t the same. Whether or not you include a trailing slash can change the behaviour.
S3 keys are not file paths
Although an S3 key looks a lot like a file path, they aren’t always the same, and the distinction can trip you up.
Using fuzzy string matching to find duplicate tags
Getting a Markdown link to a window in Safari
Why do programming languages have a main() function?
Lots of programming languages have a function called main() where code starts executing. Where does this come from?
Running concurrent Try functions in Scala
If you have a function that returns Try[_], how do you call it more than once at the same time?
What does \d match in a regex?
It’s more complicated than I thought.
Changing the accent colour of ICNS icons
Playing with macOS ICNS image files to create colourful new icons.
Using AppleScript to open a URL in Private Browsing in Safari
Finding the months between two dates in Python
Getting every item from a DynamoDB table with Python
A Python function that generates every item in a DynamoDB table.
Showing human-friendly dates in JavaScript
What’s a nicer way to show a date than an ISO 8601 timestamp?
Moving messages between SQS queues
You can send messages to a DLQ if they fail processing. What if you fix the bug, and you want to resend the failed messages?
Taking tuple unpacking to terrible places
I want to assign a bunch of variables to True, but I don’t know how many there are. Reflection to the rescue!
Exploring an unknown SQL server
You’re handed a SQL server which has some data, but you don’t know anything about the schema. What do you do?
Comparing JSON strings when testing in Scala
There are lots of ways to format JSON. How do you know if two JSON strings have the same data, just differently formatted?
A snippet for downloading files with Python
Storing language vocabulary as a graph
Experimenting with a way to store words and phrases that highlights the connections between them.
A Jekyll filter for adding non-breaking spaces
A way to avoid awkward line breaks in the middle of phrases.
Adjusting the dominant colour of an image
Adjusting the hue to get different colour variants of the same image.
A deletion canary: testing your S3 bucket permissions
If you’ve tried to disable deletions in your S3 buckets, how do you know they’re working?
Finding the CPU and memory bottlenecks in an ECS cluster
This YAML file will self-destruct in five seconds!
YAML allows you to execute arbitrary code in a parser, even if you really really shouldn’t.
Some useful spreadsheet functions: FORMULATEXT, MATCH, CONCATENATE and INDIRECT
November 2019 scripts: downloading podcasts, retrying flaky errors, Azure and AWS
How I scan and organise my paperwork
My procedure for scanning paper, and organising the scanned PDFs with keyword tagging.
Saving a copy of a tweet by typing ;twurl
An AWS costs graph that works for me
How I get a Cost Explorer graph for the last 30 days of spending, broken down by service.
Sans I/O programming: what, why and how (PyCon UK talk)
Code that pushes I/O to the boundary is simpler, easier to reuse and easier to test.
The rough edges of filecmp
The filecmp module has a confusing API, and it just caught me out.
Experiment: GitHub code search with de-duplication
Streaming large objects from S3 with ranged GET requests
Reliably reading a large object by stitching together multiple GetObject requests into a single Java InputStream.
Iterating over the entries of a compressed archive (tar.gz) in Scala
Code to turn an InputStream into an Iterator of entries from a tar.gz file or similar compressed archive in Java/Scala.
Finding divisors of a number with Python
Using unique prime factorisations and itertools to find all the divisors of a number.
Creating preview thumbnails of PDF documents
Listing even more keys in an S3 bucket with Python
Python functions for getting a list of keys and objects in an S3 bucket.
A Jekyll filter for obfuscating email addresses
The original Markdown implementation would do randomised hex/decimal encoding to help obscure email addresses, and I do the same in Jekyll.
Converting Acorn images on the command-line
I wrote some AppleScript to help me do batch conversion of Acorn images into formats like PNG and JPEG.
A script for getting cover images from mobi ebooks
Falsehoods programmers believe about Unix time
It’s not quite the number of seconds since 1 January 1970.
Creating a locking service in a Scala type class
Breaking down some tricky code that allows us to lock over concurrent operations.
Creating a GitHub Action to auto-merge pull requests
Saving myself the trouble of clicking that pesky “merge” button.
Finding the latest screenshot in macOS Mojave
Atomic, cross-filesystem moves in Python
Explaining some code for moving files around in a way that’s atomic and works across filesystem boundaries.
Checking Jekyll sites with HTMLProofer
Working with really large objects in S3
Code for processing large objects in S3 without downloading the whole thing first, using file-like objects in Python.
Notes on reading a UTF-8 encoded CSV in Python
Some notes on trying to do this in a way that supports both Python 2 and 3, and the frustration of doing so.
Iterating in fixed-size chunks in Python
A snippet for iterating over an arbitrary iterable in chunks, and returning a smaller chunk if the boundaries don’t line up.
Getting credentials for an assumed IAM Role
A script that creates temporary credentials for an assumed IAM role, and stores them in ~/.aws/credentials.
Finding SNS topics without any subscriptions
I’m trying out Go, and I wrote a tool to help me find SNS topics that don’t have any subscriptions.
A basic error logger for Python Lambdas
A snippet to make it a bit easier to debug errors in AWS Lambda functions written in Python.
Implementing parallel scan in DynamoDB with Scanamo
Prototype code for running a parallel scan against a DynamoDB table, and using Scanamo to serialise rows as Scala case classes.
Avoiding the automatic redirect on Tumblr posts
I see an intermittent 303 Redirect when trying to navigate to a Tumblr ‘permalink’; changing the User-Agent seems to fix it.
A robot leaked my SSH keys
A cautionary tale of a daft incident where I leaked a set of SSH keys to GitHub.
My favourite iMac accessory
Adding a USB extension cable to my iMac makes a world of difference.
Drawing ASCII bar charts
A Python snippets for drawing bar charts in command-line applications.
Creating a data store from S3 and DynamoDB
A new storage layer for large records in the Catalogue pipeline.
Beware of logged errors from subprocess
If you use Python’s subprocess module, be careful you don’t leak sensitive information in your error logs.
Two shortcuts for using S3 in the shell
Two shell functions for editing and inspecting S3 objects as if they were local files.
Notes on A Plumber’s Guide to Git
Git is a fundamental part of many modern developer workflows – but how does it really work under the hood? In this workshop, we’ll learn about the internals of Git.
The Hypothesis continuous release process
How we do continuous releases of hypothesis-python, and why.
Getting helpful CloudWatch alarms in Slack
How we use AWS Lambda to send messages about our CloudWatch alarms to Slack, and some ways we add context and information to make those messages as helpful as possible.
Getting every message in an SQS queue
Code for saving every message from an SQS queue, and then saving the messages to a file, or resending them to another queue.
Listing keys in an S3 bucket with Python, redux
Python functions for getting a list of keys and objects in an S3 bucket.
IP and DNS addresses for documentation
If you’re writing technical docs and need placeholder IP addresses or DNS hostnames, there are some special values just for you!
Your repo should be easy to build, and how
Making your repo easy to clone and build is very important. This post explains why, and how I’m using Make and Docker to achieve that goal.
Pruning old Git branches
Two commands for managing Git branches: one for deleting branches which have already been merged, one for deleting branches which were deleted on a remote.
Downloading logs from Amazon CloudWatch
A detailed breakdown of how I wrote a Python script to download logs from CloudWatch.
My favourite WITCH story
As the WITCH computer celebrates five years since its reboot at TNMoC, a fun story of how it was left to run at Christmas.
A plumber’s guide to Git
How does Git work under the hood? How does it store information, and what’s really behind a branch?
Using hooks for custom behaviour in requests
I often have code I want to run against every HTTP response (logging, error checking) — event hooks give me a nice way to do that without repetition.
Using pip-tools to manage my Python dependencies
How I use pip-tools to ensure my Python dependencies are pinned, precise, and as minimal as possible.
Some useful Git commands for CI
A couple of Git commands that I find useful in builds and CI.
Ode to docopt
Why I love docopt as a tool for writing clean, simple command-line interfaces.
A Python module for lazy reading of file objects
I wrote a small Python module for lazy file reading, ideal for efficient batch processing.
Listing keys in an S3 bucket with Python
A short Python function for getting a list of keys in an S3 bucket.
A Python interface to AO3
AO3 doesn’t have an official API for scraping data - but with a bit of Python, it might not be necessary.
Experiments with AO3 and Python
AO3 doesn’t have an official API for scraping data - but with a bit of Python, it might not be necessary.
Another example of why strings are terrible
Pop quiz: if I lowercase a string, does it still have the same length as the original string?
Use keyring to store your credentials
If you need to store passwords in a Python application, use the keyring module to keep them safe.
Creating low contrast wallpapers with Pillow
Take a regular tiling of the plane, apply a random colouring, and voila: a unique wallpaper, courtesy of the Python Imaging Library.
Tiling the plane with Pillow
Using the Python Imaging Library to draw regular tilings of squares, triangles and hexagons.
Why I use py.test
Why py.test is my unit test framework of choice in Python.
A shell alias for tallying data
A way to count records on the command-line.
aspell, a command-line spell checker
Python snippets: Cleaning up empty/nearly empty directories
A pair of Python scripts I’ve been using to clean up my mess of directories.
Python snippets: Chasing redirects and URL shorteners
A quick Python function to follow a redirect to its eventual conclusion.
Clearing disk space on OS X
A few tools and utilities I’ve been using to help clear disk space on my Mac.
Introduction to property-based testing
Testing with randomly generated examples can be a good way to uncover bugs in your code.
Finding 404s and broken pages in my Apache logs
A Python script for finding 404 errors in my Apache web logs - and by extension, broken pages.
A Python smtplib wrapper for Fastmail
A quick python-smtplib wrapper for sending emails through Fastmail.
Safely deleting a file called ‘-rf *’
If for some reason you create a file called
-rf *, it’s possible to delete it safely. But really, don’t create it in the first place.Treat regular expressions as code, not magic
Regexes have a reputation for being unreadable monsters, but it doesn’t have to be that way.
Get images from the iTunes/App/Mac App Stores with Alfred
Using Alfred and a Python script to retrieve artwork from the iTunes, App and Mac App Stores.
Exclusively create a file in Python 3
If you want to create a file, but only if it doesn’t already exist, Python 3 has a helpful new file mode
x.Pretty printing JSON and XML in the shell
Backups and Docker
The Docker folder on your computer can quickly fill up space. Don’t forget to exclude it from backups.
Export a list of URLs from Safari Reading List
A Python script for getting a list of URLs from Safari Reading List.
Python and the BBC micro:bit
Playing with a tiny computer that runs Python.
Quick shell access for Docker containers
A Bash function for quickly getting shell access to Docker containers.
Review: Effective Python
A review of Effective Python, by Brett Slatkin.
Finding even more untagged posts on Tumblr
A new version of my site for finding untagged Tumblr posts.
Useful Bash features: exit traps
Safer file copying in Python
A Python script for non-destructive file copying/moving.
Useful Git features: a per-clone exclude file (.git/info/exclude)
Another way to ignore untracked files in Git.
Pygmentizr
A web app for applying syntax highlighting to code using the Pygments library.
Tidying up my 1Password
Adding checkboxes to lists
A bookmarklet to add checkboxes to lists in the browser.
Acronyms
Unpacking sets and ranges from a single string
Notes on Tumblr
Playing with 404 pages
Updates to my site for finding untagged Tumblr posts
A quick Alfred workflow for opening recent screenshots
Thoughts on Overcast
Some thoughts on Marco Arment’s new podcast player, Overcast.
Getting plaintext LaTeX from Wolfram Alpha
Finding untagged posts on Tumblr, redux
Finding untagged posts on Tumblr
Darwin, pancakes and birthdays
Looking at whether Darwin ever missed out on birthday cake for pancakes
214 notes
How to truncate the middle of long command output
Use a command group
{ head -n 3; echo '[…]'; tail -n 5; }to snip print the first few and last few lines.AirPlay Receiver can interfere with Flask apps
It listens on port 5000, which is the default port used for running Flask apps in debug mode, then Safari sends blank pages for my Flask app.
What’s the
mainprefix in SQLite queries?SQLite uses schema prefixes like
mainandtempto disambiguate between attached databases and connection-specific temporary tables.The file(1) command can read SQLite databases
It can identify a SQLite database and give you basic information about the version, page count, encoding, and more.
My randline project is tested by Crater
I got a GitHub issue warning me that my project will break with a future version of Cargo.
Drawing an image with Liquid Glass using SwiftUI Previews
I used Xcode to create an image with a Liquid Glass effect, then I used the Preview to export it as a standalone file.
My preferred options for SmartyPants in Python
smartypants.smartypants(…, Attr.q | Attr.D | Attr.e | Attr.u)Setting up golink in my personal tailnet
I created a macOS LaunchAgent to start golink automatically whenever my desktop Mac restarts.
Create a file atomically in Go
Use
os.CreateTempto create a temporary file in the target directory, then do an atomic rename once you’ve finished writing.Get a map of IP addresses for devices in my tailnet
How to do resumable downloads with curl
You want the
--continue-at -flag, which will resume the transfer from the size of the already-downloaded file.The SQLite command line shell will count your unclosed parentheses
If the prompt starts with
(x1or(x2, it means you’ve opened some parentheses and not closed them yet.Use SQL triggers to prevent overwriting a value
A trigger lets you run an action when you
INSERT,UPDATEorDELETEa value.Testing date formatting with date-fns-tz and different timezones
Override the
TZenvironment variable in your tests.How to find the Pygments token type for a short name
Look at the source code of
pygments.token.How to expire a Tailscale node key faster than the min expiry
Use
tailscale debug set-expire --in=<duration>.Use
systemctl is-activeto determine if a service is runningRemoving a self-hosted runner from GitHub Actions
My Git config
How I set up Git on a new computer.
Python f-strings cheat sheet
Some Python f-string examples that I find helpful.
The caret anchor (
^) matches differently in Python and RubyIgnore AI upscaled YouTube videos with yt-dlp
Filter for formats that don’t include
-sr(“super resolution”) in their format ID.Collapsing whitespace in a Liquid template
Output an empty string with stripped whitespace, that is
{{- "" -}}.The LastModified date of an S3 multipart upload is when the upload started, not when it finished
Python has a builtin tool to do rot13 (among other things)
Look in the codecs module.
Remove the microsecond precision from a
datetimein PythonCall
datetime.replace(microsecond=0).Look at the
__annotations__to learn about the definition of a TypedDictDon’t show Dock icons from apps on another device
The name of this feature is “Handoff”, and that’s where you’ll find the setting for it.
Using the Tumblr v1 API doesn’t require auth
You can get information from
https://{username}.tumblr.com/api/read.Use the
-vflag to get verbose output from Go testsThis prints all
t.Logandt.Logfcalls, even if the test succeeds or times out.Get a list of values in a JSON object with jq
The equivalent to Python’s
dict.values()isjq '[.[]]'.Seeing the public node key of a Tailscale node
Use
tailscale status --self --jsonortailscale debug netmap.Don’t nest a
<Script>in a<Head>with Next.jsIf you do, the rendered page won’t include the script anywhere.
Using Go to write to a file, but only if it doesn’t exist yet
Opening a file with
os.O_CREATE|os.O_EXCLwill ensure you only create the file if it doesn’t already exist.The person who runs the Cambridge NTP servers has an excellent email address
Discard a variable in a JavaScript object spread by assigning it to
_Repeatedly run flaky Go tests with
stressIt runs your test hundreds of times, which can be useful for finding flaky failures.
How to play with SQLite functions without real data
You can run a
SELECT function(…);query without any tables.How to list the tests that will be run by a
go testcommandUse
go test -list={pattern}.Looking up posts in the Bluesky API
Install the
atprotopackage, construct a client with your username/password, then call theget_post_threadmethod with yourat://URI.Using zipstream to stream new zip files to object storage with boto3
You can construct a
zipstream.ZipFile, add files, then wrap it in a file-like object to upload it withS3.upload_fileobj.Using Linode object storage and boto3
If you’re calling
put_object, you need the config optionrequest_checksum_calculation = "when_required".Adding a string to a tarfile in Python
Wrap the string in an
io.BytesIOfirst, then create aTarInfoobject and pass them both toaddfile()to add the string to your tarfile.Disable HTTP Basic Auth for certain pages in Caddy
Define a matcher that negates the routes you want to be public, then use that with your
basic_authdirective.Collecting pytest markers from failing tests
You can annotate tests with markers, and using the
pytest_collection_modifyitemsandpytest_terminal_summaryhooks you can get a list of markers for tests that failed.You can change the size of tabs on web pages with the
tab-sizepropertyShow a list of checkboxes in a WTForms form
Subclass
SelectMultipleFieldand override thewidgetandoption_widgetfields.Redacting sensitive information from gunicorn access logs
Create a subclass of
gunicorn.glogging.Logger, and redact information in theatoms()method.Listen for the
popstateevent to see when the user clicks the “back” buttonMore generally, it fires whenever the user is navigating the session history.
Python’s f-strings support
=for self-documenting expressionsThe f-string
f"{x=}"expands tof"x={x}".Comparing two files in a bash script
Inspect the exit value of
cmp --silent.Use
typing.getargs()to get a list oftyping.Literal[…]valuesRuby’s range can iterate over more than just numbers
You can iterate over a range between two
Stringvalues, because Ruby’sStringdoes intelligent increments of alphanumeric strings.The error “No aggregated item, sequence was empty” comes from Jinja2
You get this error message if you try to use Jinja2’s filters to get the min/max of an empty sequence.
How to run a task on a schedule on macOS
Create a
LaunchAgentwith aStartCalendarIntervalorStartIntervalthat defines how often you want the task to run.Get a string representation of a Python traceback with
traceback.format_exc()Go’s compiler is smart enough to spot division by zero errors
Parsing JSON in Go with a required field
Use
text=truewithsubprocessfunctions to get stdout/stderr as str, not bytesGet the duration of a video file with
mediainfoUse
mediainfo --Inform='Video;%Duration%' [VIDEO_FILE].Print a comma-separated number in Python with
{num:,}You can use
{num:,}to insert a comma every three digits,{num:_}to insert an underscore every three digits, and{num:n}to insert a locale-aware digit separator.Add the
-vflag to see whatrmis deletingYou can set/update the
totalof a progress bartqdmafter it startsUpdate the
.totalattribute, then call.refresh().How to stream lines from stdout with
subprocessUse
subprocess.Popen()withbufsize=1andtext=True, then you can interate over the lines withproc.stdout.How do I find photos of a person on Flickr?
https://www.flickr.com/people/{path_identifier}/photosofHow does Flickr’s getLicenseHistory handle photos with no license changes?
Python 3.14 includes a pi-related Easter egg
You can start the interpreter with
𝜋thon!Where does AirDrop save files on macOS?
Look in
/private/tmp.How to check if Tailscale is running
Use
tailscale statusand look for theBackendStatekey.To filter the results of a SQLite tally for values with a certain frequency, use a
HAVINGinstead of aWHEREclauseSELECT col_name, COUNT(*)
FROM tbl_name
GROUP BY col_name
HAVING COUNT(*) > 100;When fixing mojibake, use
ftfy.fix_and_explain()to understand how it’s fixing a piece of textWhy isn’t
delete_where()deleting rows in sqlite-utils?The
delete_where()function doesn’t auto-commit, so you need to wrap itwith db.connor something else to trigger the commit.console.log()holds a reference to an object, not a copy of itWhen you view an array/object with
console.log(), you see the contents at the time you expand it, not as it existed when you calledconsole.log().You can set an output mode for SQLite
How do you write ratios in the
aspect-ratioproperty?When you define an aspect ratio as
x/y, you can only use numbers forxandy.Python 3.13 throws a
ResourceWarningfor SQLite databases that aren’t explicitly closedHow to install exiftool in GitHub Actions
How to get a macOS file/folder icon in Swift
Use
NSWorkspace.shared.iconto get the icon as anNSImage, then you can save it to disk or do something else with it.Disable JavaScript in an
<iframe>by setting thesandboxattributeCreate an animated placeholder box with CSS
What does Flickr return in the
flickr.photo.getSizesAPI for videos?The video’s owner will get the URL to the original video file as “Video Original”, otherwise you should look for the largest video size.
A basic socket server in Ruby
My first bit of socket programming is a Ruby server that reads lines from the socket, and prints them. Not useful on its own, but a stepping stone to more exciting things!
Getting and setting the cover image from an EPUB file
How to find the
content.opfin an EPUB fileHow to find platform-specific directories
Two Python libraries for this task are appdirs and platformdirs, which tell you the location of the platform-specific cache directory and other similar directories.
Restricting routes to pre-approved IP addresses in Caddy
Use
shutil.copyfileobjandxbto avoid overwriting files when copying in PythonHow to tally the attributes of the top N rows in a SQLite table
Use a
WITHclause to do a nested query for the top N rows in the table, then do a tally over that result.How to get the IP address of a device in my Tailnet
Use
tailscale status --jsonand filter the output usingjq.How to find the biggest files backed up by Backblaze
Look at the file
/Library./Backblaze.bzpkg /bzdata /bzfilelists /bigfilelist.dat There are limits on the styles you can apply with
:visitedBecause the
:visitedselector will tell you whether somebody has been to a URL, browsers limit what styles you can apply to such links – to prevent somebody nefarious stealing your browsing history.Editing a filename in Finder will convert it to NFD
Even if the filename looks the same, it may be invisibly converted to a different sequence of bytes.
How can I work out what program is keeping a disk open?
Use
sudo lsofand grep for the name of the disk you’re trying to eject.You can reset the start of a regex in Ruby
The
\Kescape is the “Match-Reset Anchor”, which resets the start of the reported match, and skip any previously consumed characters.What errors can you get from
hyperlink.parse?Mostly you get
hyperlink.URLParseError, but you can occasionally get aValueErroras well.How to get the expiry date of an HTTPS certificate with Ruby
Connect to the domain using
net/http, then you can inspect thepeer_cert/not_afterproperty on the response.Debugging some confusing behaviour with
findandxargsUse the
--verboseflag to see whatxargsis doing; don’t rely onfindto return files in a consistent order.How to install an asset from a GitHub release
Use
gh release download, which includes a pattern matcher if you want to pick a specific asset.Creating a reverse proxy to a multi-site server with Caddy
You need to add Host headers and HTTPS configuration to your
reverse_proxyblock.How to find all of Apple’s system icons
You need to look for files named
*.icnsinside any subdirectory ofCoreTypes.bundle.Drawing a diagonal banner over the corner of an image
Find the shortest prefix to identify a string in Ruby
The built-in
Abbrevmodule can calculate a set of unambiguous abbreviations for a set of strings, and then you can look for the shortest result for each string.How to get the target of an HTTP redirect with curl
What is the
author_namein the list of tags on a Flickr photo?When you call the
flickr.photos.getInfoAPI, each tag is attributed to an author. Theauthor_nameis their username, not their realname.How to get a user’s email address with the Flickr API
The
flickr.profile.getProfileAPI returns somebody’s email address, but only if you’re allowed to see it.Making an “under construction” element in pure CSS
Using a
repeating-linear-gradientas thebordergets you something that looks a bit like hazard tape.HTML strings may not be equivalent if you minify them
There’s a lot of whitespace in HTML which looks irrelevant at first glance, but may be significant and cause the document to render differently.
How do the
ispublic,isfriendandisfamilyflags work in the Flickr API?Use
std::io::IsTerminalto detect if you’re running in the terminal in RustThis allows me to suppress ANSI escape codes if the output is going somewhere other than the terminal.
Use
$_to get the last argument to the previous bash commandThis allows you to write commands like
mkdir myfolder && cd $_orgit init myrepo && cd $_.With Flask-Login, you want
current_user == None, notcurrent_user is Nonecurrent_useris a proxy object that happens to be wrappingNone, but isn’t actuallyNone.How to get the expiry date of an HTTPS certificate with Python
Connect to the domain using the
socketmodule, then use thegetpeercert()method on the connection to get information about the HTTPS certificate.Write to the middle of a file with Python
Open the file with mode
r+to be able to seek around the file and write to it.Custom error pages in Flask
You can use
app.error_handlerto add custom responses for HTTP status codes, so the errors match the look and feel of the rest of the site.Create solid-colour image placeholders to show before an image loads
Get an image from a video with ffmpeg
Get the embedded artwork from an MP3 file
Use the command
eyeD3 [MP3_FILE] --write-images [FOLDER].Convert an animated GIF to an MP4 with ffmpeg
Using the Wikimedia Commons API to tell if a file has been deleted
Build a URL with query string parameters with curl
A combination of
--getand--data/--data-urlencodeallows you to write curl commands which are readable and expressive.How to get the selected item in Finder using AppleScript
What happens when you replace a photo on Flickr?
Why the term “snak” keeps appearing in the Wikidata API
Get my Netlify bandwidth usage from the API
Removing letterboxing from a video screenshot with ImageMagick
Using
-trimwill remove the black portions and leave you the unletterboxed image.How to check the quality of a network connection
Using an
NWPathMonitorand inspecting the value ofNWPath.status,NWPath.isExpensiveandNWPath.isConstrainedcan tell you what sort of connection you’re running on.How to highlight Python console sessions in Jekyll
Adding a couple of options to the
consolelexer (console?lang=python&prompt=>>>) gets you syntax highlighting for a Python console session.How to simulate an
[Errno 54] Connection reset by peerwhen using pytestYou can run a TCP server in the background using a fixture, and using the
SO_LINGERsocket option can reset the connection.Writing a file in Swift, but only if it doesn’t already exist
Adding
.withoutOverwritingto yourwrite()call will prevent you from overwriting a file that already exists.Get a Palette colour as a command-line argument with Clap
Wrapping a
Palette:Srgbin a struct and implementingFromStrfor the struct allows you to take hexadecimal colours as command-line inputs.How to get the filename/size without downloading a file in curl
You can do some fun stuff with the
--write-outflag and variables.There’s a musical that tells you the number of minutes in a year
The song Seasons of Love from Rent starts with the line “Five hundred twenty-five thousand, six hundred minutes”.
How to get a tally of tally counts in SQLite
Using a nested query allows me to perform a two-level aggregation of the values in a column – how many values appear once, how many twice, and so on.
How to count how many Discord messages were sent on a given day
Using the
Duringfilter gives me a count of how many messages were being sent.How to see the HTTP requests being made by pywikibot
To see exactly what HTTP requests were being made, I modified the library so that betamax would record requests.
How to embed an inline SVG in a CSS rule
Modern browsers allow you to embed the SVG almost as-is, with just a couple of characters that need escaping – no base64 required!
How to shuffle an array in a Jekyll template
If you want an array in random order, you can use the
samplefilter to get a random sample of the same size as the original array.Checking if a URL has changed when you fetch it over HTTP
When you make an HTTP request, you can use the
If-Modified-Sinceheader to get a 304 Not Modified if nothing has changed since your last request.The
opencommand can ask questionsIf you pass an argument that can’t be easily identified as a file or a URL,
openwill ask you what to do next. This may be a surprise if you were trying to use it in a script.Why is Pillow rotating my image when I save it?
Images can have orientation specified in their EXIF metadata, which isn’t preserved when you open and save an image with Pillow.
How to change the name of an internal link in an Obsidian table
Escaping the pipe like
[[filename\|display text]]allows you to customise the of a link in a table.Getting a boto3 Session for an IAM role using Python
Why I use Sessions in boto3, and the Python function I use to create them.
My config for running youtube-dl
The flags and arguments I find useful when I’m using youtube-dl.
How much will Mastodon instances try to re-send messages?
How to restrict a page to specific IP addresses
Use the
-n/-iflags to avoid overwriting files withcpandmvHow to parse URLs in JXA
Using
errexitand arithmetic expressions in bashHow to check when an HTTPS certificate expires
The COUNT(X) function only counts non-null values
Exclude files from Time Machine with
tmutil addexclusionYou need to call
resp.close()to close the file opened bysend_file()Use the
{% raw %}tag to describe Liquid in LiquidIf you’re trying to write about using Liquid tags in a Liquid-based site, wrapping your tags in the
{% raw %}tag will prevent them being rendered.What characters are allowed in titles on Wikimedia Commons?
Run a script on macOS on a schedule using a LaunchAgent
Beware of using
test -nwith command expansionGet and manipulate the contents of a page in Safari with
"do JavaScript"How to do offline geo-lookups of IP addresses
MaxMind offer databases you can do to look up IP addresses without sending the address off to a remote service.
How to tally combinations of values across multiple columns
How to move files when you need sudo on the remote server
How to gracefully restart a gunicorn app
How to find the longest common suffix in a list of strings in Python
How to simulate shell pipes with the subprocess module
Use the
{% capture %}tag to assign complex strings to variablesIf you want to get a string that’s semi-complicated to construct, you can put a “mini-template” in the
{% capture %}tag to build it over multiple lines.How to create a footer that’s always at the bottom of the page
WordPress URLs that get hammered by spammers
Manage MP3 metadata from iTunes with eyed3
Sort a list of DOM elements by sorting and calling
appendChild()How to create flag emojis for countries in Python
Use the IMAGE function to insert an image into a spreadsheet
How to style a
<details>element differently depending on whether it’s open or closedCreate a directory before you
cpormva file to itRunning the Netlify CLI in GitHub Actions
Use shlex.split() to parse log files quickly
Use the regex library to get Unicode property escapes in Python
Run a randomly selected subset of tests with pytest
By reading the code for the
pytest-random-orderplugin, I was able to write a new plugin that runs a random subset of tests.Getting a tally of SQLite values as a CSV
Using sqlite-utils to convert a CSV into a SQLite database
You can use sqlite-utils on the command line to create a SQLite database from a CSV file.
Python’s sqlite3 context manager doesn’t close connections
The
sqlite3.connect(…)context manager will hold connections open, so you need to remember to close it manually or write your own context manager.How to delete albums
Live Text is aware of how hyphenation works (kinda)
Go between M-IDs and filenames on Wikimedia Commons
Telling mechanize how to find local issuer certificates
Calling
browser.set_ca_data(cafile=certifi.where())will tell where mechanize can find some local SSL certificates.Why I prefer XML to JSON in the Wikimedia Commons APIs
The XML-to-JSON conversion leads to some inconsistent behaviour, especially in corner cases of the API.
Find files that use a particular SDC field
The acronym “woe” in the Flickr API stands for “Where On Earth”
Use Unicode property escapes to detect emoji in JavaScript
Finding the original page for a post on Mastodon
Following the logged-out 302 Redirect takes you to the original post.
Use concurrency gates to prevent concurrent deployments
How to profile Swift code
Getting the base directory of an sbt project
Some notes on printing sbt settings, so you can use them as the input to another script.
How to use hex colours with the palette crate
You can use
Srgb::from_str()to parse a hexadecimal string as a colour in the palette crate.A Python function to ignore a path with .git/info/exclude
If your Python script creates a file that you don’t want to track in Git, here’s how you can ignore it.
Use
git check-ignoreto debug your.gitignoreRunning
git check-ignore --verbose <PATH>will tell you which rule applies to a given path, and where that rule is defined.Installing mimetype on Alpine Linux
How do Dreamwidth posts IDs work?
They were deliberately non-sequential as an anti-spam technique. It’s no longer required, but it’s in the codebase now and hasn’t been changed since it was written.
Conditional updates on nested fields in DynamoDB
Add a Git co-author credit with “Co-authored-by” in your commit message
How to iterate over the lines of an InputStream in Scala
Using TransportAPI and geopy to get the distance between stations
Manipulating URL query parameters in JavaScript
The Content-Disposition header can be used to name a downloaded file
How to suppress installing rdoc/ri docs when running
gem installReplace black/white parts of an image with ImageMagick
Pushing with
--force-with-leaseis safer than with--forceIt checks the remote state of the origin hasn’t changed since you last fetched, so you don’t risk overwriting anybody else’s commits.
How to use xargs for parallel processing
Create compact JSON with Python
Calling
json.dumps(…, separators=(',', ':'))will reduce the amount of whitespace in the final string.Custom 404 responses in Finatra
A snippet for returning a custom 404 response in a Finatra app when somebody requests a missing page.
List all Git object IDs and their type
Python throws a TypeError if you return a non-string from a custom
__repr__or__str__methodIt fails with the error “
__repr__/__str__returned non-string”.Why does Hypothesis try the same example three times before failing?
Rust macros are smarter than just text substitution
This is a safety feature that prevents macros expanding in an unexpected way.
You can use
shutil.whichto check if an executable is in your PATHThis is useful for checking if something’s installed.
Get an RSS feed of external audio posts on Tumblr
If you add
/podcastto a Tumblr site, you get a podcast-like RSS feed for all the external audio posts on that site.