Python Programming, news on the Voidspace Python Projects and all things techie.

Pythonutils API Documentation

emoticon:car Along with the new version of ConfigObj are new auto-generated API docs.

These can be found over at :

Pythonutils API Docs

These have been created with the Epydoc 3.0 alpha. As a result, they are much better looking (and hopefully useful) than their predecessor. Moving a lot of the tests out of the main module has helped with this.

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-07 23:03:28 | |

Categories: , ,

ConfigObj New Features

emoticon:target A new version of ConfigObj is now available. As well as a few bugfixes (and the file size shrinking 40% due to the separation of the tests and changelog), there are several important new features.

Despite being relatively easy to code, these greatly extend the capabilities of ConfigObj. These extracts from the docs summarise what is new.

  • Empty Values are now valid syntax, with a new option to write them
  • Copy Mode allows the creation of default config files from a configspec, including comments
  • unrepr mode allows for the storing and retrieving of basic Python datatypes

Empty values

From Empty Values.

Many config files from other applications allow empty values. As of version 4.3.0, ConfigObj will read these as an empty string.

A new option/attribute has been added (write_empty_values) to allow ConfigObj to write empty strings as empty values.

from configobj import ConfigObj
cfg = '''
    key =
    key2 = # a comment
config = ConfigObj(cfg)
print config
{'key': '', 'key2': ''}

config.write_empty_values = True
for line in config.write():
    print line

key =
key2 =     # a comment

Copy Mode

From Copy Mode.

Because you can specify default values in your configspec, you can use ConfigObj to write out default config files for your application.

However, normally values supplied from a default in a configspec are not written out by the write method.

To do this, you need to specify copy=True when you call validate. As well as not marking values as default, all the comments in the configspec file will be copied into your ConfigObj instance.

from configobj import ConfigObj
from validate import Validator
vdt = Validator()
config = ConfigObj(configspec='default.ini')
config.filename = 'new_default.ini'
config.validate(vdt, copy=True)


There are functions to assist in the automatic creation of a configspec, in the ConfigPersist Module.

unrepr mode

From unrepr mode.

The unrepr option allows you to store and retrieve the basic Python data-types using config files. It has to use a slightly different syntax to normal ConfigObj files. Unsurprisingly it uses Python syntax.

This means that lists are different (they are surrounded by square brackets), and strings must be quoted.

The types that unrepr can work with are :

strings, lists tuples
None, True, False
dictionaries, integers, floats
longs and complex numbers

You can't store classes, types or instances.

unrepr uses repr(object) to write out values, so it currently doesn't check that you are writing valid objects. If you attempt to read an unsupported value, ConfigObj will raise a configobj.UnknownType exception.

Values that are triple quoted cased. The triple quotes are removed before converting. This means that you can use triple quotes to write dictionaries over several lines in your config files. They won't be written like this though.

If you are writing config files by hand, for use with unrepr, you should be aware of the following differences from normal ConfigObj syntax :

List : ['A List', 'With', 'Strings']
Strings : "Must be quoted."
Backslash : "The backslash must be escaped \\"

These all follow normal Python syntax.

So ConfigObj can now be used for simple (as in easy) data persistence. Move over YAML. Wink

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-07 22:51:40 | |

Categories: ,

ConfigObj 4.3.0

emoticon:world ConfigObj 4.3.0 is now released.

This has several bugfixes, as well as several major feature enhancements.

You can download it from : 244Kb

What is ConfigObj ?

ConfigObj is a simple but powerful config file reader and writer: an ini file round tripper. Its main feature is that it is very easy to use, with a straightforward programmer's interface and a simple syntax for config files. It has lots of other features though :

  • Nested sections (subsections), to any level

  • List values

  • Multiple line values

  • String interpolation (substitution)

  • Integrated with a powerful validation system

    • including automatic type checking/conversion
    • repeated sections
    • and allowing default values
  • All comments in the file are preserved

  • The order of keys/sections is preserved

  • No external dependencies

  • Full Unicode support

  • A powerful unrepr mode for storing basic datatypes

What's New ?

Moved the tests and the CHANGELOG (etc) into a separate file. This has reduced the size of by about 40%.

Added the unrepr mode to reading and writing config files. Thanks to Kevin Dangoor for this suggestion.

Empty values are now valid syntax. They are read as an empty string ''. (key =, or key = # comment.)

validate now honours the order of the configspec.

Added the copy mode to validate. Thanks to Louis Cordier for this suggestion.

Fixed bug where files written on windows could be given '\r\r\n' line terminators.

Fixed bug where last occurring comment line could be interpreted as the final comment if the last line isn't terminated.

Fixed bug where nested list values would be flattened when write is called. Now sub-lists have a string representation written instead.

Deprecated encode and decode methods instead.

You can now pass in a ConfigObj instance as a configspec (remember to read the configspec file using list_values=False).

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-07 22:36:19 | |

Categories: ,

Coding Style & Standard

emoticon:mobile This is a brief outline of the coding style and standards I have picked up along the way. I attempt to stick to these when coding my projects [1], bearing in mind that a foolish consistency is the hobgoblin of little mind.

Most of these come straight from PEP 8, a few from working on ConfigObj with Nicola Larosa and the rest are the product of my own warped imagination. Smile

There is also a sensible list of Python coding style guidelines at Python Idioms and Efficiency Suggestions.

Four Space Indentation

And definitely no tabs.


I prefer docstrings with either of the following two styles :

def function_class_or_method(object):
    """A single line docstring."""


def function_class_or_method(object):
    Several lines of docstring.

    Preferably using ReST 'markup'.

Line Length

Maximum line length of 79 characters. Longer lines should be wrapped by surrounding expressions in parentheses rather than using \.

Long strings can be split across several lines using parentheses :

('This is an excessively long string. '
'So, what we can do is split it across, '
'several %s. Instead of one long one. Good hey ?' %

Note that the single value for string formatting doesn't have a trailing comma to turn it into a tuple. They annoy me. Razz

I also prefer single quotes to double quotes.

Where long expressions go over more than one line, it is helpful to indent lines after the first one. This shows that they belong to each other.

result = (question1() + question2() + question3() +
    question4() + question5() + 27)

Line Spacings

Functions and methods should be separated with a single blank line. Class definitions with two blank lines.

Normally variable definitions don't need a blank line between them, unless they are logically distinct and you want to separate them.

Logical chunks of code within function/method definitions can have a blank line, if you want to visually separate them.

Any blank lines in indented code that falls inside a function or method, should have a single comment marker. This assists code folding in some editors, but also makes a visual difference between blank lines separating methods and blank lines separating chunks of code.

"""Module docstring."""

var1 = 'Some Value'
var2 = "Another value."

CONST1 = 'Important constant'
CONST2 = 'Another constant'

class ClassName(object):
    """Class docstring."""

    class_attribute = 3

    def __init__(self):
        """Method docstring."""

    def another_method(self):
        """Another docstring."""
        print 'A method.'
        x = 3

class AnotherClass(object):


No inline comments, comments should be above the line they comment.

It can be useful to precede comments with FIXME: or NOTE: if it clarifies the intent of the comment.

Parentheses Round Expressions

Some expressions can get complicated. Parentheses can (and should) be used to make them less ambiguous. This is for the sake of people who read the code, even if it doesn't matter to the Python parser.

if (test1 and test2) or (test3 or test4):

Programming Rules

These few rules apply to how you code, rather than just style.

  • When testing for None, use is.

    if obj is None

    This is because None is a singleton and the identity test is more efficient than testing for equality.

  • Classes should inherit from object.

    If a class has no base classes, then it is better to make it a new style class and inherit from object.

    class Something(object):

  • No mutable objects as default arguments.

    Default arguments are created on parsing, not when a function/method is called. This means you mustn't use mutable objects (like dictionaries or lists) as default arguments.

    Instead you should do :

    def function(default=None):
        if default is None:
            default = {}
  • No bare excepts. If you really want to catch all exceptions, then use except Exception:, but it is many times better to only trap exceptions that you expect. Doing otherwise will suppress a multitude of bugs.

  • If you are writing a module, always define __all__.


Three simple rules :

  • Imports at the top of modules (or the top of functions if they are local).

  • Avoid from xxx import * wherever possible.

  • I think it looks nicer to put imports on separate lines.

    import xxx should come before from xxx import ....

    Standard library before extension modules.

Naming Conventions

There are various Python naming conventions I use. Consistency here is certainly good as it helps to identify what sort of object names point to. I think the conventions I use basically follow PEP8.

  • Module names should be lowercase with underscores instead of spaces. (And should be valid module names for importing.)
  • Variable names and function/method names should also be lowercase with underscores to separate words.
  • Class names should be CamelCase (uppercase letter to start with, words run together, each starting with an uppercase letter).
  • Module constants should be all uppercase.

E.g. You would typically have module.ClassName.method_name.

Module names in CamelCase with a main class name identical to the module name are annoying. (e.g. ConfigParser.ConfigParser, which should always be spelt configobj.ConfigObj.)

Also, variables, functions, methods and classes which aren't part of your public API, should begin with a single underscore.


And finally, you should always have whitespace around operators and after punctuation. The exception is default arguments to methods and functions.

E.g. def function(default=argument): and x = a * b + c

By the way, I usually have my editor set to display whitespace. I leave no trailing whitespace. I don't have the editor set to remove trailing spaces on save though, as this strips indentation on blank lines. This can mess up code folding in Lunix editors. Wink

This odd little coding habit is definitely the fault of Nicola Larosa. Laughing

[1]and I would prefer it if contributors stuck to a similar style. Smile

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-07 12:07:10 | |

Categories: ,

Benefits of Open Source

emoticon:ghostradio A visitor to my website [1] asked me a question about Open Source, specifically how business can benefit from Open Source.

The answers are partly obvious, but it's good to see Open Source gaining traction in the business world. Below are a hasty look at some of the reasons why :

A lot of companies benefit greatly from Open Source. For example Linux, Apache, Open Office and Python are all big open source projects that a huge number of businesses rely on for their day to day operation.

Perhaps a better question is, how can companies benefit from releasing their code as Open Source.

There are lots of ways this can be beneficial to a company. Off the top of my head, this includes :

  • Getting more developers to work on a project

    Open sourcing a project is a good way of getting more developers to work on a project. This is obviously most useful when the project is important to a company, but not a core part of their revenue stream.

    One example might be a company that delivers its digital products from a distributed application server they have developed themselves.

    They don't earn income directly from the server, yet their business depends on it. It could be very beneficial to them to see a developer community working on improving the code with them. Smile

  • Publicity

    Open Source projects will bring people to a company website as well as other publicity.

    Open Source tends to create a fanatical following amongst developers and users. This can be very valuable to a company [2].

  • As part of the business plan

    Some companies release projects as open source, with a restrictive license (e.g. the GPL) as well as selling commercial versions. The Trolltech QT python binding is an example of this.

    Undoubtedly making the project available free to Open Source developers means the project is more likely to be chosen for commercial projects.

  • Enthusiastic developers

    A lot of contributors to Open Source project are high quality professionals. Conversely, a lot of high quality developers prefer to work on Open Source projects.

    Allowing your team to work on Open Source projects (whether directly related to your business or not), makes it more likely that you will be able to attract and keep motivated quality workers.

[1]Don't ask me why they chose to ask me. Confused
[2]But it has to be managed wisely. If the community feels your decisions harm the Open Source projects this can quickly work against you.

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-05 16:23:28 | |

Categories: ,

A Handy Little Tool

emoticon:drive For reasons which I won't go into [1], I've just had my bacon saved by the handy little tool freeundelete.

All I have to say is that it does what it says on the box, and it's free. Very Happy

[1]I'll give you a clue with the phrase; a weekend's work.

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-02 21:53:10 | |


Python 411 Interview

emoticon:podcast Yesterday (Saturday April 1st), I had an interview with Ron Stephens. Ron runs the Python 411 Podcast Series, which explore various topics of interest to Python beginners.

Ron interviewed me about my open source projects, but also how I have come to produce so much in only three years of part time hacking [1]. Smile

I really enjoyed the interview (Ron is a great host), hopefully a few of you will also find it interesting.

You can listen to the interview, by visiting :

The Python Learning Foundation
[1]Unfortunately I lose my amateur status in two weeks now. Wink

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-02 16:51:49 | |

Categories: ,

DivX to DVD

emoticon:movies Today I've been playing with turning AVI files into DVDs.


Non-technical description following !

I did this using several freeware tools :

The steps are :

  1. Convert the AVI to an MPEG
  2. Convert the MPEG to DVD files
  3. Burn the DVD

I used the two tutorials :

For the third step I used Nero 7. I had to download the demo version via a Torrent Client [1]. Anyone know of a decent freeware DVD burning tool ?

Anyway, it worked fine. It looks like DVDAuthor has decent tools for putting together good looking DVDs. Smile

[1]I feel a bit of a traitor for not using a Python client, but BitComet is nice.

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-01 23:19:51 | |

Categories: ,

rest2web Gets a Facelift

emoticon:podcast rest2web finally gets some attention. Very Happy

To start with it is only a facelift on the website, but expect new features and bugfixes to follow soon.

Thanks to Fuchsiashockdesign for the new template. It will soon also be applied to :

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-01 23:07:55 | |

Categories: ,


emoticon:html A friend has just designed a new look template for me.

This will be the basis of the websites for :

I'm sure you'll agree it's a great improvement. Razz

I've been tweaking the layout and CSS to work with the output of rest2web.

I've installed two new Firefox Extensions to assist me. They are both a great help. Firefox rocks.

  • CSSViewer

    This lets you see the CSS rules in effect for any element on a page.

  • IE Tab

    This lets you view a page with the IE rendering engine, within a Firefox tab.

    This makes developing for both browsers so much easier.

Unfortunately I'm still having fiddly CSS problems.

For an image that has a target, docutils generates HTML like the following :

<a class="reference image-reference" href="images/screenshot_big.jpg">
<div align="center" class="align-center">
   <img alt="Building with rest2web" class="image align-center"
     src="images/screenshot.jpg" style="width: 410px; height: 308px;" />

Which is invalid XHTML because you shouldn't put a div inside an anchor.

When you visit the link, the image gets surrounded with an ugly purple border. In order to change this, I've tried various permutations of the following CSS :

.image-reference a:visited  {
    text-decoration: none
    border-colour: black;

Firefox steadfastly ignores all my efforts. Sad


The following CSS works for Firefox, but not IE.

a.image-reference:visited {
    color: #999999;

Like this post? Digg it or it.

Posted by Fuzzyman on 2006-04-01 14:17:59 | |

Categories: , ,

Hosted by Webfaction