Blogs
Typically I read at least one news story a day that irritates me, usually I either don't care enough to gripe about them further, or I forget. After griping at ET about driving in the car with a phone in her hand, I remembered an article I read the SF Streets Blog titled: "Advocates Concerned That Cyclists Are Included in Distracted Driving Bill" (link)
One of the choice quotes from the article being:
The California Bicycle Coalition (CBC), which was an early supporter of the original distracted driving legislation, was not thrilled about the inclusion of cyclists in the bill. CBC Communications Director Jim Brown said that he was confused about the motivation for extending the same level of fines to cyclists, particularly absent data showing distracted cycling as a public safety hazard.
"The consequences of a distracted driver are considerably more serious than the consequences of distracted cycling," said Brown, adding that safe riding should be encouraged at all times and that talking on a cell phone or any other practice that distracted a cyclist from riding would not be advisable.
As a member of the San Francisco Bicycle Coalition, I'm partially annoyed by Mr. Brown's comments, but I don't particularly care. Reading further through the article, I found this:
Andy Thornley, Program Director for The San Francisco Bicycle Coalition, agreed with Winter that lumping cyclists with motorists in this law was not good policy. While the SFBC "teaches and preaches safe, respectful, and mindful bicycling," said Thornley, "we're very leery of any equivalence of penalty when punishing a guilty cyclist or driver for the same offense."
"Even worse, we wonder whether bicyclists would be cited more often than motorists because it's so much easier to spot someone texting while pedaling," he added. "It's already a problem of perception that individual bicycle riders seem to be noticed being naughty more than motorists, comfortably anonymous within their glass and steel boxes."
What a hypocrite! Riding your bike while on the phone or worse, texting is just as stupid as some of the no-helmet, no-light nonsense I was incensed over a few weeks ago, but the fact that these two gentlemen from Bike Coalitions want preferential treatment for cyclists in the most idiotic way possible blows my mind. To be honest, I'm entirely in favor of bicyclists being cited more often than motorists for breaking the law (running red lights or not using signals comes to mind).
This kind of no-distractions law makes a lot of sense to me, and should be applied to just about anybody operating a moving vehicle, bikes, trikes, motorcycles, mopeds, cars, tractors, law mowers, you name it. If you are operating a vehicle distracted you raise your chances of hurting yourself or others on public roads (ever been hit while walking by a cyclist?).
Inside of the San Francisco cycling community, I think we can do our part by shunning or otherwise pushing cyclists into light posts who are on their cell phones while riding. They are clearly morons and in my opinion the CBC or the SFBC has no place defending their idiocy.
Writing software is an outlet for artistic expression to many people, myself included. For me, solving problems involves a good deal of creativity not only in the actual solution but also in the manipulating several moving parts in order to fit the solution into an existing code-base. Combining this creative outlet with a beautiful language, such as Python results in some developers writing code that holds an masterpiece-level of beauty to them, to the untrained eye one might look at a class and think nothing of it, but to the author of that code, it might represent a substantial amount of work and personal investment.
Like art, sometimes the beauty is entirely subjective. there has been times where I've been immensely pleased with one of my creations, only to turn to wholly unimpressed Dave. Managing or working with any team of highly motivated, passionate and creative developers presents this problem, as a group: how can you objectively judge code while preserving the sense of ownership by the author?
Dealing with statics in Python is something that has bitten me enough times that I have become quite pedantic about them when I see them. I'm sure you're thinking "But Dr. Tyler, Python is a dynamic language!", it is indeed, but that does not mean there aren't static variables.
The funny thing about static variables in Python, in my opinion, once you understand a bit about scoping and what you're dealing with, it makes far more sense. Let's take this static class variable for example:
>>> class Foo(object): ... my_list = [] ... >>> f = Foo() >>> b = Foo()
You're trying to be clever, defining your class variables with their default variables outside of your __init__ function, understandable, unless you ever intend on mutating that variable.
>>> f.my_list.append('O HAI') >>> print b.my_list ['O HAI'] >>>
Still feeling clever? If that's what you wanted, I bet you do, but if you wanted each class to have its own internal list you've inadvertantly introduced a bug where any and every time something mutates my_list, it will change for every single instance of Foo. The reason that this occurs is because my_list is tied to the class object Foo and not the instance of the Foo object (f or b). In effect f.__class__.my_list and b.__class__.my_list are the same object, in fact, the __class__ objects of both those instances is the same as well.
>>> id(f.__class__) 7680112 >>> id(b.__class__) 7680112
When using default/optional parameters for methods you can also run afoul of statics in Python, for example:
>>> def somefunc(data=[]): ... data.append(1) ... print ('data', data) ... >>> somefunc() ('data', [1]) >>> somefunc() ('data', [1, 1]) >>> somefunc() ('data', [1, 1, 1]) >>>
This comes down to a scoping issue as well, functions and methods in Python are first-class objects. In this case, you're adding the variable data to the somefunc.func_defaults tuple, which is being mutated when the function is being called. Bad programmer!
It all seems simple enough, but I still consistently see these mistakes in plenty of different Python projects (both pony-affiliated, and not). When these bugs strike they're difficult to spot, frustrating to deal with ("who the hell is changing my variable!") and most importantly, easily prevented with a little understanding of how Python scoping works.
PYRAGE!
A few weekends ago ET and I had some engagement photos taken, I'm told this is normal, by the husband-and-wife team from Tibidabo Photography, Bob and Becky. The duo met us at one of my favorite spots in San Francisco: Duboce Ave and Buena Vista Ave East after which we ran around in Buena Vista Park taking a few shots, then down to Baker Beach. As much as I hate having my picture taken, they did a wonderful job and grabbed some really stellar shots.

My "roots" in the open source community come from the BSD side of the open source spectrum, my first major introduction being involvement with FreeBSD and OpenBSD. It is not surprising that my licensing preferences fall on the BSD (2 or 3 clause) or MIT licenses, the MIT license reading as follows:
Copyright (c) [year] [copyright holders]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
I bring the subject up because I wanted to address a brief "kerfuffle" that occurred recently on the Eventlet mailing list with the maintainer of gevent, a fork/rewrite of Eventlet. Both projects are MIT licensed which gives anybody that would like to fork the source code of either project a great deal of leeway to hack about with the code, commercialize it, etc.
In my spurious free time I maintain a few Python modules (py-yajl, Cheetah, PyECC) and am semi-involved in a couple others (Django, Eventlet), only one of which properly supports Python 3. For the uninitiated, Python 3 is a backwards incompatible progression of the Python language and CPython implementation thereof, it's represented significant challenges for the Python community insofar that supporting Python 2.xx, which is in wide deployment, and Python 3.xx simultaneously is difficult.
As it stands now my primary development environment is Python 2.6 on Linux/amd64, which means I get to take advantage of some of the nice things that were added to Python 3 and then back-ported to Python 2.6/2.7. Regular readers know about my undying love for Hudson, a Java-based continuous integration server, which I use to test and build all of the Python projects that I work on. While working this weekend I noticed that one of my C-based projects (py-yajl) was failing to link properly on Python 2.4 and 2.5. It might be easy to cut-off support for Python 2.4, which was first released over four years ago, there are still a number of heavy users of 2.4 (such as Slide), in fact it's still the default /usr/bin/python on Red Hat Enterprise Linux 5. What makes this C-based module special, is that thanks to Travis, it runs properly on Python 3.1 as well. Since the Python C-API has been fairly stable through the 2 series into Python 3, maintaining a C-based module that supports multiple versions of Python.
In this case, it's as easy as some simple pre-processor definitions:
#if PY_MAJOR_VERSION >= 3 #define IS_PYTHON3 #endif
Which I can use further down the line to modify the handling some of the minor internal changes for Python 3:
#ifdef IS_PYTHON3 result = _internal_decode((_YajlDecoder *)decoder, PyBytes_AsString(bufferstring), PyBytes_Size(bufferstring)); Py_XDECREF(bufferstring); #else result = _internal_decode((_YajlDecoder *)decoder, PyString_AsString(buffer), PyString_Size(buffer)); #endif
Not particularly pretty but it gets the job done, supporting all major versions of Python.
Python on Python
Writing modules in C is fun, can give you pretty good performance, but is not something you would want to do with a large package like Django (for example). Python is the language we all know and love to work with, a much more pleasant language to work with than C. If you build packages in pure Python, those packages have a much better chance running on top of IronPython or Jython, and the entire Python ecosystem is better for it.
A few weeks ago when I started to look deeper into the possibility of Cheetah support for Python 3, I found a process riddled with faults. First a disclaimer, Cheetah is almost ten years old; it's one of the oldest Python projects I can think of that's still chugging along. This translates into some very old looking code, most people who are new to the language aren't familiar with some of the ways the language has changed in the past five years, let alone ten.
The current means of supporting Python 3 with pure Python packages is as follows:
- Refactor the code enough such that
2to3can process it - Run 2to3 over the codebase, with the
-woption to literally write the changes to the files - Test your code on Python 3 (if it fails, go back to step 1)
- Create a source tarball, post to PyPI, continue developing in Python 2.xx
I'm hoping you spotted the same problem with this model that I did, due to the reliance on 2to3 you are now trapped into always developing Python targeting Python 2. This model will never succeed in moving people to Python 3, regardless of what amazing improvements it contains (such as the Unladen Swallow work) because you cannot develop on a day-to-day basis with Python 3, it's a magic conversion tool away.
Unlike with a C module for Python, I cannot #ifdef certain segments of code in and out, which forces me to constantly use 2to3 or fork my code and maintain two separate branches of my project, duplicating the work for every change. With Python 2 sticking around on the scene for years to come (I don;t believe 2.7 will be the last release) I cannot imagine either of these workflows making sense long term.
At a fundamental level, supporting Python 3 does not make sense for anybody developing modules, particularly open source ones. Despite Python 3 being "the future", it is currently impossible to develop using Python 3, maintaining support for Python 2, which all of us have to do. With enterprise operating systems like Red Hat or SuSE only now starting to get on board with Python 2.5 and Python 2.6, you can be certain that we're more than five years away from seeing Python 3 installed by default on any production machines.





