New python-debian feature: Dependency Parsing

Since my merge commit of this afternoon python-debian has grown dependency parsing support.

(But first things first: you know about python-debian, don't you? If you don't, and you always wanted to program with Debian-related files with Python, then shame on you!)

Thus far, playing with Packages-like files using dictionary-like objects was already as simple as (quoting from /usr/share/doc/python-debian/examples/deb822/grep-maintainer):

for pkg in deb822.Packages.iter_paragraphs(file('/var/lib/dpkg/status')):
    if pkg.has_key('Maintainer') and maint_RE.search(pkg['maintainer']):
        print pkg['package']

However, it was a bit unfortunate that Depends-like fields were only returned as strings. Now each package (as iterated upon in the above snippet) is equipped with a .relations property returning a dictionary of inter-package relationship fields. Looking up keys like "depends" you will get back a conjunctive normal form (CNF) representation of dependencies, together with parsed constraints on version or architectures, if any.

A simple example is shipped as /usr/share/doc/python-debian/examples/deb822/depgraph, which outputs a labeled Graphviz script of all inter-package dependencies extracted from a Packages file. Here is its most relevant snippet:

name = pkg['package']
rels = pkg.relations
for deps in rels['depends']:
    if len(deps) == 1:
        emit_arc(name, deps[0]['name'])
    else:   # output an OR node
        or_node = get_id()
        emit_arc(name, or_node)
        emit_node(or_node, 'OR')
        for dep in deps:
            emit_arc(or_node, dep['name'].lower())

The appropriate sub-classes of Deb822 have been customized with the knowledge of which inter-package relationship fields are supported in their stanzas (e.g. Build-Depends are supported by Sources, but not by Packages; the other way around for Recommends).

Testing from the git repo is more than welcome.