Python 3.0a2 Released!

December 8, 2007

The second alpha release is out!

Python 3000 is getting real, real fast! :D

How to fly? import antigravity

December 6, 2007

xkcd is great!

Python 3.0a1 Released!

September 1, 2007

Yes, the first alpha release is out! :D

Congratulations to all python developers for this release!!!

Generating Maze using Python

August 2, 2007

Do you like mazes?

eriol@mornie:~$ python maze.py
+--+--+--+--+--+--+--+--+--+--+
|  |           |        |     |
+  +  +  +--+  +  +--+  +  +  +
|  |  |  |     |     |     |  |
+  +  +  +--+--+--+  +--+--+  +
|  |  |     |        |     |  |
+  +  +--+  +  +--+--+  +  +  +
|  |  |  |              |  |  |
+  +  +  +--+--+--+--+--+--+  +
|  |     |     |              |
+  +--+--+  +  +  +--+--+--+  +
|           |     |           |
+--+--+--+--+--+--+--+--+--+--+

After reading this good article, I decided to wrote some code to generate a perfect maze :D

The result is here: maze.py

As you can see, Depth-First Search is not a complex algorithm:

def create(self):
    cell_stack = []
    while self.visited_cells < self.total_cells:
        neighbors = self.find_neighbors_with_walls(self.current_cell)
        if neighbors:
            new_cell = random.choice(neighbors)
            self.current_cell.destroy_wall(cell=new_cell)
            cell_stack.append(self.current_cell)
            self.current_cell = new_cell
            self.visited_cells += 1
        else:
            self.current_cell = cell_stack.pop()

PyCon It

May 19, 2007

The first Python Conference in Italy will be held in Florence on June, the 9th and 10th.

If you love Python, you can't miss it! :)

RSS Feeds a Go-Go!

May 6, 2007

Finally I had the time to add RSS feeds! I hope you enjoy them :)

I'm not going to show some code because the documentation of Django's syndication feed framework is very good!

A reminder using GTK shaped window

April 26, 2007

The GNU/Linux User Group Catania meets the last thursday of every month. Usually a reminder is sent to mailing list by someone, but the other day a friend of mine started a «reminder contest».

I could not miss it :)

I wanted something unusual to set the timer, so I decided to use the Heaviside step function:

def u(t):
    if t < 0: return 0
    else: return 1

Obviously not a single unit step :)

def setTimer(t):
    return u(t) - 0.5 * u(t-TOTAL_HOURS-3) - 0.25 * u(t-TOTAL_HOURS-1)

In this manner the reminder is more dynamic: I use the return value to change the display's frequency.

It's time to write the GUI part!

A shaped window is simply a pixmap where the background pixels are transparent.

An image is worth a thousand words.

preminder.py screenshot

Yes, the pizza is our window :)

class PReminder:

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_POPUP)
        self.window.set_events(self.window.get_events() | gtk.gdk.BUTTON_PRESS_MASK)
        self.window.connect("button_press_event", self.hide)

        [...]

Using gtk.WINDOW_POPUP makes the window a popup so it will not have a titlebar. In addiction, the "button_press_event" signal is attached to self.hide callback to hide the reminder:

    def hide(self, *args):
        self.window.hide()
        if self.timerShow:
            gobject.source_remove(self.timerShow)

To masks out everything except for the image we have to use gtk.gdk.Window.shape_combine_mask:

self.window.shape_combine_mask(self.mask, 0, 0)

preminder.py screenshot

Changing the window itself as the time for the appointment approaches, can be useful.

    def draw(self):
        w = self.width, self.pangolayout.get_pixel_size()[0]
        offset = (max(w) - min(w)) / 2.

        if self.width < self.pangolayout.get_pixel_size()[0]:
            offset = -offset

        self.mask.draw_rectangle(self.bmgc,
                                True,
                                0, 0,
                                self.pieces * self.pixelpiece,
                                self.height)
        textwidth = self.pangolayout.get_pixel_size()[0]
        self.pixmap.draw_layout(self.bgc,
                                int(offset),
                                int(self.height / 2.),
                                self.pangolayout)
        self.mask.draw_layout(self.wmgc,
                            int(offset),
                            int(self.height / 2.),
                            self.pangolayout)

        self.image = gtk.Image()
        self.image.set_from_pixmap(self.pixmap, self.mask)
        self.image.show()

        self.window.shape_combine_mask(self.mask, 0, 0)

We have to change only the mask to obtain the desired effect.

preminder.py screenshot

Checking for last thursday of every month can be done in few line of code using dateutil:

    lastThursday = rrule.rrule(rrule.MONTHLY,
                               byweekday=rrule.TH(-1),
                               count=1)[0].date()

The complete checking method:

    def check(self):
        today = datetime.today()
        lastThursday = rrule.rrule(rrule.MONTHLY,
                                   byweekday=rrule.TH(-1),
                                   count=1)[0].date()

        if today.date() == lastThursday:
            now = today.time()
            if START_CHECK_HOUR <= now <= FINISH_CHECK_HOUR:
                timerModulator = setTimer(now.hour - START_CHECK_HOUR.hour)
                timer = int(timerModulator * 60 * 60 * 1000)
                self.setText(DIPLAYING_TEXT)
                self.setPiece(now.hour - START_CHECK_HOUR.hour)

                self.show()
                self.timerShow = gobject.timeout_add(AUTO_HIDE_AFTER * 1000,
                                                     self.hide)
        else:
            timer = CHECK_TIMER * 1000

        self.timerID = gobject.timeout_add(timer, self.check)

You can download the complete source code here: preminder-0.1.zip

Playing with ctypes and libcaca

March 25, 2007

ctypes is a foreign function interface for Python. It allows to call functions in dlls/shared libraries and access and manipulate C data types in Python: you can use it to wrap libraries in pure Python. It is included in Python 2.5 standard library.

I want to code a funny example using it, so I will show how to make a snake game using libcaca.

libcaca is an ascii art library like AAlib, but it has some cool features:

  • Unicode support
  • 2048 colours
  • dithering of colour images
  • advanced text canvas operations (blitting, rotations)

snake.py screenshot

First of all we have to load libcaca, I use Linux so I will call libcaca.so.0:

import ctypes as C

lcaca = C.cdll.LoadLibrary('libcaca.so.0')

Now you can access libcaca's functions from Python :)

Create canvas and display for our snake is very easy:

cv = lcaca.cucul_create_canvas(CANVAS_WIDTH, CANVAS_HEIGHT)
dp = lcaca.caca_create_display(cv)
lcaca.caca_set_display_title(dp, "snake.py - playing with ctypes and libcaca")

To get events from keyboard call caca_get_event:

lcaca.caca_get_event(dp, 0x0001, C.byref(event), 0)

Where event is a caca_event structure. We need it because if not null, it will be filled with information about the event received.

How define event? Simply like that:

class MOUSE(C.Structure):
    _fields_ = [('x', C.c_uint),
                ('y', C.c_uint),
                ('button', C.c_uint)]

class RESIZE(C.Structure):
    _fields_ = [('w', C.c_uint),
                ('h', C.c_uint)]

class KEY(C.Structure):
    _fields_ = [('ch', C.c_uint),
                ('utf32', C.c_ulong),
                ('utf8', C.c_char_p * 8)]

class ev(C.Union):
    _fields_ = [('type', C.c_uint),
                ('mouse', MOUSE),
                ('resize', RESIZE),
                ('key', KEY)]    

event = ev()

Now we can code the snake class:

class Snake(object):

    def __init__(self, center_point, length):

        self.head = center_point
        self.body = []

        for y in xrange(self.head[1] + 1, self.head[1] + length + 1):
            self.body.append((self.head[0], y))

    def move(self, direction):

        phead = tuple(self.head)

        if direction == 'UP':
            self.head[1] -=1
        elif direction == 'DOWN':
            self.head[1] +=1
        elif direction == 'LEFT':
            self.head[0] -=1
        elif direction == 'RIGHT':
            self.head[0] +=1

        self.body = [phead] + self.body[:-1]

    def grow(self):
        self.body += [tuple(self.head)] * 2

    def draw(self):
        global cv
        lcaca.cucul_set_color_ansi(cv, 0x05, 0x00)

        for p in self.body:
            lcaca.cucul_put_char(cv, p[0], p[1], ord('o'))
        lcaca.cucul_set_color_ansi(cv, 0x02, 0x00)
        lcaca.cucul_put_char(cv, self.head[0], self.head[1], ord('@'))
        lcaca.caca_refresh_display(dp)

And the target class:

class Target(object):

    def __init__(self):
        self.total = 0

    def random(self, width, height):
        self.x = int(random.uniform(1, width))
        self.y = int(random.uniform(1, height))
        self.value = random.choice(range(1,10))

    def sum(self):
        self.total += self.value

    def draw(self):
        global cv
        lcaca.cucul_set_color_ansi(cv, 0x03, 0x00)
        lcaca.cucul_put_char(cv, self.x, self.y, ord(str(self.value)))
        lcaca.caca_refresh_display(dp)

We are ready for the mainloop ;)

while True:
    while lcaca.caca_get_event(dp, 0x0001, C.byref(event), 0):
        if event.key.utf32 == 113: # 'q' pressed
            sys.exit()
        elif event.key.utf32 == UP:
            d = 'UP'
        elif event.key.utf32 == DOWN:
            d = 'DOWN'
        elif event.key.utf32 == LEFT:
            d = 'LEFT'
        elif event.key.utf32 == RIGHT:
            d = 'RIGHT'

    try:
        s.move(d)
    except NameError:
        pass

    if (tuple(s.head) in s.body[1:] or
        not 0 < s.head[0] < CANVAS_WIDTH - 1 or
        not 0 < s.head[1] < CANVAS_HEIGHT - 1):
        print 'Game Over!'
        print 'Total score:', t.total
        sys.exit()
    elif tuple(s.head) == (t.x, t.y):
        t.sum()
        t.random(CANVAS_WIDTH - 2, CANVAS_HEIGHT - 2)
        s.grow()

    lcaca.cucul_clear_canvas(cv)
    draw_border()
    s.draw()
    t.draw()
    time.sleep(0.1)

The complete example is here: snake.py

Update 2007/10/20:

Sam Hocevar pointed me about importance of checking caca_get_event's return value, otherwise from time to time invalid keys are read. Thank you, Sam!

My blog with Django!

March 8, 2007

At the end I made it!

Django is great! You can build your own blog in few minutes! :)

Many thanks to Sal Zeta for his help with this site's design!

Storing binary data in SQLite

January 10, 2007

Storing images into a database is not common, usually you store only the file name, but sometimes it can be useful. Think you must log the position of several objects on a map. You can store the map and the logs in different files, but if your users have to share map and logs and they are not geek people, it can be a serious problem.

Remember that, of course, store files into a database makes the storage space more expensive. However, if you have to store one or few files it's not a big problem :-)

Consider the following database schema:

CREATE TABLE map (
    name varchar(20) NOT NULL PRIMARY KEY,
    image_file blob NOT NULL
);

CREATE TABLE logs (
    -- <your logs schema here>
);

Let's start to code:

import Image
import StringIO
from pysqlite2 import dbapi2 as sqlite

Storing an image into the database is very simple:

def storeInDatabase(cur, image_name, data):

    cur.execute("INSERT INTO map (name, image_file) values (?, ?)",
                (image_name, sqlite.Binary(data))
               )
    con.commit()

N.B. As said by Fredrik Lundh, SQLite 3.0 has a limitation of 1 MB for each row of data, and the database uses NUL bytes to separate columns in the storage.

Retrieve the previously image stored is simple too:

def retrieveFromDatabase(cur, image):

    cur.execute("SELECT image_file FROM map WHERE name = ?", (image,))
    img = cur.fetchone()[0]
    return StringIO.StringIO(img)

I use StringIO.StringIO because cur.fetchone()[0] returns a buffer-object and I want a file-object instead ;)

You can test with:

if __name__ == '__main__':

    IMAGE = 'Surf.jpg'

    i = open(IMAGE, 'rb')
    idata = i.read()
    i.close()

    con = sqlite.connect('blob.db')
    cur = con.cursor()

    try:
        storeInDatabase(cur, image_name=IMAGE, data=idata)
    except sqlite.IntegrityError:
        print 'You have stored this map already'

    img = retrieveFromDatabase(cur, IMAGE)

    cur.close()

    Image.open(img).show()

The whole example, blobexample.py

Python in a Nutshell

December 19, 2006

Today, when I arrived at home I saw a package on the table in the living room:

Python in a Nutshell

My first purchase on Amazon! :)