~doctormo/apt-cat/trunk

« back to all changes in this revision

Viewing changes to AptCategory/__init__.py

  • Committer: Martin Owens
  • Date: 2010-10-31 19:49:17 UTC
  • Revision ID: doctormo@gmail.com-20101031194917-07y6w88mkcbsnuge
Inital commit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright 2010 Martin Owens
 
3
#
 
4
# This program is free software: you can redistribute it and/or modify
 
5
#  it under the terms of the GNU General Public License as published by
 
6
#  the Free Software Foundation, either version 3 of the License, or
 
7
#  (at your option) any later version.
 
8
#
 
9
#  This program is distributed in the hope that it will be useful,
 
10
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
#  GNU General Public License for more details.
 
13
#
 
14
#  You should have received a copy of the GNU General Public License
 
15
#  along with this program.  If not, see <http://www.gnu.org/licenses/>
 
16
#
 
17
"""
 
18
Finding packages in Apt by category.
 
19
 
 
20
To make a package available simply tell apt that it enhances one of the apt-category-* packages.
 
21
"""
 
22
 
 
23
import os
 
24
import apt.cache
 
25
import logging
 
26
 
 
27
__appname__ = "apt-cat"
 
28
__version__ = "0.2"
 
29
 
 
30
PKG_TEMP  = "apt-category-%s"
 
31
CACHES    = apt.cache.Cache()
 
32
 
 
33
class NoPackageError(KeyError):
 
34
    """Specific package couldn't be found"""
 
35
    pass
 
36
 
 
37
class NoCategoriesError(ValueError):
 
38
    """No categories can be found, non installed."""
 
39
    pass
 
40
 
 
41
class NoPackagesError(ValueError):
 
42
    """No packages can be found in this category."""
 
43
    pass
 
44
 
 
45
class NoCategoryError(KeyError):
 
46
    """The specified category can't be found. Not installed."""
 
47
    pass
 
48
 
 
49
 
 
50
class Category(object):
 
51
    """A package category"""
 
52
    def __init__(self, apt_package):
 
53
        self._pkg = apt_package
 
54
        self._cand = self._pkg.candidate
 
55
 
 
56
    @property
 
57
    def name(self):
 
58
        """Return the summary as the name"""
 
59
        return self._cand.summary.title()
 
60
 
 
61
    @property
 
62
    def cid(self):
 
63
        """Return the part of the package name as the category id"""
 
64
        return self._pkg.name.split('-')[-1]
 
65
 
 
66
    @property
 
67
    def pid(self):
 
68
        """Return the package name and the package id"""
 
69
        return self._pkg.name
 
70
 
 
71
 
 
72
class Package(object):
 
73
    """Cover an installable package."""
 
74
    def __init__(self, apt_package):
 
75
        self._pkg  = apt_package
 
76
        self._cand = self._pkg.candidate
 
77
 
 
78
    @property
 
79
    def name(self):
 
80
        """Return the name of the package"""
 
81
        return self._pkg.name.replace('-', ' ').title()
 
82
 
 
83
    @property
 
84
    def pid(self):
 
85
        """Return the package identifier"""
 
86
        return self._pkg.name
 
87
 
 
88
    @property
 
89
    def summary(self):
 
90
        """Return the short one line summary"""
 
91
        return self._cand.summary
 
92
 
 
93
    @property
 
94
    def description(self):
 
95
        """Return the long description"""
 
96
        return self._cand.description
 
97
 
 
98
    def is_installed(self):
 
99
        """Return true is the package is installed."""
 
100
        return self._pkg.is_installed
 
101
 
 
102
 
 
103
 
 
104
def _it_rev_dep(package_name, relationship, installed=None):
 
105
    """Iterate over reverse dependancies"""
 
106
    already = []
 
107
    package = CACHES[package_name]
 
108
    for dep in package._pkg.rev_depends_list:
 
109
        # We like the wrapper classes from python-apt
 
110
        pkg = apt.package.Package(CACHES, dep.parent_pkg)
 
111
        # Only return unique items, suspect versions from locations.
 
112
        is_unique = not pkg.name in already
 
113
        if dep.dep_type == relationship and is_unique:
 
114
            if installed == None or pkg.is_installed == installed:
 
115
                already.append(pkg.name)
 
116
                yield pkg
 
117
 
 
118
 
 
119
def iterate_categories(installed=None):
 
120
    """Iterate over available/installed package categories"""
 
121
    pkg = None
 
122
    try:
 
123
        for pkg in _it_rev_dep('apt-cat', 'Depends', installed):
 
124
            yield Category(pkg)
 
125
    except KeyError:
 
126
        raise NoPackageError("Apt-cat isn't installed. Please install first.")
 
127
    if not pkg:
 
128
        raise NoCategoriesError("No categories found")
 
129
 
 
130
 
 
131
def iterate_packages(categories, installed=None):
 
132
    """Iterate over packages available in the given category."""
 
133
    if not isinstance(categories, list):
 
134
        categories = [ categories ]
 
135
    dep = None
 
136
    category = None
 
137
    for category in categories:
 
138
        if isinstance(category, Category):
 
139
            pkg = category.pid
 
140
        else:
 
141
            pkg = PKG_TEMP % category
 
142
        try:
 
143
            for dep in _it_rev_dep(pkg, 'Enhances', installed):
 
144
                yield Package(dep)
 
145
        except KeyError:
 
146
            raise NoCategoryError("Category %s not found." % pkg)
 
147
    if not dep:
 
148
        raise NoPackagesError("No packages found in %s." % categories)
 
149