In September, I went to Belgium for a digital preservation conference. I wrote about what I learnt and what I saw for the Flickr.org blog.
When I hover over an image, I can add a border to a link, or change the colours of an SVG icon.
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.
A few shell scripts I use to go between the Finder and the Terminal.
I’ve made a new tool that allows me to reuse my thumbnailing code across all my projects.
Dozens of MPs who were re-elected to their seats are still labelled “former Member of Parliament”, days after the election results.
I’ve been writing tools in Rust again.
The new bot improves metadata for Flickr photos on Wikimedia Commons, and makes it easier to find out which photos have been copied across.
I made a library that knows how to read lots of different forms of Flickr.com URL, and I used hyperlink
to do it.
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.
I went to France for a conference about archiving the web, and I came back with thoughts and photos.
Whatever displaces public cloud as the default model for large-scale computing has to be more than “AWS, but 3% better”.
It’s the scientific study of elections and voting, and it comes from the Greek word for “pebble”, because pebbles were used for voting in ancient Greece.
I was able to build my Jekyll site much faster by using the built-in caching API.
If you listen carefully to the Ballad of Willie Watkins, you might hear another song peeking through.
Combining several existing tools to make something that allows for quick experiments and exploration.
A new way to browse the photos in the Flickr Commons programme.
Swing dancing and prompt engineering are pretty different. But could learning one help us learn the other?
Some experimenting with the YouTube API to merge two accounts into one.
A fledgling author uses a theatre trip to leave the nest. (Or: some props I made for a cosplay event.)
In which Apple Photos accidentally tells me about a cool new animal.
Although Obsidian doesn’t support AppleScript, I can use System Events to find out which note I have open.
I wrote some shell config to smooth out the experience of using virtual environments in Python.
A few commands that help me keep unwanted entries out of my shell’s autocomplete.
A quick script to help move the biggest items out of my main Photos Library.
Looking for search queries that came from robots, not real people.
My Apple Watch knows where I am, which is handy when I have a camera that doesn’t.
After nearly seven years, it’s time for something new.
The tags, folders, and themes I use to manage information in my Obsidian vaults.
Using the GetAccessKeyInfo and GetAccessKeyLastUsed APIs can help us trace an IAM key back to its source.
Applying a default tag that points to the IaC definition makes it easy to go from the console to the code.
A couple of functions I use to get access to CloudFront logs as easy-to-use iterators.
A function to find all the files in a directory is one of my most-used snippets.
How I make images that load quickly and look good for readers, and which are easy for me to manage.
A two-handed sapphic romance with a clever narrative twist makes for a compelling and thoughtful new play.
Calling the UpdateService API on a fixed schedule allows us to turn services off in the evening, and back on again the next morning.
How to make sure you get a Date
back when you call JSON.parse
and JSON.stringify
.
Having one function that you always use to get the current time is super handy when debugging issues that only occur at specific times.
I don’t keep Docker running all the time, but intercepting the docker
command means it’s always running when I need it.
AppleScript only allows us to add photos to an album; dipping into Swift and PhotoKit lets us both add and remove photos.
A script to give me a quick overview of some objects in a hierarchical view.
When ECS is “unable to consistently start tasks successfully”, we get a Slack alert that tells us to investigate.
Terraform can fill in placeholders with exact values from your deployment, for easy copy/paste instructions.
Careful use of the PublishBatch
API makes it quick and easy for me to send thousands of messages into SNS.
Using from_entries
is a nicer way to deal with the list of Name/Value pairs returned by the AWS CLI.
Using redirects to filter out bots trying to hack my non-existent PHP installation.
Using collections.UserDict, we can create a dictionary where dict[key1] and dict[key2] always point to the same value.
How do you make sure everyone gets to work with everyone else?
The browser can be a pretty good place to run your JavaScript tests.
Did you know you can use %c
to format your console.log
messages?
Digitising and pruning my boxes of paper from school. In which I have nostalgia, sadness, and the sense that everything old is new again.
Getting something that looks more like the output of the ListObjectsV2 API.
Building our own platform allowed us to make decisions based on what’s best for the collections, and not the limitations of our digital infrastructure.
Debugging my <picture> and <source> tags.
A note to my future self. Also, reverse image search is amazing.
You probably want to use version 7.
Using Apple’s built-in tools to get OCR text from an image, but without going through a GUI.
Party like it’s 1996! A trailing checkmark cursor will make your Brand Website feel fun and authentic.
By downloading all our Prismic documents, we can run validation rules, fix broken links, and find interesting examples.
Some notes on printing sbt settings, so you can use them as the input to another script.
Using a custom transporter to modify the log message and remove secret information.
Updating the accent colour everywhere, with immediate effect, using a script written in Swift.
A decade ago, I registered a domain and started writing.
Twitter’s archives don’t include the alt text you wrote on images, but you can save a copy with their API.
Making it easier to find all the images in my Obsidian vault.
Notes from a talk about agile and iterative approaches to project management.
Some web scraping and Python helps me find books that I can borrow immediately.
Casually covering a canvas with coloured circles.
A suggestion for a better error message to help people who work in multiple languages.
A script that helps us optimise our __NEXT_DATA__
, which in turn helps reduce page size.
When I’m writing templates with Jinja, strict behaviour is what I want, even if it’s not the default.
Repeating geometric patterns make for a colourful and eye-catching piece.
A Python function to help me draw circular arcs, as part of an upcoming project.
Getting a more descriptive build label than ‘Deployment’.
You don’t realise how big the solar system is until you’ve walked the length of it.
If your app has just ruined my day, I need help, not humour.
My last post was surprisingly popular; a few reflections on the experience.
If NASA was the first to land on Mars in For All Mankind, what would the commemorative plaque look like?
I made a cross-stitch blueprint of the Apollo Moon lander and the Saturn V rocket.
Where did this UK phone number come from?
Automations for my automations.
I wanted to learn jq’s more powerful features, so I tried to filter some JSON from the AWS Secrets Manager CLI.
Wrapping my CLI tool for finding dominant colours in a lightweight web app.
Using different targets to build Rust binaries that will run in Glitch.
Some old code I wrote to draw cam-accurate illustrations of cipher wheels.
A bash script to check the HTTP status code of a bunch of URLs, for simple and portable uptime checking.
A mysterious problem with SQS-based autoscaling and an over-eager CloudWatch Alarm.
Some recent changes I’ve made to fix or improve my Twitter cards.
To help me keep my tab count down, I wrote a JXA script to close tabs that can easily be recreated.
Digging into the history of Route 53, DNS, and port number assignments.
Some Python code for turning MRI scans of fruit and veg into animated GIFs.
Explaining some code that draws coloured rectangles in a way that looks a bit like an upside-down bookshelf.
Digging into a throwaway comment in the Python documentation.
An improvement to Rust’s error handling that I almost reported, until I realised it was fixed.
macOS allows both the slash and colon as path separators, and this caused me no small amount of confusion.
A new tool for playing with images.
If you’re looking at a UUID’d file in the PhotosLibrary package, how do you find its original filename?
A collection of small worldbuilding ideas about magical objects.
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.
Slides for a short talk about READMEs, why they’re important, and what they should contain.
If you’re not careful when redacting PDFs, it’s possible to share more information than you intended.
Building a relationship founded on trust and respect.
A bookmarklet that gives me a just-for-me toolbar to make changes to this site.
Sending the AWS bill to Slack, so everyone can be more informed and intentional about spending.
Is uppercasing then reversing a string the same as reversing and then uppercasing? Of course not.
The AWS console will tell you when your EventBridge rule is going to run… if you know where to look.
How do you pick the right combination of planks to lay a wooden floor? Python and itertools to the rescue!
A script that allows me to ignore folders like “target” and “node_modules”, so they don’t appear in search results.
The Markdown syntax for images reminds us that we need to write alt text.
A Python script that finds CloudWatch Alarms which are based on a now non-existent source.
I have hotkeys to search GitHub in several ways, including by user, by repo, and within the work organisation.
Diving into the internals of the AWS SDK to find deleted secrets.
A Python script that shows me how often I’ve been journalling, so I can track my progress.
Making it easier to see how long a file transfer will take, in the terminal.
Collaboration between our digital and collections teams helped to build a single search box for all of our catalogues.
A Python script that shows me the name of processes that have Secure Input enabled.
A web app for creating pairs of hearts based on Pride flags.
Making it slightly easier for me to enable and disable Voice Control quickly.
I joined Corey Quinn to discuss my DynamoDB calculator and using the cloud to preserve digital collections.
How I reincarnated a fifteenth-century monk and taught him to use Twitter.
If you use ICU date formatting, make sure you use the right format specifier for year.
Create short-lived, temporary roles for experimenting with AWS IAM policy documents
I take notes so I remember more of what I read.
School tells us that “Maths always has one right answer!”, which is a convenient but unhelpful lie.
A JavaScript function that remembers if a details element was reopened, and keeps it open when you reload the page.
If your Python script creates a file that you don’t want to track in Git, here’s how you can ignore it.
A script to work out which camera I use most often on my iPhone, and whether I’d miss a telephoto lens.
An Excel mistake shows why learning to write good error messages is a critical skill for software developers.
Although I don’t expect anyone to use it directly, there might be some interesting ideas that could apply elsewhere.
How and why we keep copies of Wellcome’s digital collections in multiple cloud storage providers.
How you can invoke Quick Look on the command-line to generate high-quality thumbnails.
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.
Although an S3 key looks a lot like a file path, they aren’t always the same, and the distinction can trip you up.
Lots of programming languages have a function called main() where code starts executing. Where does this come from?
If you have a function that returns Try[_], how do you call it more than once at the same time?
It’s more complicated than I thought.
Playing with macOS ICNS image files to create colourful new icons.
How many good person points do you lose for making a joke about somebody’s weight?
Using cold storage tiers to reduce the cost of storing Wellcome’s digital collections in the cloud.
We are better off when the same topic is represented in multiple, different archives.
A Python function that generates every item in a DynamoDB table.
What’s a nicer way to show a date than an ISO 8601 timestamp?
Feeling the weight of death in a former concentration camp.
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?
A script that downloads the nicely formatted AO3 downloads for everything I’ve saved in Pinboard.
Using social media can lead us to have more opinions than we really need. Can we fix that?
I want to assign a bunch of variables to True, but I don’t know how many there are. Reflection to the rescue!
You can’t stop people making mistakes, but you can make it more likely that they’ll admit their next mistake to you.
A fun app to calculate the size of your data in terms of floppy disks.
Rehearsing a presentation only tells you the minimum length of time you’ll take. If you’re speaking to a time limit, remember to leave some slack.
A picture speaks a thousand words, which is why I always have pen and paper to hand.
You’re handed a SQL server which has some data, but you don’t know anything about the schema. What do you do?
Cis people are allowed to think about their gender too.
When a complex system fails, it’s usually a combination of problems, not a single person’s mistake.
There are lots of ways to format JSON. How do you know if two JSON strings have the same data, just differently formatted?
We all have bodies, and I’ve been trying to become more self-aware and connected with mine.
Experimenting with a way to store words and phrases that highlights the connections between them.
Notes from a talk about inclusion in design and unconscious bias.
If you’re rich, not only can you invest in good boots, you can also invest in experimental boot-making startups.
It’s okay to take sick leave if you’re working from home.
A way to avoid awkward line breaks in the middle of phrases.
Adjusting the hue to get different colour variants of the same image.
How we use the fetch.txt file in a bag to track multiple copies of an object in our digital archive.
If you’ve tried to disable deletions in your S3 buckets, how do you know they’re working?
A map I use to plot which railway stations I’ve visited.
A web app to generate mashups of Norse valknuts and Pride flags.
YAML allows you to execute arbitrary code in a parser, even if you really really shouldn’t.
My procedure for scanning paper, and organising the scanned PDFs with keyword tagging.
How I get a Cost Explorer graph for the last 30 days of spending, broken down by service.
Slides from a presentation about our processes, practices, and tools.
Some examples of how I’ve been using concurrent.futures to speed up my batch scripting in Python.
Code that pushes I/O to the boundary is simpler, easier to reuse and easier to test.
The filecmp module has a confusing API, and it just caught me out.
Some code and trigonometry for drawing shapes that don’t fit neatly into a rectangular grid.
Reliably reading a large object by stitching together multiple GetObject requests into a single Java InputStream.
Code to turn an InputStream into an Iterator of entries from a tar.gz file or similar compressed archive in Java/Scala.
Using unique prime factorisations and itertools to find all the divisors of a number.
Python functions for getting a list of keys and objects in an S3 bucket.
Where does braille come from? How was braille originally written? What can you write in braille today? And more.
After months of introspection and soul-searching, I’ve had some big realisations about my identity.
The original Markdown implementation would do randomised hex/decimal encoding to help obscure email addresses, and I do the same in Jekyll.
Although paper dictionaries are mostly a thing of the past, knowing how to use a Chinese dictionary helps me learn the rest of the language.
I wrote some AppleScript to help me do batch conversion of Acorn images into formats like PNG and JPEG.
At WWDC, I was disappointed to see Apple pitch period tracking exclusively towards women, and not in a more gender-inclusive way.
Notes on common themes and ideas in a variety of trans inclusion policies, as we start thinking about writing a policy at Wellcome.
It’s not quite the number of seconds since 1 January 1970.
Breaking down some tricky code that allows us to lock over concurrent operations.
Twitter uses t.co to shorten links in tweets, so I wrote some Python to take a t.co URL and find the original tweet.
Using the auto-generated captions from a YouTube video as a starting point for a complete transcript.
Saving myself the trouble of clicking that pesky “merge” button.
Explaining some code for moving files around in a way that’s atomic and works across filesystem boundaries.
Code for processing large objects in S3 without downloading the whole thing first, using file-like objects in Python.
Slides and notes for my talk ‘The Curb Cut Effect’. Making something better for disabled people can make it better for everybody.
Notes from the inaugural ‘You Got This’ conference, a conference about creating a healthy and sustainable work life.
Some notes on trying to do this in a way that supports both Python 2 and 3, and the frustration of doing so.
A snippet for iterating over an arbitrary iterable in chunks, and returning a smaller chunk if the boundaries don’t line up.
A script that creates temporary credentials for an assumed IAM role, and stores them in ~/.aws/credentials.
Since Tumblr users are going on a mass deletion spree (helped by the Tumblr staff), some scripts to save content before it’s too late.
The three lists I use to manage my book recommendations.
Pictures from my trip to the waterfalls and former tin plating works at Aberdulais.
I’m trying out Go, and I wrote a tool to help me find SNS topics that don’t have any subscriptions.
A snippet for returning a custom 404 response in a Finatra app when somebody requests a missing page.
How do we design services and platforms to reduce the risk of harassment and abuse from other users?
Notes and slides from my PyCon UK 2018 keynote. In a world where people are less and less trusting, how can we take steps to make ourselves more trustable?
A few lessons I learned while doing the signage for this year’s PyCon UK.
A snippet to make it a bit easier to debug errors in AWS Lambda functions written in Python.
A quick braindump of my thoughts from drawing some venue maps for PyCon UK.
Prototype code for running a parallel scan against a DynamoDB table, and using Scanamo to serialise rows as Scala case classes.
I see an intermittent 303 Redirect when trying to navigate to a Tumblr ‘permalink’; changing the User-Agent seems to fix it.
A collection of ideas and suggestions for running conferences which are more inclusive and accessible. Based on my experiences at AlterConf, PyCon UK, and similar events.
I recently discovered that iCloud was deleting my old calendar entries, so I switched to FastMail.
A cautionary tale of a daft incident where I leaked a set of SSH keys to GitHub.
Adding a USB extension cable to my iMac makes a world of difference.
A Python snippets for drawing bar charts in command-line applications.
If you use Python’s subprocess module, be careful you don’t leak sensitive information in your error logs.
Two shell functions for editing and inspecting S3 objects as if they were local files.
Slides and notes for a talk about online harassment, and why you should always design with an abusive ex in mind.
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.
How we do continuous releases of hypothesis-python, and why.
Although hopefully never needed, I think it’s worth keeping an overnight bag in your workplace.
Code for saving every message from an SQS queue, and then saving the messages to a file, or resending them to another queue.
Python functions for getting a list of keys and objects in an S3 bucket.
If you’re writing technical docs and need placeholder IP addresses or DNS hostnames, there are some special values just for you!
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.
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.
A detailed breakdown of how I wrote a Python script to download logs from CloudWatch.
As the WITCH computer celebrates five years since its reboot at TNMoC, a fun story of how it was left to run at Christmas.
Tapping the microphone to test it can be bad for all sorts of reasons – and other advice from the Nine Worlds speaker guidelines.
How does Git work under the hood? How does it store information, and what’s really behind a branch?
In the tech industry, how can we be more aware of our privilege, and use that to build inclusive cultures?
Why I like the lottery system used to select lightning talks at PyCon UK this year.
Slides for showing tweets that look like tweets on slides in Keynote and PowerPoint.
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.
I’m very picky about the way underlines look, and have spent a lot of time trying to get the perfect underline in LaTeK .
How I use pip-tools to ensure my Python dependencies are pinned, precise, and as minimal as possible.
A couple of Git commands that I find useful in builds and CI.
Why I love docopt as a tool for writing clean, simple command-line interfaces.
I wrote a small Python module for lazy file reading, ideal for efficient batch processing.
A Rust utility for saving local copies of my full-page archives from Pinboard.
A short Python function for getting a list of keys in an S3 bucket.
For accessibility and inclusion, AlterConf sets a high bar to beat.
AO3 doesn’t have an official API for scraping data - but with a bit of Python, it might not be necessary.
AO3 doesn’t have an official API for scraping data - but with a bit of Python, it might not be necessary.
Pop quiz: if I lowercase a string, does it still have the same length as the original string?
A few suggestions for “low tech devices” that aid in the process of generating ideas.
If you need to store passwords in a Python application, use the keyring module to keep them safe.
Take a regular tiling of the plane, apply a random colouring, and voila: a unique wallpaper, courtesy of the Python Imaging Library.
Using the Python Imaging Library to draw regular tilings of squares, triangles and hexagons.
Why py.test is my unit test framework of choice in Python.
A way to count records on the command-line.
PyCon had a dedicated quiet room for people to get some downtime, and I think it’s a great idea.
Live captioning of conference talks was an unexpected bonus at this year’s PyCon UK.
A pair of Python scripts I’ve been using to clean up my mess of directories.
A quick Python function to follow a redirect to its eventual conclusion.
A few tools and utilities I’ve been using to help clear disk space on my Mac.
A Python script I wrote that let me sends web pages from my Mac and my iPhone to my Kindle.
Testing with randomly generated examples can be a good way to uncover bugs in your code.
A Python script for finding 404 errors in my Apache web logs - and by extension, broken pages.
A quick python-smtplib wrapper for sending emails through Fastmail.
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.
Regexes have a reputation for being unreadable monsters, but it doesn’t have to be that way.
Using Alfred and a Python script to retrieve artwork from the iTunes, App and Mac App Stores.
If you want to create a file, but only if it doesn’t already exist, Python 3 has a helpful new file mode x
.
I have some TextExpander snippets that I use to cut out words I don’t want to write.
Updating the Skeletor clip loop chart for the 2015 Clip Show.
The Docker folder on your computer can quickly fill up space. Don’t forget to exclude it from backups.
A Python script for getting a list of URLs from Safari Reading List.
Playing with a tiny computer that runs Python.
A Bash function for quickly getting shell access to Docker containers.
A review of Effective Python, by Brett Slatkin.
A new version of my site for finding untagged Tumblr posts.
Configuring an IPython notebook server that is always running and easily accessible in Windows.
A Python script for non-destructive file copying/moving.
Another way to ignore untracked files in Git.
I made a clone of GitHub’s Contributions graph to use as a motivational tool.
Some advice for students sitting technical exams
A web app for applying syntax highlighting to code using the Pygments library.
A bookmarklet to add checkboxes to lists in the browser.
A standing desk that I built solely from IKEA parts.
Some thoughts on Marco Arment’s new podcast player, Overcast.
A script for automatically backing up bookmarks from Pinboard
Looking at whether Darwin ever missed out on birthday cake for pancakes
An essay about the number zero that I wrote for school.