Navigation

home code debian images resume weblog wiki

Older news:

Feb 18, 2005:
Mixing whitespace
Jan 10, 2005:
The difference between dogs and cats
Dec 22, 2004:
Sunrise in winter
Dec 12, 2004:
New site layout
Winter in Rotterdam
Cyprus (November 2004)
Nov 26, 2004:
Python decorators

Browse:


Abstract methods in python (4)/programming

Posted on 2004-01-26 by ivo :: /programming :: link

Well, that was interesting. Rigel pushed me to submit the code to the ASPN cookbook, which I did. Then he told me that my entry was included in today's issue of daily python (apparently they do that to all entries from the ASPN cookbook). Incidentally I fixed a few minor bugs in the code. The complete code is downloadable here: abstractmethods.py.

Abstract methods in python (3)/programming

Posted on 2004-01-22 by ivo :: /programming :: link

Ok, here is the same code as in the last two articles, this time with more explanation. The point is that python doesn't have a notion of “abstract methods.” Abstract methods are part of an base class that defines an interface, without any code. Abstract methods can't be called directly, because they don't contain any code in their definition.

In the definition of the base class, you may want to include a specific method that is part of the interface, but the specific implementation is still unknown. A popular example seems to be the drawing of a point or a line in a graphical application.

The classes Point and Line share several implementation details, but differ on other. In particular, the way they are drawn is completely different (you will want to optimize the drawing of a line). Suppose these two classes are derived from the same class, Object. It is possible to separate the implementation of the method draw of these two classes, while draw can still be called from the base class Object.

The text below will introduce some utility classes that make this possible.

The goal of this article is defining a way to make it possible to define classes such as the following (not yet paying attention to the proper syntax):

class Object (object):
    abstract draw()

    def update(self):
        self.draw()

class Point (Object):
    def draw(self):
        ...
    ...

class Line (Object):
    def draw(self):
        ...
    ...

The method draw of the class Object cannot be implemented, because the concept of ‘drawing’ a generic object is undefined. Other methods, such as the update above may want to use draw anyway, because it is part of the specification for the Object class and its descendants.

The implementation in python exists of two parts:

  1. The definition of a way to declare abstract methods, and
  2. a way to restrict the creation/usage of these abstract classes.

First the declaration part. To declare an abstract method, we can use callable class variables:

class Object (object):
    draw = AbstractMethod()

When somebody tries to call Object.draw(), an exception will be raised. But as long as methods in Object use self.draw(), they will actually use Point.draw(), because self will be of type Point.

If AbstractMethod is a class, draw will be an instance of this class, so we can make draw callable, and raise a proper exception (TypeError or NotImplementedError for example) if it is called instead of an implementation in one of the descendant classes.

class AbstractMethod (object):
    def __init__(self, func):
        self._function = func

    def __get__(self, obj, type):
        return self.AbstractMethodHelper(self._function, type)

    class AbstractMethodHelper (object):
        def __init__(self, func, cls):
            self._function = func
            self._class = cls

        def __call__(self, *args, **kwargs):
            raise TypeError('Abstract method `' + self._class.__name__ \
                            + '.' + self._function + '\' called')

So now we can declare Object as follows:

class Object (object):
    draw = AbstractMethod('draw')
    def update(self):
        self.draw()

If we tried to call Object().draw() directly, we get an exception:

>>> Object().draw()
TypeError: Abstract method `Object.draw' called

The same happens with Object().update():

>>> Object().update()
TypeError: Abstract method `Object.draw' called

If we implement a descendant class which implements draw, there is no error.

class Point (Object):
    def draw(self):
        print 'Point.draw called'

(Note that there is no definition for update in Point, it uses the implementation inherited from Object.)

>>> Point().update()
Point.draw called

Of course, we shouldn't be getting an exception at all if we try to call an abstract function. It should be impossible to create an instance of a class that has one or more abstract methods in its definition (either declared directly in the class definition, or implicitly via inheritance without overriding it with a real method). We can solve this pretty easily by declaring a metaclass that checks if there are any abstract methods in a class definition, and raise an exception if there are.

class Metaclass (type):
    def __init__(cls, name, bases, *args, **kwargs):
        type.__init__(cls, name, bases, *args, **kwargs)
        cls.__new__ = staticmethod(cls.new)

        ancestors = list(cls.__mro__)
        ancestors.reverse()  # Start with __builtin__.object
        for ancestor in ancestors:
            for clsname, clst in ancestor.__dict__.items():
                if isinstance(clst, AbstractMethod):
                    abstractmethods.append(clsname)
                else:
                    if clsname in abstractmethods:
                        abstractmethods.remove(clsname)

        abstractmethods.sort()
        setattr(cls, '__abstractmethods__', abstractmethods)

    def new(self, cls):
        if len(cls.__abstractmethods__):
            raise NotImplementedError('Can\'t instantiate class `' + \
                                      cls.__name__ + '\';\n' + \
                                      'Abstract methods: ' + \
                                      ", ".join(cls.__abstractmethods__))

        return object.__new__(self)

The definition of Object becomes:

class Object (object):
    __metaclass__ = Metaclass
    draw = AbstractMethod('draw')

This has the final result:

>>> Point().update()
Point.draw called
>>> Object().update()
NotImplementedError: Can't instantiate class `Object';
Abstract methods: draw

The error can be caught much earlier on when the exception is raised when the class is instantiated.

There is one remaining issue, which is that descendant classes of Object which don't implement all the abstract methods defined in Object can also not be instantiated:

>>> class FooClass (Object):
...     pass
>>> FooClass()
NotImplementedError: Can't instantiate class `FooClass';
Abstract methods: draw

The code in the last article didn't do this, but the code in this article checks all ancestors for any abstract methods that haven't been implemented.

Abstract methods in python (2)/programming

Posted on 2004-01-22 by ivo :: /programming :: link

The fun never stops!

class Object (object):
    __metaclass__ = Metaclass
class Metaclass (type):
    def __init__(cls, name, bases, *args, **kwargs):
        type.__init__(cls, name, bases, *args, **kwargs)
        cls.__new__ = staticmethod(cls.new)

        abstractmethods = []
        for clsname, clst in cls.__dict__.items():
            if isinstance(clst, AbstractMethod):
                abstractmethods.append(clsname)

        abstractmethods.sort()
        setattr(cls, '__abstractmethods__', abstractmethods)

    def new(self, cls):
        if len(cls.__abstractmethods__):
            raise NotImplementedError('Can\'t instantiate class `' + \
                                      cls.__name__ + '\';\n' + \
                                      'Abstract methods: ' + \
                                      ", ".join(cls.__abstractmethods__))

        return object.__new__(self)
class MyAbstractObject (Object):
    foo = AbstractMethod('foo')

class MyObject (MyAbstractObject):
    def foo(self):
        print 'foo'

def main():
    a = MyObject()
    a.foo()
    b = MyAbstractObject()
    b.foo()
> python test.py
foo
Traceback (most recent call last):
  File "test.py", line 25, in ?
    main()
  File "test.py", line 21, in main
    b = MyAbstractObject()
  File "/home/ivo/p/python/abstract-classes/Metaclass.py", line 29, in new
    raise NotImplementedError('Can\'t instantiate class `' + \
NotImplementedError: Can't instantiate class `MyAbstractObject';
Abstract methods: foo

Abstract methods in python/programming

Posted on 2004-01-22 by ivo :: /programming :: link

Classes are fun!

class AbstractMethod (object):
    def __init__(self, func):
        self._function = func

    def __get__(self, obj, type):
        return self.AbstractMethodHelper(self._function, type)

    class AbstractMethodHelper (object):
        def __init__(self, func, cls):
            self._function = func
            self._class = cls

        def __call__(self, *args, **kwargs):
            raise TypeError('Abstract method `' + self._class.__name__ \
                            + '.' + self._function + '\' called')
class MyAbstractObject (object):
    foo = AbstractMethod('foo')

class MyObject (MyAbstractObject):
    def foo(self):
        print 'foo'

def main():
    a = MyObject()
    a.foo()
    b = MyAbstractObject()
    b.foo()
> python test.py
foo
Traceback (most recent call last):
  File "test.py", line 25, in ?
    main()
  File "test.py", line 22, in main
    b.foo()
  File "/home/ivo/p/python/abstract-classes/AbstractMethod.py", line 19, in __call__
    raise TypeError('Abstract method `' + self._class.__name__ \
TypeError: Abstract method `MyAbstractObject.foo' called

Debian desktop background/debian

Posted on 2004-01-19 by ivo :: /debian :: link

Most desktop backgrounds are way too bright for my taste, and the ones focused on Debian are no exception. I created a simple and dark image to put on my desktop. You can see it in action in this screenshot.

the background

Dependencies on libgnutls5/debian

Posted on 2004-01-16 by ivo :: /debian :: link

The number of packages that depend on libgnutls5 has dropped considerably since the introduction of libgnutls7. There are currently 22 binary packages that depend on libgnutls5 in any architecture, and only five source packages that have an explicit build dependency on libgnutls5-dev.

The ultimate goal is to get libgnutls5 and libopencdk4 out of sarge before it is released.

I am sending email to the maintainers of these packages, so please, if you maintain one of these, change your build dependency to libgnutls7-dev | libgnutls-dev.

anubis
Maintainer has promised an upload this weekend.
elinks
Build-Depends on libgnutls7-dev|libgnutls5-dev. Maintainer notified.
gtklp
Build-Depends on libgnutls-dev|libgnutls5-dev. Maintainer notified.
lynx
Maintainer notified.
thy
Maintainer notified.

Status updates can be found here.

A truly free mind/programming

Posted on 2004-01-15 by ivo :: /programming :: link

When complaining on IRC about the time I spent on writing articles for this weblog, someone jokingly said that I should put a PayPal banner on my website. But I tend to hate paypal.

But another thought struck me then, which is that I don't want to recieve any money for the work that I do for this site. All the texts on this site are licensed for redistribution, as long as you give me credit, and keep the copyright notices intact (details). I don't do this because I'm so philanthropic, I just want anyone to be able to take my texts or code or images or anything else, and modify it for their needs and redistribute the result.

Basically this has happened long before I came into contact with the free software movement. I had written some code that I wanted to give away to friends. I saw that they were using it, which felt good. But I was young and naive at that time.

Later I found out about the existence of Linux, and the idea of choice appealed to me. I installed it, and gradually became aware of all the projects that surrounded it: the GNU Project, the Free Software Foundation (FSF), the League for Programming Freedom. As time went on, I came into contact with GIMP. To install it, you needed lesstif. I had heard of Motif before, and I thought it was good that there was a project that wanted to provide a free version of it. That lesstif has been licensed under a non-free license for a long time didn't bother me then. It was better than nothing.

Gradually I became aware of the real reason for the existence of organizations such as the FSF. I started releasing my own code under licenses such as the GNU General Public License (GNU GPL).

As I started to become more involved in the free software movement, starting with the GNU Translation Project, I came into contact with the real values of licensing code under free licenses, and I learned to understand not only the virtues, but also the responsibilities that come with code released under the GPL. Being a user of (almost) only free software, I was already aware of the expectations of other programmers, and I learned to apply those feelings to my own software.

My code became free, and my mind followed. It was a gradual process, but I can't say I'm sorry it happened. I'm glad. But paypal still sucks.

Scientific methods/science

Posted on 2004-01-15 by ivo :: /science :: link

Introduction

Usually, when people ask me if I have a religion, or if I believe in something, I usually answer “no”. My parents are both atheists, I wasn't baptized. When I have to put a little more nuance in that, it becomes “I believe in Nature.” But I don't mean Nature to be some higher order being like some people see mother nature. So I change it to “I believe in science.”

“But there are some things that science can't explain.” (usually they refer to the metaphysical) — bzzt, wrong. There are things that science hasn't yet had a chance to explain. (And there are things that science explains, but nobody wanted to know about.)

There are people who don't know how to handle science, there are those who don't know how to handle scientific results, and there are those who just Do Not Get It. There are a lot of generally accepted principles that apply to any scientific research. These principles have influenced the way that scientists do research since the middle ages, when research in western Europe was generally intended to support the Catholic Church in their doctrine.

Read more…

gnutls10 1.0.4-1 finally uploaded/debian

Posted on 2004-01-14 by ivo :: /debian :: link

I have just uploaded gnutls10 1.0.4-1 in all its glory to unstable. It contains new binary packages, so it'll take a while before it shows up in incoming. Let's hope it's still in time to get released with sarge…

The only thing that was keeping it is a solution to bug #224846. I was unable to reproduce it for a while, until I found the culprit: it turned out that the chroot that I'm using to build packages was contaminated with latex2html and a few other tex-related packages. Removing them made me able to fix it quickly. Instead of rebuilding the documentation, I'm now just using the upstream version of the postscript file.

For those who want to test it before it hits incoming, and I know there are some of you who do, you can also get it from my package archive.

Blosxom plugin: cvs/programming/blosxom

Posted on 2004-01-12 by ivo :: /programming/blosxom :: link

I was looking for a way to have the $Revision: 1.1 $ that CVS inserts in the theme file recognized and/or ignored by blosxom, so I could show the latest version of the HTML template in the page. Because the only plugin on the blosxom website that appears to do something that I think I wanted—cvsinfo—is unavailable, I wrote my own plugin to do it. You can download it here.

Documentation

NAME

Blosxom Plug-in: cvs

SYNOPSIS

Replaces CVS keywords (such as $Id: cvs,v 1.2 2004/01/12 12:59:43 ivo Exp $) with the part after the :.

INSTALLATION

Drop the cvs plug-in into your Blosxom plugins folder.

CONFIGURATION

None necessary.

VERSION

1.2

AUTHOR

Ivo Timmermans <ivo@o2w.nl>, http://www.lychnis.net/

LICENSE

cvs Blosxom Plug-in
Copyright 2004, Ivo Timmermans <ivo@o2w.nl>

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.

Blosxom theme: lychnis/programming/blosxom

Posted on 2004-01-12 by ivo :: /programming/blosxom :: link

I finally made the theme for this website (http://www.lychnis.net/) available for download: lychnis 1.5.

The theme needs at least these plugins: better_title, cvs, headlines, sitelinks, theme, writeback, xhtml. Some of these plugins required tweaking to make them work, sometimes I had to correct the HTML code in them to be XHTML. I'll get these changes published once I've cleaned them up, or maybe I will submit them to the original author(s) of the plugin.

The original idea for the layout is copied from a design on OSWD, called libra. Among other things I changed it to be XHTML 1.1 compliant and to make more use of CSS.

lychnis.net live/site

Posted on 2004-01-12 by ivo :: /site :: link

My new domain lychnis.net is alive, and I created a brand new website for it. Take a look at the information about the site to find out what it means, or just go there.

The new site is also based on blosxom, with a few minor modifications to some of the plugins (most notably the hide plugin). The articles are the same as in the weblog. Only the most recent article is shown on the frontpage, the rest can still be read by clicking on weblog in the navigation bar at the top.

Coding style guide for C code/programming

Posted on 2004-01-12 by ivo :: /programming :: link

After reading Fruit's Source Code Style, I have taken the document and modified it to match my own coding style. The result is this Coding style guide. Thanks to warp and Garion for their comments. More comments are always welcome.

It basically documents the style that I like to program in. This will differ from other people's. It is certainly not prescriptive, only indicative of what I think yields readable source code for any project.

Blosxom theme: scratchpad/programming/blosxom

Posted on 2004-01-09 by ivo :: /programming/blosxom :: link

I made the theme that I'm using for this page available here: version 0.1. It's pretty easily customizable with CSS. If your browser offers the possibility to select alternative stylesheets when viewing this page you can try it now to get an idea of what would be possible. The theme itself is loosely based on the iztsu theme.

The theme needs at least these plugins: archives, bloglinks, breadcrumbs, categories, find, htmllinks, readme, sitelinks, theme, writeback, xhtml. Some of these plugins required tweaking to make them work, sometimes I had to correct the HTML code in them to be XHTML. I'll get these changes published once I've cleaned them up, or maybe I will submit them to the original author(s) of the plugin.

Blosxom plugin: sitelinks/programming/blosxom

Posted on 2004-01-08 by ivo :: /programming/blosxom :: link

In the header of the page you'll see a new bar, with a list of shortcuts to more information on my website. To do this, I took the bloglinks plugin and changed it to a sitelinks plugin. The change to the code is minimal, the only thing that's really different is that it expects the contents to be aligned next to eachother instead of in a list structure. You can download the code here.

Lython/programming

Posted on 2004-01-07 by ivo :: /programming :: link

What's that, did Hell just freeze over? I didn't see this one coming, but now it's possible to compile lisp code to python bytecode with lython

On the website it claims that the lisp code “resembles common lisp.” I took a look at the example code fragments that are distributed with the code. It looks as if lython is just a wrapper for python, that takes lisp syntax and translates it to python syntax. And it's only the lisp syntax that has been implemented so far, no native lisp functions (all function calls are directly translated to python function calls). But Common Lisp is so much more than just syntax, it's a massive amount of function calls. These will have to be supported before lython becomes a useful program. Until that time, I fear that lython will be nothing more than a toy to scare your friends with on a cold winter night.

Creative commons license/

Posted on 2004-01-06 by ivo :: / :: link

I have included a copyright and license statement at the bottom of this page:

Copyright © 2003-2004 Ivo Timmermans. Unless otherwise specified, all material on this website (including any images, sound files, and other original works) may be distributed licensed under a Creative Commons License.

In short, this means that you can redistribute content from this page under an identical license, as long as you take some restrictions into account. There is more information in the Commons deed, which is a short summary of the full license.

Before I did this, you didn't have the right to reproduce anything, except in those cases described as “fair use”. I think that this newly chosen Creative Commons license corresponds better to the way I think about copyright and ownership, and the licenses I usually put on my code (GNU General Public License (GNU GPL) or BSD, in two occasions GNU Lesser General Public License (LGPL)). The texts I wrote for this website don't have a special status for me, so it's only logical that they should be free as well.

Blosxom and RSS/debian

Posted on 2004-01-05 by ivo :: /debian :: link

For planet Debian, this blog is being syndicated with others via RSS. It appears that Blosxom doesn't automatically add a release date+time (the pubDate tag) to the RSS document. Mark Howard mailed me how to fix this: in blosxom.cgi, find the line starting with rss story in the __DATA__ section, and change it to (all on one line):

rss story   <item>\n
    <title>$title</title>\n
    <pubDate>$dw, $da $mo $yr $ti:00 GMT</pubDate>\n
    <link>$url/$yr/$mo_num/$da#$fn</link>\n
    <description>$body</description>\n
  </item>\n

Font sizes/site

Posted on 2004-01-03 by ivo :: /site :: link

Someone has been complaining that the fonts on this website are too big. This comment touches a subject that I've often enraged myself about: default font sizes in browsers.

For some reason or other, Microsoft ships Internet Explorer with a rather large default font size setting. People aren't exactly inclined to change anything, so most of the IE users will be using this default. This has inspired web designers all over the world to specify smaller fonts on their websites, to make it look acceptable in IE.

Mozilla ships with a default font size of 16 points, I always change that to 12 points to be able to read pages that don't specify anything in a comfortable font size. This does mean that I see websites that were designed for IE (which is a bad thing to do at any time) with very small, nearly illegible text.

I designed the layout of this website for my own browser, and it looks good (well, acceptable) in Internet Explorer, when you change the font to “Smallest”. I will not change the size of the fonts here, people should configure their browsers to display fonts in the size they like. If you keep the default of IE or Mozilla, you get what you asked for: large letters.

Happy 2004/

Posted on 2004-01-01 by ivo :: / :: link

A very happy new year to everyone!

I'm sure you all have some new year's resolutions. This year, own resolutions are simple:

  • Get a job in Sweden and move there;
  • Learn to speak, write and read more Japanese;
  • Become stronger in Go, at least 5th kyuu at the end of 2004.