~ubuntu-branches/ubuntu/maverick/python-debian/maverick

« back to all changes in this revision

Viewing changes to examples/debtags/pkgwalk

  • Committer: Bazaar Package Importer
  • Author(s): John Wright
  • Date: 2008-04-30 23:58:24 UTC
  • mfrom: (1.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080430235824-iq9mp0fbd0efmruv
Tags: 0.1.10
* debian_bundle/deb822.py, tests/test_deb822.py:
  - Do not cache _CaseInsensitiveString objects, since it causes case
    preservation issues under certain circumstances (Closes: #473254)
  - Add a test case
* debian_bundle/deb822.py:
  - Add support for fixed-length subfields in multivalued fields.  I updated
    the Release and PdiffIndex classes to use this.  The default behavior for
    Release is that of apt-ftparchive, just because it's simpler.  Changing
    the behavior to resemble dak requires simply setting the
    size_field_behavior attribute to 'dak'.  (Ideally, deb822 would detect
    which behavior to use if given an actual Release file as input, but this
    is not implemented yet.)  (Closes: #473259)
  - Add support for Checksums-{Sha1,Sha256} multivalued fields in Dsc and
    Changes classes
* debian/control:
  - "python" --> "Python" in the Description field
  - Change the section to "python"

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
#
 
3
# Copyright (C) 2007  Enrico Zini <enrico@debian.org>
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify it under
 
6
# the terms of the GNU General Public License as published by the Free Software
 
7
# Foundation; either version 2 of the License, or (at your option) any later
 
8
# version.
 
9
 
 
10
# Navigate among related Debian packages
 
11
 
 
12
import sys
 
13
 
 
14
# Requires python-extractor, python-magic and python-debtags
 
15
from debian_bundle import debtags
 
16
import re
 
17
from optparse import OptionParser
 
18
import apt
 
19
 
 
20
 
 
21
VERSION="0.1"
 
22
 
 
23
class Parser(OptionParser):
 
24
        def __init__(self, *args, **kwargs):
 
25
                OptionParser.__init__(self, *args, **kwargs)
 
26
 
 
27
        def error(self, msg):
 
28
                sys.stderr.write("%s: error: %s\n\n" % (self.get_prog_name(), msg))
 
29
                self.print_help(sys.stderr)
 
30
                sys.exit(2)
 
31
 
 
32
if __name__ == '__main__':
 
33
        parser = Parser(usage="usage: %prog [options] pkgname",
 
34
                        version="%prog "+ VERSION,
 
35
                        description="walk through Debian packages")
 
36
        parser.add_option("--tagdb", default="/var/lib/debtags/package-tags", help="Tag database to use (default: %default)")
 
37
 
 
38
        (options, args) = parser.parse_args()
 
39
 
 
40
        if len(args) == 0:
 
41
                parser.error("Please provide the name of an initial package")
 
42
 
 
43
        # Read full database 
 
44
        db = debtags.DB()
 
45
        tagFilter = re.compile(r"^special::.+$|^.+::TODO$")
 
46
        db.read(open(options.tagdb, "r"), lambda x: not tagFilter.match(x))
 
47
 
 
48
        aptCache = apt.Cache()
 
49
 
 
50
        # Maximum number of previous packages to remember 
 
51
        maxlen = 5
 
52
        # Initial package selection
 
53
        trail = [ args[0] ]
 
54
 
 
55
        # Loop until the user chooses to quit
 
56
        done = False
 
57
        while not done:
 
58
                # Compute a package weight according to how old it is in the
 
59
                # trail
 
60
                pkgweight = {}
 
61
                for idx, pkg in enumerate(trail):
 
62
                        pkgweight[pkg] = 1.-(idx/maxlen)
 
63
 
 
64
                # For every tag, find the number of packages in trail that have the tag
 
65
                tagscores = {}
 
66
                for pkg in trail:
 
67
                        for tag in db.tagsOfPackage(pkg):
 
68
                                if tag in tagscores:
 
69
                                        tagscores[tag] += pkgweight[pkg]
 
70
                                else:
 
71
                                        tagscores[tag] = pkgweight[pkg]
 
72
 
 
73
                # Divide every tag score by the number of packages in the trail,
 
74
                # obtaining a 'tag weight'.  A package can be later scored by summing
 
75
                # the weight of all its tags.
 
76
                for tag in tagscores.iterkeys():
 
77
                        tagscores[tag] = float(tagscores[tag]) / float(len(trail))
 
78
 
 
79
                # Find the merged tagset of the packages in trail
 
80
                trailtags = set(tagscores.keys())
 
81
 
 
82
                # Get the list of packages whose tagsets intersect the trail tagset
 
83
                nextpkgs = set()
 
84
                for pkg, tags in db.iterPackagesTags():
 
85
                        if trailtags & tags:
 
86
                                nextpkgs.add(pkg)
 
87
 
 
88
                # Score every package by the sum of the weight of its tags
 
89
                def pkgscore(pkg):
 
90
                        score = 0.0
 
91
                        for tag in db.tagsOfPackage(pkg):
 
92
                                if tag in tagscores:
 
93
                                        score += tagscores[tag]
 
94
                        return score
 
95
                
 
96
                # Show the first 20 packages in reverse score order
 
97
                #display = sorted(nextpkgs - set(trail), key=pkgscore, reverse=True)[:20]
 
98
                display = sorted(nextpkgs, key=pkgscore, reverse=True)[:20]
 
99
                for num, pkg in enumerate(display):
 
100
                        aptpkg = aptCache[pkg]
 
101
                        desc = aptpkg.rawDescription.split("\n")[0]
 
102
                        print "%2d) %s - %s" % (num + 1, pkg, desc)
 
103
 
 
104
                # Ask the user to choose a new package
 
105
                while True:
 
106
                        ans = raw_input("> ").strip()
 
107
                        if ans[0] == 'q':
 
108
                                done = True
 
109
                                break
 
110
                        elif ans.isdigit():
 
111
                                num = int(ans) - 1
 
112
                                if num < len(display):
 
113
                                        # TODO: on a different kind of interface, display the full
 
114
                                        # description of pkg
 
115
                                        trail = [display[num]] + trail[:maxlen]
 
116
                                        break
 
117
                                else:
 
118
                                        print "The number is too high"
 
119
 
 
120
 
 
121
# vim:set ts=4 sw=4: