Systems and software
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
- Code crimes
- CSS
- Datetime shenanigans
- Docker
- Error messages
- Git
- Go
- HTML
- Images and videos
- JavaScript
- jq
- LaTeX
- Python
- Regular expressions
- Ruby
- Rust
- Scala
- Shell scripting
- Software testing
- SQLite
- Swift
- Tailscale
- Terraform

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.

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.

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.
138 articles
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.
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.
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.
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.
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.
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.
Step… Step… Step…
Swing dancing and prompt engineering are pretty different. But could learning one help us learn the other?
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.
Spotting spam in our CloudFront logs
Looking for search queries that came from robots, not real people.
Finding a mystery IAM access key
Using the GetAccessKeyInfo and GetAccessKeyLastUsed APIs can help us trace an IAM key back to its source.
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.
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.
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.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.
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.
Ten years of blogging
A decade ago, I registered a domain and started writing.
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.
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.
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.
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.
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.
An editing toolbar for alexwlchan.net
A bookmarklet that gives me a just-for-me toolbar to make changes to this site.
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!
Finding misconfigured or dangling CloudWatch Alarms
A Python script that finds CloudWatch Alarms which are based on a now non-existent source.
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.
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.
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.
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.
Finding the months between two dates in Python
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?
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
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
Saving a copy of a tweet by typing ;twurl
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.
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.
Listing even more keys in an S3 bucket with Python
Python functions for getting a list of keys and objects in an S3 bucket.
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.
Atomic, cross-filesystem moves in Python
Explaining some code for moving files around in a way that’s atomic and works across filesystem boundaries.
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.
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.
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.
The Hypothesis continuous release process
How we do continuous releases of hypothesis-python, and why.
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.
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.
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.
Some useful Git commands for CI
A couple of Git commands that I find useful in builds and CI.
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.
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.
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.
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.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
Export a list of URLs from Safari Reading List
A Python script for getting a list of URLs from Safari Reading List.
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.
Acronyms
Unpacking sets and ranges from a single string
Updates to my site for finding untagged Tumblr posts
A quick Alfred workflow for opening recent screenshots
Getting plaintext LaTeX from Wolfram Alpha
Finding untagged posts on Tumblr
Darwin, pancakes and birthdays
Looking at whether Darwin ever missed out on birthday cake for pancakes
140 notes
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.
Ignore 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 TypedDictUse 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.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}.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.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.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-sizepropertyRedacting sensitive information from gunicorn access logs
Create a subclass of
gunicorn.glogging.Logger, and redact information in theatoms()method.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.
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].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.Python 3.14 includes a pi-related Easter egg
You can start the interpreter with
𝜋thon!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;Why 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 thesandboxattributeA 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!
How 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.
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.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.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.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.Making an “under construction” element in pure CSS
Using a
repeating-linear-gradientas thebordergets you something that looks a bit like hazard tape.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.Convert an animated GIF to an MP4 with ffmpeg
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.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.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 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!
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.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.
Use the
-n/-iflags to avoid overwriting files withcpandmvHow to parse URLs in JXA
Using
errexitand arithmetic expressions in bashThe COUNT(X) function only counts non-null values
You 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.Beware of using
test -nwith command expansionGet and manipulate the contents of a page in Safari with
"do JavaScript"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
Sort a list of DOM elements by sorting and calling
appendChild()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.Live Text is aware of how hyphenation works (kinda)
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.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.
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
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
Manipulating URL query parameters in JavaScript
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.