Submitting My First Patch to Python

Thursday February 20, 2014

I recently discovered my first bona fide bug in Python. I tracked down the issue, submitted a patch, which was thereafter accepted. I'm writing this blog post to show how easy it is to contribute to open source, how approachable the Python community is, and because I'm downright proud that I've now contributed to Python!

I technically mean the CPython implementation of the Python language wherever I say Python in this post. Ignore this comment if that means nothing to you.

Finding My First Python Bug

I was using the logging module for some code I was writing the other day. While the logging module is fantastic, it bothers me that logging messages use percent formatting and not bracket formatting. I wrote about my solution in another blog post. In the process however, I noted the following bug. I was running Python 3.3, and had the following behavior.

>>> import logging
>>> logging.basicConfig(style="{")
>>> logging.error("hello")
%(levelname)s:%(name)s:%(message)s

Of course, I'd expect ERROR:root:hello. I installed the absolute latest (at the time), 3.4beta2, and the problem persisted. Next step was to check the Python source. It's browseable online at hg.python.org. I downloaded it to my computer with

hg clone http://hg.python.org/cpython
hg update 3.3 # optional, will put you on 3.3 branch.
# note you would want to stay on bleeding edge to see if an issue persists

The install directions in the README are very straight-forward. It also has testing instructions which will be very useful later. Using Python 3.4.0b2 (v3.4.0b2:ba32913eb13e, Jan 5 2014, 11:02:52), my issue persisted. Now let's go track down the bug. I ran,

ack "def error\("

which I knew had to be in the logging module, and found the Lib/logging/__init__.py file. Jackpot. From my error, I knew that the %(levelname)s:%(name)s:%(message)s had to be some hardcoded constant that was not correctly set by the style keyword, so I then grepped for that string, found the BASIC_FORMAT constant, and then looked where it was referenced. Looking at the code, it is used as a default regardless of what the style parameter is, which was exactly my bug. I wrote a quick fix but then remembered I needed to prove I was right. Time for test cases!

In all honesty, this was probably harder than writing the patch itself. Since my behavior existed, and Python passes testing before release, that meant my specific bug wasn't already being tested for. I first found where the tests are based on a hunch:

find . -name testing #didn't find anything find . -name test #found
Lib/test, which seemed promising.

Indeed, there are a bunch of test_* files inside Lib/test, including test_logging.py. After taking some time to read existing test cases, I made a few test cases using the style keyword in basicConfig. From the readme, tests are run with make test. I ran the tests and confirmed that they all pass with my change. (It was an easy bug to fix, what can I say?) Awesome, now just need to ship it back to the Python community.

Submitting a Patch to Python

I went to bugs.python.org, created an account, and opened a bug - very easy and straight-forward. I was assigned Issue #20242. In the body, I wrote where I'd tested it (Python 3.3, 3.4b2, and the e7d922d8ee03 bleeding edge), exactly what the expected behavior was, and exactly the actual behavior. Then I jumped back to my local Python repository to create the patch, which is done with the following command.

hg diff | tee issue20242.patch # tee allows you to see the patch. also works: hg diff > issue20242.patch

I then attached that file to the bug report, and waited. Vinay Sajip, the maintainer of logging, responded 5 hours later (!!). Shortly thereafter, he made a tweak to my patch and then merged into Python core. Life goal of contributing to Python - mission accomplished!

Note if you want to find a first bug to tackle in Python, you can search open issues for the easy keyword - or follow this link.


Want to receive similar articles? (No spam, promise!)