Navigation

home code debian images resume weblog wiki

Older news:

Dec 11, 2006:

Debian GNU/Linux

About lychnis.net
Jul 7, 2005:
Wanneer gebruik je -d en wanneer gebruik je -t?
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

Browse:


Debian GNU/Linux

/meta

Posted on 2006-12-11 by ivo :: /meta :: link

Debian GNU/Linux is a Linux distribution. Worldwide, about one thousand people work together to make a high-quality free operating system. I have been a developer since about october 2000. My work there is mainly maintaining packages, and sometimes I translate some Debian-specific things. Read more about my work for Debian.

python-gnutls

The GnuTLS project is developing a library that provides an interface to TLS or SSL sockets. python-gnutls provides a set of bindings so that the GnuTLS library can be used from your python programs.

tinc

tinc is a Virtual Private Network daemon that uses the linux tun device, and runs completely in userspace. Now the development is mostly done by Guus Sliepen.

pokey

Pokey is a graphical interface to tinc. It shows a graphical representation of the network that has been built up with tinc. It doesn't work with the latest version of tinc, because the protocol has changed a few times since the last release of pokey. Development will probably be picked up again when tinc splits the protocol handling into a library. Here's a screenshot.

Translating software

http://vertaling.nl.linux.org/ Translating open source software to Dutch. More information about the GNU Translation Project's website.

Doflijn

Doflijn is a windowmanager for the X Window System. It is based on aewm, and aimed at providing as little functionality as possible while still being about as useful as for example sawfish.

Sheep

Sheep (officially called "Sheep Asleep") is a script for EPIC (which is an IRC client). It was originally based on SplitFire, but now it has been rewritten from scratch. This script (or rather, this collection of scripts) is now obsolete, since irssi is so much more suited for the level of scriptability required for sheep. Not only that, irssi is also scriptable in Perl (actually any language, but Perl seems to be the most common) instead of EPIC's horrible Tcl-like language. I have a small collection of scripts for irssi on my IrssiScripts page.

BLURT

BLURT stands for Bloody Lame Useless Redundant Terminal. It is a terminal emulator for X, intended to use less resources than xterm or rxvt. It also offers far less features; in fact it was designed to be as small as possible, but still provide a fully functional terminal emulator.

Useless Code

UselessCode: A collection of completely useless code. Do not expect too much of it, it's just a compilation of some of my more embarassing little projects. A lot of this code is also scattered throughout this site and the wiki.

CVS

Some of my code is available from CVS, and can be browsed through online via ViewCVS.

Style guides

I wrote a few Coding style guides. They basically document the style that I like to program in, in four languages (C, C++, Perl, Python). This will differ from other people's styles. They are certainly not prescriptive, only indicative of what I think yields readable source code for any project.

Blosxom

I wrote a few plugins and themes for Blosxom, a simple but powerful weblogging system.

Plugins

Themes

About lychnis.net/meta

Posted on 2006-12-11 by ivo :: /meta :: link

License and copyright

Most material on this site is copyright © 2003-2004 Ivo Timmermans. Material on this site by other copyright holders is clearly indicated.

Unless otherwise specified, all material on this website (including any images, sound files, and other original works) that has been published by me has been licensed for distribution under a Creative Commons License.

Comments to the articles are not covered by this license, they should be considered normal copyrighted works. Always contact their authors for more information.

All released code archives, downloadable scripts, etc. should always be accompanied with a license that indicates if and under which conditions they can be redistributed.

Layout

The original idea for the old layout of this site (which is still used in the image pages for example) 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.

Code

The site uses blosxom as if it were some kind of content management system (CMS). I know it's not intended to be, but it interacts nicely with my weblog, which is running another instance of blosxom. They share the content, but for reading older articles the weblog is more suited. This instance is using some plugins to generate the content: better_title, gzip, headlines, hide, sitelinks, theme, writeback, xhtml. All these plugins can be downloaded from the blosxom website. The theme file is not yet finished, but when it is I will publish it.

Lychnis

Lychnis is the name of a genus of flowers that are common in Europe. The image at the top left of the old layout and in the shortcut icon is a processed image of a lychnis flos-cuculi L. (ragged robin).

Stats

Website statistics.

Links

hacker powered by blosxom. Valid XHTML 1.1 Valid CSS 2 Creative Commons licensed Valid RSS

Wanneer gebruik je -d en wanneer gebruik je -t?/meta

Posted on 2005-07-07 by ivo :: /meta :: link

Wanneer gebruik je -d en wanneer gebruik je -t?

Samenvatting

Tegenwoordige tijd
ik: alleen de gecorrigeerde stam. jij/hij/zij: gecorrigeerde stam + t, ook als de gecorrigeerde stam op een d eindigt. Als de stam op een t eindigt komt er geen extra t bij.
Verleden tijd
ik/jij/hij/zij: gecorrigeerde stam + -de/-te, als de stam eindigt op een van de medeklinkers in "'t kofschip" (ch telt als een letter): -te, anders -de.

Hele werkwoord

Het hele werkwoord, ofwel infinitief, is de -en vorm die de handeling in zijn geheel aangeeft. Voorbeeld: werken, lopen, verhuizen, gebeuren, geloven.

Stam

De stam van een werkwoord is de belangrijkste indicator voor welke letter gebruikt moet worden in de vervoegingen. De stam wordt verkregen door het onvervoegde werkwoord te ontdoen van de uitgang -en.

inf.: werken → stam: werk-

inf.: lopen → stam: lop-

inf.: verhuizen → stam: verhuiz-

inf.: gebeuren → stam: gebeur-

inf.: geloven → stam: gelov-

Soms eindigt de stam van een werkwoord op een klinker, in dat geval staat er vaak alleen een -n achter de stam.

inf.: doen → stam: doe-

Gecorrigeerde stam

Vaak is het zo dat de stam op zich niet voldoet aan de nederlandse spellingsregels en dus niet op zichzelf als een woord gebruikt kan worden. Voordat dat kan, moet hij eerst gecorrigeerd worden. De stam van lopen bijvoorbeeld is lop-, waarbij de 'o' een lange klank heeft. Deze stam wordt dan gecorrigeerd door een 'o' toe te voegen: de gecorrigeerde stam is loop-.

stam: werk- → gec. stam: werk-

stam: verhuiz- → stam: verhuis-

stam: gebeur- → stam: gebeur-

stam: gelov- → stam: geloof-

Tegenwoordige tijd

In de tegenwoordige tijd geldt altijd de volgende regel voor werkwoorden waarvan de stam niet eindigt op een t:

ikstam
jijstam-t
hij/zijstam-t
wij/jullie/zijhele werkwoord

Voor de jij/hij/zij-vervoeging komt er dus altijd een -t achter de stam, nooit een -d.

infinitiefwerken   infinitiefvinden   infinitiefgeloven
stamwerk-   stamvind-   stamgelov-
gec. stamwerk-   gec. stamvind-   gec. stamgeloof-
ikwerk   ikvind   ikgeloof
jijwerkt   jijvindt   jijgelooft
hij/zijwerkt   hij/zijvindt   hij/zijgelooft
wij/jullie/zijwerken   wij/jullie/zijvinden   wij/jullie/zijgeloven

Het kan nodig zijn de uiteindelijke vorm nog te corrigeren, als hij bijvoorbeeld eindigt op dubbel t.

Uitzondering: als het zinsdeel jij of je direct volgt op het vervoegde werkwoord, dan is de vervoeging stam zonder -t. Dit geldt alleen als je gebruikt wordt als onderwerp van de zin; in alle andere grammaticale functies van je gaat dit niet op. Dit zal alleen verwarrend werken in de gevallen waar je je kunt gebruiken in plaats van een andere vorm (jou, jezelf, jouw, etc.). Als je je kunt vervangen door jij, dan vervalt de -t.

inf.: werken → stam: werk-
Je werkt hard vandaag.
Werk je hard vandaag?

inf.: vinden → stam: vind-
Jij vindt blauw mooi.
Vind jij blauw mooi?

Jij houdt je op de vlakte. (jezelf)    → (je is hierin niet het onderwerp van de zin.)
Hij leest je bestand in. (jouw)

Bij werkwoorden waar de stam eindigt op een t komt er geen extra -t bij.

inf.: liften → stam: lift-
ik lift, jij lift, hij lift
Lift jij wel eens?

Verleden tijd

Verleden tijd: gec. stam-de of gec. stam-te

Voltooid deelwoord: gegec. stam-d of gegec. stam-t

Om te bepalen of in de verleden tijd een -d of een -t gebruikt moet worden, kijk je naar de klank voor de -en uitgang in het hele werkwoord. Als die hard is, moet er een -t uitgang komen in de verleden tijd, en anders -d. De volgende klanken zijn hard: T K F S CH P.

Uit die klanken komt het kofschip ezelsbruggetje. Dit ezelsbruggetje zegt dat wanneer de ongecorrigeerde stam op een van de letters uit 'T KoFSCHiP eindigt, de verleden tijd -t krijgt, en anders -d. Let goed op dat je hiervoor de stam neemt, en niet de gecorrigeerde stam; het gaat immers om de klank voor -en in het hele werkwoord.

inf.: werken → stam: werk-; eindigt op een harde klank, dus verleden tijd is -t: werkte.

inf.: verhuizen → stam: verhuiz-; eindigt op een zachte klank, dus verleden tijd is -d: verhuisde.

inf.: geloven → stam: gelov-; eindigt op een zachte klank, dus verleden tijd is -d: geloofde.

inf.: gebeuren → stam: gebeur-; eindigt op een zachte klank, dus verleden tijd is -d: gebeurde.

Dan is er nog het voltooid deelwoord, waar exact dezelfde -d/-t regels voor gelden. Dit wordt gebruikt in zinnen met een vorm van 'zijn' of 'hebben' en het voltooid deelwoord begint vaak met ge-.

Ik ben verhuisd.

Het is gebeurd.

Jij hebt gewerkt.

Zo kan het dus voorkomen dat er van 1 werkwoord 2 vormen bestaan waartussen het enige verschil is dat de laatste letter een d of een t is. Toch is het altijd helemaal duidelijk omschreven welke vorm er gebruikt moet worden.

Het gebeurt. - Tegenwoordige tijd, dus gec. stam plus -t.

Het is gebeurd. - Voltooid deelwoord, en een -d uitgang vanwege de zachte klank in het hele werkwoord, dus gec. stam plus -d.

Coding style guide - C/meta

Posted on 2004-04-26 by ivo :: /meta :: link

This document is Copyright © 2004 Ivo Timmermans. This document is licensed for distribution under a Creative Commons License. It is based on Fruit's Source Code Style, which was licensed under the artistic license.

<< Back to coding style index.

  1. Source file layout
    1. Line length
    2. Copyright and license statement
    3. Preprocessor directives
    4. Macros
    5. Comments
    6. Documentation
  2. Function definitions
    1. Declaration
    2. Placing braces
  3. Variables
    1. Naming
    2. Declarations
    3. Initialization
  4. Function body
    1. Function length
    2. Using braces
    3. How to indent
    4. Using tabs
    5. When to indent
    6. Line continuation
    7. Complex line continuation
    8. Control line continuation
    9. Empty lines
  5. Parentheses
    1. Using parentheses
    2. Placing parentheses
    3. Using spaces
    4. Typecasts
  6. Placing assignments
  7. Boolean expressions

1. Source file layout

1. Line length

Lines may not exceed 78 characters. Do not write lines that are longer than 78 characters. It is always possible to wrap lines, and continue on the next line. It should never be necessary to indent more than about four levels deep. (This asserts that tabs count as if they were 8 characters.)

2. Copyright and license statement

At the head of each source file there should be a comment, which mentions the file name, its function in the program, a copyright and license statement. Always include at least one email address. Optional extra information, such as CVS Id tags, should follow the license. For notes on the layout of multiline comments, see below.

/*
 * foo.c - Frobnicate the foobar
 * Copyright (C) 2004  Ivo Timmermans <ivo@o2w.nl>
 *
 * License…
 *
 * $Id: foo.c,v 1.1 2004/01/10 12:34:56 ivo Exp $
 */

Top-level inline documentation should be in a separate comment, after this one.

3. Preprocessor directives

Simple statements should be like this:

#include <stdio.h>

#define CONSTANT 3

When nesting statements, such as #ifdefs, put a tab after the # and the rest of the line. Put a comment after the accompanying #else and #endif to indicate which block is terminated.

#ifdef SOMETHING
#   ifdef SOMETHINGELSE
#       define CONSTANT 4
#   endif  /* SOMETHINGELSE */
#endif  /* SOMETHING */
4. Macros

There is no reason to make macros longer than 78 characters, they can be wrapped with a backslash at the end of the previous line. Creating a macro which uses local variables should be avoided, but if absolutely necessary, wrap the macro in a do {} while (0)-loop. Always wrap macro arguments in parentheses when the expansion could be ambiguous.

#define MACRO(x, y) do { \
    do_something_with(x); \
    (y) = (x) << 4; \
} while (0)
5. Comments

Multiline comments should be formatted as follows, so that the vertical line of asterisks on the left is a clear indication that it is a comment.

/*
 * First paragraph of a multiline comment.
 *
 * Second paragraph of the comment.
 */

Simple comments following a statement should be separated from the statement with two spaces. The length of the entire line should not be more than 78 characters, put the comment on the preceding line if necessary (but put an empty line before it to improve readability).

    frob(arguments);  /* Frobnicate before it's too late! */

    /* This comment is too long to fit on the next line. */
    r = functioncall(with, arguments);

    /*
     * Do not read the code below, it is evil.
     *
     * Actually that's a lie.
     */
    do_evil_stuff();
6. Documentation

Documentation for functions can be placed in a header file, along with their prototype declarations. This information can be extracted with tools such as doxygen to make nicely formatted documents; public functions are usually part of an API. Static functions will of course have their documentation alongside their definitions.

Comments on the inner workings of a function—for example the exact algorithm that is used—should be placed inline in the code, or above it in the source file.

foo.h:

/* Sort list alphabetically, returns the sorted list */
extern list_t *sort_list(const list_t *list);

foo.c:

/*
 * Sort list alphabetically, using the modified bubblesort
 * algorithm, which is defined in bubblesort.c.
 */
list_t *sort_list(const list_t *list) {
    …
}

2. Function definitions

1. Declaration

Everything in the function declaration should be on one line. If the argument declaration doesn't fit in 78 characters, they should be separated at the commas. Precede the continuation line with two tabs (the continuation must not be on the same indentation level as the function body).

static struct somestruct *function(struct somestruct **argument,
        struct someotherstruct *something, int foo, int blargh) {

Of course, if you need a long declaration such as the one above, you need to start thinking of using typedefs.

If a function takes no arguments, explicitly declare it with function(void). If a function returns nothing, explicitly declare it void function(…).

2. Placing braces

Braces are formatted using what looks like K&R style but is more regular. In particular, braces are put after a function declaration, not on a line of their own. So:

int main(int argc, char **argv) {
    if (foo) {
        bar;
    }
    return 0;
}

3. Variables

1. Naming

Use lowercase names for everything, using underscores if something needs multiple words. The only exception are preprocessor constants, which are all uppercase. Short names avoid tedious typing but do make the names descriptive of their content. Don't bother reusing local variables; the compiler will do that for you.

    int i, fd, program_path;  /* good */
    int aFile, temp;  /* bad */

Common sense applies: don't use i for storing the return value of a function, don't use r as a counter. Never use one variable for two different things.

2. Declarations

When declaring pointers, the asterisk shall be put next to the variable name, not next to the type name. This is because the asterisk is part of what is being declared, not of the type itself. Example:

    char *p;  /* good, should be read as “the content of p is a character” */
    char* q;  /* bad, “q is a character content of” */

The virtue of this becomes apparent when you regard:

    char* p, q;  /* what is the type of q? */
3. Initialization

The machine internal representation of a NULL-pointer does not have to be all-zeroes (but the C representation is always false). Thus, do not initialize structures with memset() or bzero():

    memset(p, 0, sizeof *p);  /* bad */
    struct foo p0 = {0};
    *p = p0;  /* good */

4. Function body

1. Function length

A function should never have to be longer than about 50 lines (approximately two screenfuls on a standard terminal), including empty lines and any extra lines that are caused by wrapping. This excludes any documentation for the function, which should precede the function declaration. (Sometimes the documentation can be placed in header files, accompanying the prototype declaration.) Any function that requires more than 100 lines is probably badly designed.

2. Using braces

If possible, braces are omitted, except when either part of an if ()else … uses braces, then the other part will also use braces:

    if (foo) {
        bar;
        baz;
    } else {
        quux;
    }

When using nested if statements, always put braces around the inner code blocks, even if the inner if is the only statement in that block. This means that possible else-blocks of the outer if also get wrapped.

    if (foo) {
        if (bar)
            baz;
        else
            qux;
    } else {
        quux;
    }

dowhile ()-loops are formatted with the while on the same line as the closing brace:

    do {
        statements;
    } while (…);
3. How to indent

Indentation is always done using tabs. It is recommended that the tab length of your editor be set to something more reasonable than 8. I personally prefer 4, but the pleasant thing about tabs is that everyone can use their favourite indentation size.

4. Using tabs

Tabs are used only at the beginning of a line. If you feel a need to align other bits, use spaces. But rather don't align them at all, unless there's a very compelling reason to do so.

5. When to indent

Control statements and their body always have lines of their own, even if they are very short:

    if (x)
        y();
6. Line continuation

If a line is more than 78 characters long it should really be broken into bits. Conversely, if a line is shorter, do write it on a single line. Every line but the first should be given a single extra tab. If the line is a formula, then the operator at which you break the line should be the first character of the new line. Examples:

    x = get_foobar(foo, bar, baz) + get_xyzzy(zxnrbl, quux)
        + get_zoo(bear, monkey, lion, penguin) + get_pets(cat, dog)
        + get_colours(red, green, blue, yellow);
7. Complex line continuation

There are two reasons to deviate from this rule: if the formula is exeptionally complex it may be better to give some parts an extra tab to show that they are in fact subordinate clauses to the main formula:

    y = a
        + b
        + c1
            * c2
            * c3
            * c4
        + d;
8. Control line continuation

The other reason is when a broken line is a control statement that is followed by a body:

    if (foo + bar + baz
            + quux + xyzzy)  /* an extra tab */
        zxnrbl();
9. Empty lines

Use empty lines to indicate blocks of code that pertain to a specific operation, and to separate those that have different purposes. Always put an empty line after variable declarations and indented blocks.

void function(void) {
    int a, b = 0;

    a = do_something();

    if (a) {
        b = do_something_with_a();
    }

    do_something_with_a_and_b(a, b);
}

5. Parentheses

1. Using parentheses

If possible parentheses should be omitted, except when this evokes a warning from the compiler. In particular, return and sizeof are not functions!

    int x;
    x = sizeof x;  /* no parentheses here */
    return x;  /* nor here */

The only reason why sizeof often needs parentheses is that it is often used with type expressions, which need parentheses just like they do in typecasts.

2. Placing parentheses

Parentheses always cuddle up to the function they follow, but there's a space between a control statement (for, if and while) and the parenthesis following it. There are no spaces directly after an opening parenthesis, or directly before a closing parenthesis:

    if (foo)  /* one space */
        bar();  /* no space here */
    qux(a + b);  /* no spaces inside the parentheses */

There is a space between a control statement and the opening parenthesis, but not for function calls.

    if (foo)  /* a space */
        bar(4);  /* no space */
    for (…) {  /* a space */
        baz(qux);  /* no space */
    }
3. Using spaces

In formulas be generous with spaces, they make things more readable:

    return x * (a + b) * y;

When writing comma delimited lists, such as in function arguments, place a space only after each comma.

    foo(a, b);  /* good */
    bar(a,b);  /* bad */
    bar( a , b );  /* bad */
4. Typecasts

When doing typecasts, put a space between the type and the object being cast:

    int a = (int) p;

Write complex (pointer) types like you would in a declaration:

    struct something **a;
    a = (struct something **) p;

6. Placing assignments

Avoid assignments in truth statements—if only because they often require extra parentheses to avoid compiler warnings.

    r = read(fd, buf, sizeof buf);
    if (r == -1)
        b0rk();

7. Boolean expressions

Use the fact that boolean expressions in C mean testing for non-zero-ness. In particular, avoid pointless noise like:

    if (p != NULL) …
    if (i == 0) …

These should be rewritten as:

    if (p) …
    if (!i) …

… because C already does such a check internally.

<< Back to coding style index.

Coding style guides/meta

Posted on 2004-03-25 by ivo :: /meta :: link

Below are four coding style guides. They basically document the style that I like to program in. These will differ from other people's. They are certainly not prescriptive, only indicative of what I think yields readable source code for any project, regardless of whether it has a small or large code base.

Coding style guide - Perl/meta

Posted on 2004-03-25 by ivo :: /meta :: link

The style I like in perl can probably be best represented by the following perltidy commandline:

perltidy -sbt=2 -bt=2 -bbt=0 -ci=2 -icp -nicb -ibc -hsc -noll
-msc=2 -nsts -nsfs -pt=2 -syn -w -ce -i=8 -t -nbbc -nbbs -nbbb
-nbl -nsbl -bar -dnl

There is more to it, but this will have to do for now. Most of the principles from the C style guide will apply here, too.

Resume / curriculum vitae/meta

Posted on 2004-03-20 by ivo :: /meta :: link

Curriculum Vitae

Ivo Timmermans
Personal Details

name Ivo Roald Timmermans
gender male
nationality Dutch
address Derde Werelddreef 83, 2622 HC Delft, NL
date of birth 27 September 1977, Utrecht, NL
drivers license European, Category B; possess a car

Education

1995-2003
Applied Mathematics at the Delft University of Technology; stopped in the bachelor stage.
1989-1995
Secondary school at het Utrechts Stedelijk Gymnasium in Utrecht; subjects passed in final exams: Dutch, Latin, English, German, physics, math A, math B, chemistry, biology.

Career Summary

February 2002 – present

Software engineer at Next Element Solution Provider B.V.: Programming in PHP, Perl, C, C++, Python, SQL; project management experience.

November 2001 – January 2002

Software engineer at N2IT B.V.: Developing the FinalScratch software application; C++, GTK, Linux, realtime audio.

FinalScratch is an application that allows professional disk jockeys to play digital music (MP3, wav, Ogg Vorbis, etc) using their existing analog mixing environment.

June 2000 – October 2001

Software engineer at Cistron Internet Services B.V.: Perl, CGI, Apache, C, PostgreSQL, Linux system administration.

Mostly developing custom CGI-based applications for customers or internal use, for example: a product catalog and online shop for a comics store; a custom content management system for students.

March 1999 – September 2000

On detachment from Operator Group Delft as system administrator for a mixed Windows NT and Novell Netware network at the Thuiszorg Nieuwe Waterweg-Noord in Schiedam (institution for home care).

Next to everyday administration activities, I helped migrating a network of about 150 Windows PCs and eight Novell NetWare 3 servers to 200 PCs and fifteen Novell NetWare 5.0 servers.

Publications/talks/competitions

2000, 2001, 2002, 2003
Competed in the local (Delft), the Dutch and the Northwest European rounds of the Intercollegiate Programming Contests (ICPC).
November 2001
Article GNU Emacs als editor (GNU Emacs as editor), published in the Dutch Linux Magazine.
May 2001
Talk High Availability VPN solutions during the spring conference of the NLUUG (Dutch UNIX User Group).
November 2000
Article Virtual Private Networks met tinc (Virtual Private Networks with tinc), published in the Dutch Linux Magazine.
August 2000
Talk Virtual Private Networks, during the Networking Event 2000.

Cultural Activities

January 2003 – present
Learning Aikidou (a Japanese martial art), currently 6th kyuu level.
October 2002 – present
Playing Go (Chinese/Japanese board game), currently about 11th kyuu level.
October 2000 – present
Package maintainer for Debian GNU/Linux (responsible for the quality of about thirty software packages in Debian, helping with translations to Dutch).
November 1998 – present
Coordinator of the Dutch translation team of the Free Software Foundation.
September 1998 – present
Author (later co-author) of tinc, a userspace VPN daemon for Linux, *BSD, Solaris, Windows, OSX.
October 1997 – September 2001
Network administration commission Delftse Studentenvereniging Sint Jansbrug (student society).
August 1997 – August 1999
Member of the Sponsorship Commission in Sint Jansbrug.
March 1997 – December 1997
Lustrum Yearbook Commission for Sint Jansbrug (responsible for sponsoring and layout).
October 1995 – present
Member of the Delftse Studentenvereniging Sint Jansbrug (student society).

Language proficiency

LanguageReadingWrittenFluency
Dutchnative, very wellnative, very wellnative, very well
Englishfluentfluentfluent
Swedishxxx
Germanx
Frenchx
Japanese

References

References available on request.

python-gnutls/meta

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

python-gnutls provides a set of bindings so that the GnuTLS library can be used from your python programs. This enables you to create secure internet sockets, that can serve on either the server or client side of a connection.

Announcements regarding python-gnutls—information about new releases, including change logs—are made in a section on programming in my weblog: python-gnutls. See that page for the latest release.

For more about GnuTLS, please see their website.


It's very simple to create a secure client socket, it's just two more calls after your socket is ready. The following example is a simple relay between the terminal (stdin/stdout) and a remote host.

import gnutls
import socket
import select
import os

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('some-imap-host', some-port))
    c = gnutls.client(s)
    c.handshake()

    ins = os.fdopen(0, "r", 0)

    loop = True
    while loop:
        readers, writers, errors = select.select([ins, s], [], [])

        if len(readers):
            for r in readers:
                if r == ins:
                    text = ins.read(1)
                    if text:
                        c.send(text)
                    else:
                        c.shutdown(gnutls.SHUT_WR)
                        loop = False
                else:
                    text = c.recv(1000)
                    if text:
                        sys.stdout.write(text)
                    else:
                        loop = False

    del c
    s.close()


if __name__ == '__main__':
    main()

An example output, when communicating with an IMAPS server (lines wrapped for display purposes; blue text is typed in stdin):

> python simpleclient.py
* OK [CAPABILITY IMAP4rev1 CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT
    THREAD=REFERENCES SORT QUOTA AUTH=PLAIN] Courier-IMAP ready.
    Copyright 1998-2003 Double Precision, Inc.  See COPYING for
    distribution information.
A LOGOUT
* BYE Courier-IMAP server shutting down
A OK LOGOUT completed

Debian GNU/Linux/meta

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

Debian GNU/Linux is a Linux distribution. Worldwide, about one thousand people work together to make a high-quality free operating system. Read more about Debian.

Unofficial Debian packages

My own apt-get-able repository of unofficial Debian packages. Read more about its contents, and how to use it.

Planet Debian

The /debian tree of my weblog is part of Planet Debian, a collection of the weblogs of several Debian developers.

My work in Debian

I am responsible for the quality of several packages in Debian. To see which packages they are, have a look at the list of packages and related info.

To see the state these packages are in, have a look at the outstanding bugreports against my packages.

Coding style guide - Python/meta

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

This document is Copyright © 2004 Ivo Timmermans. This document is licensed for distribution under a Creative Commons License. It is based on Style guide for python code, which was put in the public domain.

Introduction

This document gives coding conventions for the Python code comprising the standard library for the main Python distribution. Please see the companion informational PEP describing style guidelines for the C code in the C implementation of Python[1].

This document was adapted from Guido's original Python Style Guide essay[2], with some additions from Barry's style guide[5]. Where there's conflict, Guido's style rules for the purposes of this PEP. This PEP may still be incomplete (in fact, it may never be finished <wink>).

A Foolish Consistency is the Hobgoblin of Little Minds

A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.

But most importantly: know when to be inconsistent — sometimes the style guide just doesn't apply. When in doubt, use your best judgement. Look at other examples and decide what looks best. And don't hesitate to ask!

Two good reasons to break a particular rule:

  1. When applying the rule would make the code less readable, even for someone who is used to reading code that follows the rules.
  2. To be consistent with surrounding code that also breaks it (maybe for historic reasons) — although this is also an opportunity to clean up someone else's mess (in true XP style).

Code lay-out

Indentation

Use the default of Emacs' Python-mode: 4 spaces for one indentation level. For really old code that you don't want to mess up, you can continue to use 8-space tabs. Emacs Python-mode auto-detects the prevailing indentation level used in a file and sets its indentation parameters accordingly.

Tabs or Spaces?

Never mix tabs and spaces. The most popular way of indenting Python is with spaces only. The second-most popular way is with tabs only. Code indented with a mixture of tabs and spaces should be converted to using spaces exclusively. (In Emacs, select the whole buffer and hit ESC-x untabify.) When invoking the python command line interpreter with the -t option, it issues warnings about code that illegally mixes tabs and spaces. When using -tt these warnings become errors. These options are highly recommended!

For new projects, spaces-only are strongly recommended over tabs. Most editors have features that make this easy to do. (In Emacs, make sure indent-tabs-mode is nil).

Maximum Line Length

There are still many devices around that are limited to 80 character lines; plus, limiting windows to 80 characters makes it possible to have several windows side-by-side. The default wrapping on such devices looks ugly. Therefore, please limit all lines to a maximum of 79 characters (Emacs wraps lines that are exactly 80 characters long). For flowing long blocks of text (docstrings or comments), limiting the length to 72 characters is recommended.

The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces. If necessary, you can add an extra pair of parentheses around an expression, but sometimes using a backslash looks better. Make sure to indent the continued line appropriately. Emacs Python-mode does this right. Some examples:

    class Rectangle(Blob):

        def __init__(self, width, height,
                     color='black', emphasis=None, highlight=0):
            if width == 0 and height == 0 and \
               color == 'red' and emphasis == 'strong' or \
               highlight > 100:
                raise ValueError, "sorry, you lose"
            if width == 0 and height == 0 and (color == 'red' or
                                               emphasis is None):
                raise ValueError, "I don't think so"
            Blob.__init__(self, width, height,
                          color, emphasis, highlight)
Blank Lines

Separate top-level function and class definitions with two blank lines. Method definitions inside a class are separated by a single blank line. Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).

When blank lines are used to separate method definitions, there is also a blank line between the `class' line and the first method definition.

Use blank lines in functions, sparingly, to indicate logical sections.

Python accepts the control-L (i.e. ^L) form feed character as whitespace; Emacs (and some printing tools) treat these characters as page separators, so you may use them to separate pages of related sections of your file.

Encodings (PEP 263)

Code in the core Python distribution should aways use the ASCII or Latin-1 encoding (a.k.a. ISO-8859-1). Files using ASCII should not have a coding cookie. Latin-1 should only be used when a comment or docstring needs to mention an author name that requires Latin-1; otherwise, using \x escapes is the preferred way to include non-ASCII data in string literals. An exception is made for those files that are part of the test suite for the code implementing PEP 263.

Imports

  • Imports should usually be on separate lines, e.g.:

            No:  import sys, os
            Yes: import sys
                 import os

    it's okay to say this though:

            from types import StringType, ListType
  • Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants. Imports should be grouped, with the order being

    1. standard library imports
    2. related major package imports (i.e. all email package imports next)
    3. application specific imports

    You should put a blank line between each group of imports.

  • Relative imports for intra-package imports are highly discouraged. Always use the absolute package path for all imports.

  • When importing a class from a class-containing module, it's usually okay to spell this

            from MyClass import MyClass
            from foo.bar.YourClass import YourClass

    If this spelling causes local name clashes, then spell them

            import MyClass
            import foo.bar.YourClass

    and use "MyClass.MyClass" and "foo.bar.YourClass.YourClass"

Whitespace in Expressions and Statements

Pet Peeves

Guido hates whitespace in the following places:

  • Immediately inside parentheses, brackets or braces, as in: "spam( ham[ 1 ], { eggs: 2 } )". Always write this as "spam(ham[1], {eggs: 2})".
  • Immediately before a comma, semicolon, or colon, as in: "if x == 4 : print x , y ; x , y = y , x". Always write this as "if x == 4: print x, y; x, y = y, x".
  • Immediately before the open parenthesis that starts the argument list of a function call, as in "spam (1)". Always write this as "spam(1)".
  • Immediately before the open parenthesis that starts an indexing or slicing, as in: "dict ['key'] = list [index]". Always write this as "dict['key'] = list[index]".
  • More than one space around an assignment (or other) operator to align it with another, as in:

              x             = 1
              y             = 2
              long_variable = 3

    Always write this as

              x = 1
              y = 2
              long_variable = 3

(Don't bother to argue with him on any of the above — Guido's grown accustomed to this style over 20 years.)

Other Recommendations
  • Always surround these binary operators with a single space on either side: assignment (=), comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), Booleans (and, or, not).
  • Use your better judgment for the insertion of spaces around arithmetic operators. Always be consistent about whitespace on either side of a binary operator. Some examples:

              i = i+1
              submitted = submitted + 1
              x = x*2 - 1
              hypot2 = x*x + y*y
              c = (a+b) * (a-b)
              c = (a + b) * (a - b)
  • Don't use spaces around the '=' sign when used to indicate a keyword argument or a default parameter value. For instance:

              def complex(real, imag=0.0):
                  return magic(r=real, i=imag)
  • Compound statements (multiple statements on the same line) are generally discouraged.

              No:  if foo == 'blah': do_blah_thing()
              Yes: if foo == 'blah':
                       do_blah_thing()
              No:  do_one(); do_two(); do_three()
              Yes: do_one()
                   do_two()
                   do_three()

Comments

Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!

Comments should be complete sentences. If a comment is a phrase or sentence, its first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!).

If a comment is short, the period at the end is best omitted. Block comments generally consist of one or more paragraphs built out of complete sentences, and each sentence should end in a period.

You should use two spaces after a sentence-ending period, since it makes Emacs wrapping and filling work consistenty.

When writing English, Strunk and White apply.

Python coders from non-English speaking countries: please write your comments in English, unless you are 120% sure that the code will never be read by people who don't speak your language.

Block Comments

Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment). Paragraphs inside a block comment are separated by a line containing a single #. Block comments are best surrounded by a blank line above and below them (or two lines above and a single line below for a block comment at the start of a a new section of function definitions).

Inline Comments

An inline comment is a comment on the same line as a statement. Inline comments should be used sparingly. Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.

Inline comments are unnecessary and in fact distracting if they state the obvious. Don't do this:

        x = x + 1                 # Increment x

But sometimes, this is useful:

        x = x + 1                 # Compensate for border

Documentation Strings

Conventions for writing good documentation strings (a.k.a. "docstrings") are immortalized in PEP 257 [3].

  • Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does. This comment should appear after the "def" line.
  • PEP 257 describes good docstring conventions. Note that most importantly, the """ that ends a multiline docstring should be on a line by itself, e.g.:

          """Return a foobang
    
          Optional plotz says to frobnicate the bizbaz first.
          """
  • For one liner docstrings, it's okay to keep the closing """ on the same line.

Version Bookkeeping

If you have to have RCS or CVS crud in your source file, do it as follows.

        __version__ = "$Revision: 1.2 $"
        # $Source: /home/cvs/ivo/blosxom-content/content/meta/coding-style-python.txt,v $

These lines should be included after the module's docstring, before any other code, separated by a blank line above and below.

Naming Conventions

The naming conventions of Python's library are a bit of a mess, so we'll never get this completely consistent — nevertheless, here are some guidelines.

Descriptive: Naming Styles

There are a lot of different naming styles. It helps to be able to recognize what naming style is being used, independently from what they are used for.

The following naming styles are commonly distinguished:

  • x (single lowercase letter)
  • X (single uppercase letter)
  • lowercase
  • lower_case_with_underscores
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CapitalizedWords (or CapWords, or CamelCase — so named because of the bumpy look of its letters[4])
  • mixedCase (differs from CapitalizedWords by initial lowercase character!)
  • Capitalized_Words_With_Underscores (ugly!)

There's also the style of using a short unique prefix to group related names together. This is not used much in Python, but it is mentioned for completeness. For example, the os.stat() function returns a tuple whose items traditionally have names like st_mode, st_size, st_mtime and so on. The X11 library uses a leading X for all its public functions. (In Python, this style is generally deemed unnecessary because attribute and method names are prefixed with an object, and function names are prefixed with a module name.)

In addition, the following special forms using leading or trailing underscores are recognized (these can generally be combined with any case convention):

  • _single_leading_underscore: weak "internal use" indicator (e.g. "from M import *" does not import objects whose name starts with an underscore).
  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g. "Tkinter.Toplevel(master, class_='ClassName')".
  • __double_leading_underscore: class-private names as of Python 1.4.
  • __double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces, e.g. __init__, __import__ or __file__. Sometimes these are defined by the user to trigger certain magic behavior (e.g. operator overloading); sometimes these are inserted by the infrastructure for its own use or for debugging purposes. Since the infrastructure (loosely defined as the Python interpreter and the standard library) may decide to grow its list of magic attributes in future versions, user code should generally refrain from using this convention for its own use. User code that aspires to become part of the infrastructure could combine this with a short prefix inside the underscores, e.g. __bobo_magic_attr__.
Prescriptive: Naming Conventions
Names to Avoid

Never use the characters `l' (lowercase letter el), `O' (uppercase letter oh), or `I' (uppercase letter eye) as single character variable names. In some fonts, these characters are indistinguisable from the numerals one and zero. When tempted to use `l' use `L' instead.

Module Names

Module names can be either CapWords or lowercase. There is no unambiguous convention to decide which to use. Modules that export a single class (or a number of closely related classes, plus some additional support) are often named in CapWords, with the module name being the same as the class name (e.g. the standard StringIO module). Modules that export a bunch of functions are usually named in all lowercase.

Since module names are mapped to file names, and some file systems are case insensitive and truncate long names, it is important that module names be chosen to be fairly short and not in conflict with other module names that only differ in the case — this won't be a problem on Unix, but it may be a problem when the code is transported to Mac or Windows.

There is an emerging convention that when an extension module written in C or C++ has an accompanying Python module that provides a higher level (e.g. more object oriented) interface, the Python module's name CapWords, while the C/C++ module is named in all lowercase and has a leading underscore (e.g. _socket).

Python packages generally have a short all lowercase name.

Class Names

Almost without exception, class names use the CapWords convention. Classes for internal use have a leading underscore in addition.

Exception Names

If a module defines a single exception raised for all sorts of conditions, it is generally called "error" or "Error". It seems that built-in (extension) modules use "error" (e.g. os.error), while Python modules generally use "Error" (e.g. xdrlib.Error). The trend seems to be toward CapWords exception names.

Function Names

Plain functions exported by a module can either use the CapWords style or lowercase (or lower_case_with_underscores). There is no strong preference, but it seems that the CapWords style is used for functions that provide major functionality (e.g. nstools.WorldOpen()), while lowercase is used more for "utility" functions (e.g. pathhack.kos_root()).

Global Variable Names

(Let's hope that these variables are meant for use inside one module only.) The conventions are about the same as those for exported functions. Modules that are designed for use via "from M import *" should prefix their globals (and internal functions and classes) with an underscore to prevent exporting them.

Method Names

The story is largely the same as for functions. Use lowercase for methods accessed by other classes or functions that are part of the implementation of an object type. Use one leading underscore for "internal" methods and instance variables when there is no chance of a conflict with subclass or superclass attributes or when a subclass might actually need access to them. Use two leading underscores (class-private names, enforced by Python 1.4) in those cases where it is important that only the current class accesses an attribute. (But realize that Python contains enough loopholes so that an insistent user could gain access nevertheless, e.g. via the __dict__ attribute.)

Designing for inheritance

Always decide whether a class's methods and instance variables should be public or non-public. In general, never make data variables public unless you're implementing essentially a record. It's almost always preferrable to give a functional interface to your class instead (and some Python 2.2 developments will make this much nicer).

Also decide whether your attributes should be private or not. The difference between private and non-public is that the former will never be useful for a derived class, while the latter might be. Yes, you should design your classes with inheritence in mind!

Private attributes should have two leading underscores, no trailing underscores.

Non-public attributes should have a single leading underscore, no trailing underscores.

Public attributes should have no leading or trailing underscores, unless they conflict with reserved words, in which case, a single trailing underscore is preferrable to a leading one, or a corrupted spelling, e.g. class_ rather than klass. (This last point is a bit controversial; if you prefer klass over class_ then just be consistent. :).

Programming Recommendations

  • Comparisons to singletons like None should always be done with 'is' or 'is not'. Also, beware of writing "if x" when you really mean "if x is not None" — e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might be a value that's false in a Boolean context!
  • Class-based exceptions are always preferred over string-based exceptions. Modules or packages should define their own domain-specific base exception class, which should be subclassed from the built-in Exception class. Always include a class docstring. E.g.:

            class MessageError(Exception):
                """Base class for errors in the email package."""
  • Use string methods instead of the string module unless backward-compatibility with versions earlier than Python 2.0 is important. String methods are always much faster and share the same API with unicode strings.
  • Avoid slicing strings when checking for prefixes or suffixes. Use startswith() and endswith() instead, since they are cleaner and less error prone. For example:

            No:  if foo[:3] == 'bar':
            Yes: if foo.startswith('bar'):

    The exception is if your code must work with Python 1.5.2 (but let's hope not!).

  • Object type comparisons should always use isinstance() instead of comparing types directly. E.g.

            No:  if type(obj) is type(1):
            Yes: if isinstance(obj, int):

    When checking if an object is a string, keep in mind that it might be a unicode string too! In Python 2.3, str and unicode have a common base class, basestring, so you can do:

            if isinstance(obj, basestring):

    In Python 2.2, the types module has the StringTypes type defined for that purpose, e.g.:

            from types import StringTypes
            if isinstance(obj, StringTypes):

    In Python 2.0 and 2.1, you should do:

            from types import StringType, UnicodeType
            if isinstance(obj, StringType) or \
               isinstance(obj, UnicodeType) :
  • For sequences, (strings, lists, tuples), use the fact that empty sequences are false, so "if not seq" or "if seq" is preferable to "if len(seq)" or "if not len(seq)".
  • Don't write string literals that rely on significant trailing whitespace. Such trailing whitespace is visually indistinguishable and some editors (or more recently, reindent.py) will trim them.
  • Don't compare boolean values to True or False using == (bool types are new in Python 2.3):

            No:  if greeting == True:
            Yes: if greeting:

References

[1] PEP 7, Style Guide for C Code, van Rossum [2] http://www.python.org/doc/essays/styleguide.html [3] PEP 257, Docstring Conventions, Goodger, van Rossum [4] http://www.wikipedia.com/wiki/CamelCase [5] Barry's GNU Mailman/mimelib style guide http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/mimelib/mimelib/STYLEGUIDE.txt?rev=1.1&content-type=text/vnd.viewcvs-markup

Debian packages/meta

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

This is my personal repository of Debian packages. Some of these packages have newer versions available in the official Debian archive. Some of these packages are badly broken. In any case, do not report bugs about these packages to the BTS, instead, send me an email (ivo@debian.org) if you encounter any problems.

The packages in the stable part of the repository are mostly backports of packages from unstable.

These packages are apt-gettable; just put these lines in your /etc/apt/sources.list:

Unstable

deb http://home.o2w.net/~ivo/debian unstable/$(ARCH)/
deb http://home.o2w.net/~ivo/debian unstable/all/
deb-src http://home.o2w.net/~ivo/debian unstable/source/

Testing

deb http://home.o2w.net/~ivo/debian testing/$(ARCH)/
deb http://home.o2w.net/~ivo/debian testing/all/
deb-src http://home.o2w.net/~ivo/debian testing/source/

Stable

deb http://home.o2w.net/~ivo/debian stable/$(ARCH)/
deb http://home.o2w.net/~ivo/debian stable/all/
deb-src http://home.o2w.net/~ivo/debian stable/source/

Browse

To browse the directories and download what you need by hand:

Note: Although it says $(ARCH) in the URIs above, only i386 is really supported, it is my main development platform. Sometimes I do uploads for other architectures, mainly sparc.