Python Puzzle

Pedram Amini has got a pretty neat post up on reverse engineering the protocol for a USB device. If you haven’t seen it yet (it was linked from Slashdot) it’s worth reading. However, he includes some Python code which features a puzzling (to me, anyway) idiom, which took me a while to figure out.

How Does This Work?

Pedram’s code includes the following snippets:

class web_interface_handler (BaseHTTPServer.BaseHTTPRequestHandler):
	def __init__(self, request, client_address, server):
		BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, client_address, server)
		self.missile = None

and

class web_interface_server (BaseHTTPServer.HTTPServer):
	def __init__(self, server_address, RequestHandlerClass, missile):
		BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass)
		self.RequestHandlerClass.missile = missile

and

self.server = web_interface_server(('', 12345), web_interface_handler, self.missile)

What’s puzzling is that web_interface_server.__init__() sets a web_interface_handler class-level missile member, while web_interface_handler.__init__() sets an instance-level missile member (to None). Since the instance-level member will take precedence, how can a reference ever be made to the class-level missile member?

The Trick

The relevant code is in the BaseRequestHandler.__init__() function:

def __init__(self, request, client_address, server):
	self.request = request
	self.client_address = client_address
	self.server = server
	try:
		self.setup()
		self.handle()
		self.finish()
	finally:
		sys.exc_traceback = None    # Help garbage collection

This code is not overridden by the BaseHTTPRequestHandler class (which inherits from it, and from which web_interface_handler inherits). The significance of this code is that all the “work” done by a BaseRequestHandler instance is done when it is initialized. Since this initialization code is invoked by web_interface_server.__init__() before that function sets the instance-level missile member, the code can make reference to the class-level member.

I would categorize this as “non-obvious”.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in Python, Reverse Engineering. Bookmark the permalink.

Comments are closed.