Richard Jones' Log

Sat, 27 Mar 2010
A Bit Of Cheese

I'm starting a new experiment: the Bit Of Cheese blog. It's going to highlight one package in the Cheese Shop (aka. Python Package Index) per week. Well, it might be more frequent, it might be less. Depends on whether anything takes my fancy :)

http://bitofcheese.blogspot.com/

The first module implements infix regular expressions. It's way more fun than that sounds.

category: Python | permanent link
Fri, 26 Mar 2010
Mouse warping with my MacBook + DVI

For future reference when I plug my MacBook into my LG monitor using DVI and see my mouse jumping all over the place I need to delete /System/Library/Extensions/AppleUpstreamUserClient.kext.

DRM / HDCP ROCKS, YEAH!

Fri, 26 Mar 2010
More on html.py and Python 3 compatibility

On the train home I realised that I can make html.py compatible with Python 2 and 3 without needing 2to3 translation. Out goes setuptools and the other yucky code :-)

category: Python | permanent link
On packages supporting Python 2 and 3

My html.py package (whose syntax "really could not be any better" in the words of one user) now supports unicode under Python 2. To achieve this I now need to produce a translated version of the module for Python 3 compatibility (unicode strings are u'text' in Python 2 which is a syntax error in Python 3).

So I'd heard that distutils somehow automagically supported running lib2to3 for Python 3. That's close to the truth. The distribute package supports installing to both Python 2 and Python 3 using lib2to3 to create the Python 3 version.

The trick is to use "from setuptools import setup" instead of "from distutils.core import setup" and then include "use_2to3 = True" in your setup() arguments. Well, that's most of the trick. As it turns out I also had to:

  1. Add "setuptools.use_2to3_on_doctests = False" because my docstrings have "print" statements in them (they're not actually doctests but the 2to3bot doesn't know that). Without that variable being set I would get a strange error deep in the 2to3 code.
  2. Run "python3 setup.py build install" otherwise the Python 2 code would still be installed. It seems "build" isn't actually run for a simple Python-only install. Took me a while to figure that one out.

The upshot is it works in the end and I hope that maybe this post can help others.

category: Python | permanent link
Sat, 20 Mar 2010
PyWeek 10 theme voting open!

PyWeek theme voting has commenced! If you haven't already done so you have one week to re-organise your calendar so you can write a game during the 10th Python Game Programming Challenge. The potential themes this time are:

  • Eleventh
  • Canine
  • Wibbly-wobbly
  • Rose
  • Screwdriver

(As always, there's a meta-theme...)

As an aside I just discovered (via piman in the #pyweek IRC channel) Doryen, a fairly awesome library for writing console games which seems to have quite good Python support and active developers using it.

category: Python | permanent link
Mon, 15 Mar 2010
A simple asyncore "echo server" example

Tonight I wanted a simple asyncore echo server example for my lecture notes and couldn't immediately find one. Doug Helman has a more complex one in his asyncore Module Of The Week post, but I wanted Just The Basics. So I read up a little and wrote one :-)

First the server:

import asyncore, socket

class Server(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(('', port))
        self.listen(1)

    def handle_accept(self):
        # when we get a client connection start a dispatcher for that
        # client
        socket, address = self.accept()
        print 'Connection by', address
        EchoHandler(socket)

class EchoHandler(asyncore.dispatcher_with_send):
    # dispatcher_with_send extends the basic dispatcher to have an output
    # buffer that it writes whenever there's content
    def handle_read(self):
        self.out_buffer = self.recv(1024)
        if not self.out_buffer:
            self.close()

s = Server('', 5007)
asyncore.loop()

And the client:

import asyncore, socket

class Client(asyncore.dispatcher_with_send):
    def __init__(self, host, port, message):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        self.out_buffer = message

    def handle_close(self):
        self.close()

    def handle_read(self):
        print 'Received', self.recv(1024)
        self.close()

c = Client('', 5007, 'Hello, world')
asyncore.loop()

When run the server should display:

Connected by ('127.0.0.1', 56757)

(or similar - the port number will vary) and the client should display:

Received 'Hello, world'

It was actually pretty easy to write, and kinda fun.

category: Python | permanent link
Fri, 05 Mar 2010
10th Python Game Programming Challenge in three weeks

The 10th Python Game Programming Challenge (PyWeek) is coming. It'll run from the 28th of March to the 4th of April.

The PyWeek challenge:

  1. Invites entrants to write a game in one week from scratch either as an individual or in a team,
  2. Is intended to be challenging and fun,
  3. Will hopefully increase the public body of game tools, code and expertise,
  4. Will let a lot of people actually finish a game, and
  5. May inspire new projects (with ready made teams!)

In honor of the 10th challenge I've finally brought the website out of the 80s :-) ...

BeforeAfter
category: Python | permanent link