~roadmr/ubuntu/precise/checkbox/0.13.1

« back to all changes in this revision

Viewing changes to checkbox/repository.py

  • Committer: Bazaar Package Importer
  • Author(s): Marc Tardif
  • Date: 2009-01-20 18:55:20 UTC
  • Revision ID: james.westby@ubuntu.com-20090120185520-s18m2hninrt53fki
Tags: 0.5
* New upstream version:
  * Added concept of hyper text view to display clickable links.
  * Added concept of properties to components.
  * Added pci information to launchpad report.
  * Added dmi information to launchpad report.
  * Added text area to keyboard test.
  * Removed sourcing of base postrm script.
  * Updated translations from Launchpad.
* Fixed handling of interrupt signal (LP: #327810)
* Fixed display of text in graphical interface (LP: #240374)
* Fixed support for regexes in blacklist and whitelist (LP: #327177)
* Fixed opening of subunit log file (LP: #325737)
* Fixed internet test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
# Copyright (c) 2008 Canonical
3
 
#
4
 
# Written by Marc Tardif <marc@interunion.ca>
5
 
#
6
 
# This file is part of Checkbox.
7
 
#
8
 
# Checkbox is free software: you can redistribute it and/or modify
9
 
# it under the terms of the GNU General Public License as published by
10
 
# the Free Software Foundation, either version 3 of the License, or
11
 
# (at your option) any later version.
12
 
#
13
 
# Checkbox is distributed in the hope that it will be useful,
14
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
# GNU General Public License for more details.
17
 
#
18
 
# You should have received a copy of the GNU General Public License
19
 
# along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
20
 
#
21
 
import os
22
 
import re
23
 
import logging
24
 
import posixpath
25
 
 
26
 
 
27
 
class RepositorySection(object):
28
 
    """
29
 
    Repository section which is essentially a container of entries. These
30
 
    map to the modules referenced in the configuration passed as argument
31
 
    to the constructor.
32
 
    """
33
 
 
34
 
    def __init__(self, config, name):
35
 
        """
36
 
        Constructor which takes a configuration instance and name as
37
 
        argument. The former is expected to contain directories and
38
 
        blacklist.
39
 
        """
40
 
        self._config = config
41
 
        self.name = name
42
 
        self._names = None
43
 
 
44
 
    @property
45
 
    def directories(self):
46
 
        """
47
 
        Directory contained for this sections.
48
 
        """
49
 
        directories = re.split(r"\s+", self._config.directories)
50
 
        return [posixpath.expanduser(d) for d in directories]
51
 
 
52
 
    def get_names(self):
53
 
        """
54
 
        Get all the module names contained in the directories for this
55
 
        section.
56
 
        """
57
 
        if self._names is None:
58
 
            if "whitelist" in self._config.attributes:
59
 
                self._names = re.split(r"\s+", self._config.whitelist)
60
 
            else:
61
 
                blacklist = []
62
 
                if "blacklist" in self._config.attributes:
63
 
                    blacklist = re.split(r"\s", self._config.blacklist)
64
 
 
65
 
                for directory in self.directories:
66
 
                    names = [p.replace(".py", "")
67
 
                        for p in os.listdir(directory)
68
 
                        if p.endswith(".py") and p != "__init__.py"]
69
 
                    self._names = list(set(names).difference(set(blacklist)))
70
 
 
71
 
        return self._names
72
 
 
73
 
    def get_arguments(self, name):
74
 
        config_name = "/".join([self.name, name])
75
 
        config = self._config.parent.get_section(config_name)
76
 
 
77
 
        return [config]
78
 
 
79
 
    def load_all(self):
80
 
        """
81
 
        Load all modules contained in this section.
82
 
        """
83
 
        entries = []
84
 
        for name in self.get_names():
85
 
            entries.append(self.load_entry(name))
86
 
 
87
 
        return entries
88
 
 
89
 
    def has_entry(self, name):
90
 
        """
91
 
        Check if the given name is in this section.
92
 
        """
93
 
        return name in self.get_names()
94
 
 
95
 
    def load_entry(self, name):
96
 
        """
97
 
        Load a single module by name from this section.
98
 
        """
99
 
        logging.info("Loading name %s from section %s",
100
 
            name, self.name)
101
 
 
102
 
        for directory in self.directories:
103
 
            path = posixpath.join(directory, "%s.py" % name)
104
 
            if posixpath.exists(path):
105
 
                globals = {}
106
 
                exec open(path) in globals
107
 
                if "factory" not in globals:
108
 
                    raise Exception, "Variable 'factory' not found: %s" % path
109
 
 
110
 
                arguments = self.get_arguments(name)
111
 
                return globals["factory"](*arguments)
112
 
 
113
 
        raise Exception, "Failed to find module '%s' in directories: %s" \
114
 
            % (name, self.directories)
115
 
 
116
 
 
117
 
class RepositoryManager(object):
118
 
    """
119
 
    Repository manager which is essentially a container of sections.
120
 
    """
121
 
 
122
 
    _section_factory = RepositorySection
123
 
 
124
 
    def __init__(self, config):
125
 
        """
126
 
        Constructor which takes a configuration instance as argument. This
127
 
        will be used to load sections by name.
128
 
        """
129
 
        self._config = config
130
 
 
131
 
    def load_section(self, name):
132
 
        """
133
 
        Load a section by name which must correspond to an entry in the
134
 
        configuration instance pased as argument to the constructor.
135
 
        """
136
 
        logging.info("Loading repository section %s", name)
137
 
        config = self._config.get_section(name)
138
 
        return self._section_factory(config, name)
139
 
 
140
 
 
141
 
class Repository(object):
142
 
    """
143
 
    Repository base class which should be inherited by each repository
144
 
    implementation.
145
 
    """
146
 
 
147
 
    required_attributes = []
148
 
    optional_attributes = []
149
 
 
150
 
    def __init__(self, config):
151
 
        """
152
 
        Constructor which takes a configuration instance as argument. This
153
 
        can be used to pass options to repositories.
154
 
        """
155
 
        self._config = config
156
 
        self._validate()
157
 
 
158
 
    def _validate(self):
159
 
        all_required_attributes = []
160
 
        all_optional_attributes = []
161
 
 
162
 
        cls = type(self)
163
 
        for cls_mro in cls.__mro__:
164
 
            for attr, descr in cls_mro.__dict__.iteritems():
165
 
                if attr == "required_attributes":
166
 
                    all_required_attributes.extend(descr)
167
 
                elif attr == "optional_attributes":
168
 
                    all_optional_attributes.extend(descr)
169
 
 
170
 
        if all_required_attributes and not self._config:
171
 
            raise Exception, \
172
 
                "Missing configuration section for required attributes: %s" \
173
 
                % ", ".join(all_required_attributes)
174
 
 
175
 
        if not self._config:
176
 
            return
177
 
 
178
 
        for attribute in all_required_attributes:
179
 
            if attribute not in self._config.attributes:
180
 
                raise Exception, \
181
 
                    "Configuration section '%s' missing required attribute: %s" \
182
 
                    % (self._config.name, attribute)
183
 
            elif self._config.attributes[attribute] == "":
184
 
                raise Exception, \
185
 
                    "Configuration section '%s' has empty required attribute: %s" \
186
 
                    % (self._config.name, attribute)
187
 
 
188
 
        for attribute in all_optional_attributes:
189
 
            if attribute not in self._config.attributes:
190
 
                self._config.attributes[attribute] = None
191
 
 
192
 
        all_attributes = all_required_attributes \
193
 
            + all_optional_attributes \
194
 
            + self._config.parent.get_defaults().attributes.keys()
195
 
        for attribute in self._config.attributes.keys():
196
 
            if attribute not in all_attributes:
197
 
                logging.info("Configuration section '%s' "
198
 
                    "contains unknown attribute: %s",
199
 
                    self._config.name, attribute)