Adam Johnson

Home | Blog | Training | Projects | Colophon


I have created or maintain a number of open source projects, this is a list of the most noteworthy.

Actively Maintained



Wrap a WSGI application in an AWS Lambda handler function for running on API Gateway or an ALB.

I wrote this whilst working at Time Out to help build an AWS Lambda based Django application. Existing solutions for the problem, such as Zappa, required complete control over the application deployment, whilst we already had a defined deployment pipeline using Ansible (roughly like this blog post). Therefore I created this open source layer to translate the AWS API Gateway requests back and forth to WSGI, allowing any standard Python web application to be deployed on Lambda.



A Django App that adds Cross-Origin Resource Sharing (CORS) headers to responses.

I took over maintenance of this from the creator Otto Yiu in 2016 and have shepherded it through many releases since. It adds CORS headers and is by far the most used package I maintain.



Set the draft security HTTP header Feature-Policy on your Django app.

I created this at Genus AI whilst working to get the web platform to an A+ score on It adds control over the header Feature-Policy, which at time of writing is still experimental.



Cross-database JSON field for Django models.

I took over maintenance of this from the creator Matthew Schinckel in 2019. I keep it "on life support" - working so that existing packages continue to function, but otherwise not updated. Django 3.0 comes with a native JSON field that replaces this package, thanks to the work of Google Summer of Code participant Sage Muhammad Abdullah.



Django-MySQL is a non-inventively named package that helps you use some MySQL/MariaDB-specific features in the world of Django.

This is my biggest self-made project, and what gained me the most attention from the Django community for my invitation as a core contributor.



Keep detailed records of the performance of your Django code.

This was based off some code I helped develop at YPlan, I was given permission to open source it, which I did at the PyCon UK 2017 sprints, although with some heavy re-factoring.



Let Django use settings from an arbitrary Python file instead of an importable module.

I wrote this as an investigation based on an idea posted by Jamesie Pic on the django-developers mailing list. It has quite a small surface area which makes it ideal for me to use as a maintenance "canary," for example when testing new Django versions.



An easy interface to query the EC2 metadata API, with caching.

I wrote this whilst at Time Out to fill in a gap where AWS' library boto provided an interface to the EC2 Metadata Service whilst the new version boto3 doesn't.



A flake8 plugin that helps you write better list/set/dict comprehensions.

I was given permission to write this as a plugin at YPlan through our "Friday Afternoon Time" initiative to find and fix some common performance-impacting comprehension issues we found across the YPlan codebase.



A flake8 plugin to ban type hints.

I wrote this whilst working on a codebase with type hints but no MyPy setup, which meant many of the hints had bitrotted to be fairly wrong. I figured it would be better to have no hints rather than wrong hints. Ultimately we ended up fixing the hints though, rather than banning them with this plugin.



A flake8 plugin that helps you write tidier imports.

Similar to the above, this was also created at YPlan to improve code quality, and later to ban some imports when migrating to Python 3.



Pack/unpack Python dicts into/out of MariaDB’s Dynamic Columns format.

I wrote this during PyCon UK 2016 as a way of supporting this JSON-like data type in Django-MySQL and got great support from David R. MacIver in the sprints testing it with Hypothesis. It was a fun exercise implementing a serializer/deserializer of a binary format in pure Python, optimizing it to run quickly, and discovering many bugs with Hypothesis' property-based testing. I wouldn't really recommend using Dynamic Columns these days though as MariaDB aren't actively developing the data type anymore because they added JSON support.



Run multiple python linters easily.

I made this to make my open source projects more consistent, by applying the same linters to the same sets of paths easily.



Patch the inner source of python functions at runtime.

This is a real hack, but we used it at YPlan to modify just a few of Django's innards without having to fork it. I gave a lightning talk on it at PyCon UK 2015. Since publishing, my ex-colleague Tom Grainger has fixed a lot of its edge cases.



A pytest fixture for testing flake8 plugins.

Used for testing my flake8 plugins such as flake8-comprehensions.



Pytest plugin to restrict the test types allowed.

A pretty niche Pytest plugin, we used this to defend the YPlan test suite against non-internal TestCase classes being inadvertently used in tests, which could break assumptions from our other testing tools.



Pytest plugin to check your TestCase classes call super in setUp, tearDown, etc.

Another plugin open sourced from YPlan. Django's TestCase does some magic to mean you don't need to call super() in your setUp(), but this can mean forgetting to call it when it's needed inheriting from subclasses of TestCase. This plugin runs a simple check that all setUp() (and related) methods call super(), regardless of whether it's needed.



Pytest plugin to randomly order tests and control random.seed.

I wrote this plugin at YPlan to improve the test suite and was given permission to open source it. I've written a blog post covering its history.

No Longer Maintained



A decorator to make a function accept keyword arguments only, on both Python 2 and 3.

This was useful for making functions more robust for callers by not accepting positional arguments. For example, it's used in the timezonefinder library to avoid users mixing the 'longitude' and 'latitude' arguments, which have varying conventions on order. I no longer maintain it because it's only needed on Python 2, because Python 3 has native syntax (def func(*, foo=1)).



Nose plugin to randomly order tests and control random.seed.

I wrote this plugin at YPlan to improve the test suite and was given permission to open source it. I've written a blog post covering its history and that of its successor pytest-randomly. I stopped maintaining it because Nose itself is no longer maintained. I recommend Pytest as an alternative.

Sound Resynthesis with a Genetic Algorithm


This is the source code for my final year thesis at Imperial College. I haven't tried to run it since 2011 but I put it on GitHub as some readers emailed me asking for it, and the thesis is in the repository too.