Home | Blog | Projects
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.
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
which at time of writing is still experimental.
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
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 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
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
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.
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
This plugin runs a simple check that all
setUp() (and related) methods call
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.
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
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
I stopped maintaining it because Nose itself is no longer maintained.
I recommend Pytest as an alternative.
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.