Merge lp:~james-w/linaro-image-tools/hwpack-create-config into lp:linaro-image-tools/11.11
- hwpack-create-config
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 34 |
Proposed branch: | lp:~james-w/linaro-image-tools/hwpack-create-config |
Merge into: | lp:linaro-image-tools/11.11 |
Diff against target: |
402 lines (+375/-0) 5 files modified
.bzrignore (+1/-0) .testr.conf (+3/-0) hwpack/config.py (+167/-0) hwpack/tests/__init__.py (+8/-0) hwpack/tests/test_config.py (+196/-0) |
To merge this branch: | bzr merge lp:~james-w/linaro-image-tools/hwpack-create-config |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexander Sack (community) | Approve | ||
Linaro Infrastructure | Pending | ||
Review via email: mp+33952@code.launchpad.net |
Commit message
Description of the change
Hi,
Here is a small branch to add the skeleton of the hwpack module with tests, and the start of
a hwpack.config for reading the configuration files specifying what to put in a hwpack.
You can read the description of the format at https:/
Thanks,
James
- 46. By James Westby
-
Add a testsuite function to run the tests.
- 47. By James Westby
-
Add a .testr.conf for the project.
- 48. By James Westby
-
Use a method to avoid hardcoding StringIO everywhere.
- 49. By James Westby
-
Use a helper assertion to reduce code duplication.
Michael Hudson-Doyle (mwhudson) wrote : | # |
I know this is late, but:
1) I would have appreciated some documentation on what the various properties on the Config option meant.
2) I'm sure there's a place for a _get_main_option helper -- origin, main and support at least are very similar.
Cheers,
mwh
Preview Diff
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2010-08-27 20:28:42 +0000 |
4 | @@ -0,0 +1,1 @@ |
5 | +.testrepository |
6 | |
7 | === added file '.testr.conf' |
8 | --- .testr.conf 1970-01-01 00:00:00 +0000 |
9 | +++ .testr.conf 2010-08-27 20:28:42 +0000 |
10 | @@ -0,0 +1,3 @@ |
11 | +[DEFAULT] |
12 | +test_command=python -m subunit.run $IDLIST |
13 | +test_id_list_default=hwpack.tests.test_suite |
14 | |
15 | === added directory 'hwpack' |
16 | === added file 'hwpack/__init__.py' |
17 | === added file 'hwpack/config.py' |
18 | --- hwpack/config.py 1970-01-01 00:00:00 +0000 |
19 | +++ hwpack/config.py 2010-08-27 20:28:42 +0000 |
20 | @@ -0,0 +1,167 @@ |
21 | +import ConfigParser |
22 | +import re |
23 | + |
24 | +class HwpackConfigError(Exception): |
25 | + pass |
26 | + |
27 | + |
28 | +class Config(object): |
29 | + """Encapsulation of a hwpack-create configuration.""" |
30 | + |
31 | + MAIN_SECTION = "hwpack" |
32 | + NAME_KEY = "name" |
33 | + NAME_REGEX = "[a-z0-9][a-z0-9+0.]+" |
34 | + INCLUDE_DEBS_KEY = "include-debs" |
35 | + SUPPORT_KEY = "support" |
36 | + SOURCES_ENTRY_KEY = "sources-entry" |
37 | + PACKAGES_KEY = "packages" |
38 | + PACKAGE_REGEX = NAME_REGEX |
39 | + ORIGIN_KEY = "origin" |
40 | + MAINTAINER_KEY = "maintainer" |
41 | + |
42 | + def __init__(self, fp): |
43 | + """Create a Config. |
44 | + |
45 | + :param fp: a file-like object containing the configuration. |
46 | + """ |
47 | + self.parser = ConfigParser.RawConfigParser() |
48 | + self.parser.readfp(fp) |
49 | + |
50 | + def validate(self): |
51 | + """Check that this configuration follows the schema. |
52 | + |
53 | + :raises HwpackConfigError: if it does not. |
54 | + """ |
55 | + if not self.parser.has_section(self.MAIN_SECTION): |
56 | + raise HwpackConfigError("No [%s] section" % self.MAIN_SECTION) |
57 | + self._validate_name() |
58 | + self._validate_include_debs() |
59 | + self._validate_support() |
60 | + self._validate_sections() |
61 | + |
62 | + @property |
63 | + def name(self): |
64 | + return self.parser.get(self.MAIN_SECTION, self.NAME_KEY) |
65 | + |
66 | + @property |
67 | + def include_debs(self): |
68 | + try: |
69 | + if not self.parser.get( |
70 | + self.MAIN_SECTION, self.INCLUDE_DEBS_KEY): |
71 | + return True |
72 | + return self.parser.getboolean( |
73 | + self.MAIN_SECTION, self.INCLUDE_DEBS_KEY) |
74 | + except ConfigParser.NoOptionError: |
75 | + return True |
76 | + |
77 | + @property |
78 | + def origin(self): |
79 | + try: |
80 | + origin = self.parser.get(self.MAIN_SECTION, self.ORIGIN_KEY) |
81 | + if not origin: |
82 | + return None |
83 | + return origin |
84 | + except ConfigParser.NoOptionError: |
85 | + return None |
86 | + |
87 | + @property |
88 | + def maintainer(self): |
89 | + try: |
90 | + maintainer = self.parser.get( |
91 | + self.MAIN_SECTION, self.MAINTAINER_KEY) |
92 | + if not maintainer: |
93 | + return None |
94 | + return maintainer |
95 | + except ConfigParser.NoOptionError: |
96 | + return None |
97 | + |
98 | + @property |
99 | + def support(self): |
100 | + try: |
101 | + support = self.parser.get(self.MAIN_SECTION, self.SUPPORT_KEY) |
102 | + if not support: |
103 | + return None |
104 | + return support |
105 | + except ConfigParser.NoOptionError: |
106 | + return None |
107 | + |
108 | + def _validate_name(self): |
109 | + try: |
110 | + name = self.name |
111 | + if not name: |
112 | + raise HwpackConfigError("Empty value for name") |
113 | + if re.match(self.NAME_REGEX, name) is None: |
114 | + raise HwpackConfigError("Invalid name: %s" % name) |
115 | + except ConfigParser.NoOptionError: |
116 | + raise HwpackConfigError( |
117 | + "No name in the [%s] section" % self.MAIN_SECTION) |
118 | + |
119 | + def _validate_include_debs(self): |
120 | + try: |
121 | + self.include_debs |
122 | + except ValueError: |
123 | + raise HwpackConfigError( |
124 | + "Invalid value for include-debs: %s" |
125 | + % self.parser.get("hwpack", "include-debs")) |
126 | + |
127 | + def _validate_support(self): |
128 | + support = self.support |
129 | + if support not in (None, "supported", "unsupported"): |
130 | + raise HwpackConfigError( |
131 | + "Invalid value for support: %s" % support) |
132 | + |
133 | + def _validate_section_sources_entry(self, section_name): |
134 | + try: |
135 | + sources_entry = self.parser.get( |
136 | + section_name, self.SOURCES_ENTRY_KEY) |
137 | + if not sources_entry: |
138 | + raise HwpackConfigError( |
139 | + "The %s in the [%s] section is missing the URI" |
140 | + % (self.SOURCES_ENTRY_KEY, section_name)) |
141 | + if len(sources_entry.split(" ", 1)) < 2: |
142 | + raise HwpackConfigError( |
143 | + "The %s in the [%s] section is missing the distribution" |
144 | + % (self.SOURCES_ENTRY_KEY, section_name)) |
145 | + if sources_entry.startswith("deb"): |
146 | + raise HwpackConfigError( |
147 | + "The %s in the [%s] section shouldn't start with 'deb'" |
148 | + % (self.SOURCES_ENTRY_KEY, section_name)) |
149 | + except ConfigParser.NoOptionError: |
150 | + raise HwpackConfigError( |
151 | + "No %s in the [%s] section" |
152 | + % (self.SOURCES_ENTRY_KEY, section_name)) |
153 | + |
154 | + def _validate_section_packages(self, section_name): |
155 | + try: |
156 | + packages = self.parser.get(section_name, self.PACKAGES_KEY) |
157 | + if not packages: |
158 | + raise HwpackConfigError( |
159 | + "The %s in the [%s] section is empty" |
160 | + % (self.PACKAGES_KEY, section_name)) |
161 | + for package in packages.split(" "): |
162 | + if not package: |
163 | + continue |
164 | + if re.match(self.PACKAGE_REGEX, package) is None: |
165 | + raise HwpackConfigError( |
166 | + "Invalid value in %s in the [%s] section: %s" |
167 | + % (self.PACKAGES_KEY, section_name, package)) |
168 | + except ConfigParser.NoOptionError: |
169 | + raise HwpackConfigError( |
170 | + "No %s in the [%s] section" |
171 | + % (self.PACKAGES_KEY, section_name)) |
172 | + |
173 | + def _validate_section(self, section_name): |
174 | + self._validate_section_sources_entry(section_name) |
175 | + self._validate_section_packages(section_name) |
176 | + |
177 | + def _validate_sections(self): |
178 | + sections = self.parser.sections() |
179 | + found = False |
180 | + for section_name in sections: |
181 | + if section_name == self.MAIN_SECTION: |
182 | + continue |
183 | + self._validate_section(section_name) |
184 | + found = True |
185 | + if not found: |
186 | + raise HwpackConfigError( |
187 | + "No sections other than [%s]" % self.MAIN_SECTION) |
188 | |
189 | === added directory 'hwpack/tests' |
190 | === added file 'hwpack/tests/__init__.py' |
191 | --- hwpack/tests/__init__.py 1970-01-01 00:00:00 +0000 |
192 | +++ hwpack/tests/__init__.py 2010-08-27 20:28:42 +0000 |
193 | @@ -0,0 +1,8 @@ |
194 | +import unittest |
195 | + |
196 | +def test_suite(): |
197 | + module_names = ['hwpack.tests.test_config', |
198 | + ] |
199 | + loader = unittest.TestLoader() |
200 | + suite = loader.loadTestsFromNames(module_names) |
201 | + return suite |
202 | |
203 | === added file 'hwpack/tests/test_config.py' |
204 | --- hwpack/tests/test_config.py 1970-01-01 00:00:00 +0000 |
205 | +++ hwpack/tests/test_config.py 2010-08-27 20:28:42 +0000 |
206 | @@ -0,0 +1,196 @@ |
207 | +from StringIO import StringIO |
208 | + |
209 | +from testtools import TestCase |
210 | + |
211 | +from hwpack.config import Config, HwpackConfigError |
212 | + |
213 | + |
214 | +class ConfigTests(TestCase): |
215 | + |
216 | + def test_create(self): |
217 | + config = Config(StringIO()) |
218 | + |
219 | + def get_config(self, contents): |
220 | + return Config(StringIO(contents)) |
221 | + |
222 | + def assertConfigError(self, contents, f, *args, **kwargs): |
223 | + e = self.assertRaises(HwpackConfigError, f, *args, **kwargs) |
224 | + self.assertEqual(contents, str(e)) |
225 | + |
226 | + def assertValidationError(self, contents, config): |
227 | + self.assertConfigError(contents, config.validate) |
228 | + |
229 | + def test_validate_no_hwpack_section(self): |
230 | + config = self.get_config("") |
231 | + self.assertValidationError("No [hwpack] section", config) |
232 | + |
233 | + def test_validate_no_name(self): |
234 | + config = self.get_config("[hwpack]\n") |
235 | + self.assertValidationError("No name in the [hwpack] section", config) |
236 | + |
237 | + def test_validate_empty_name(self): |
238 | + config = self.get_config("[hwpack]\nname = \n") |
239 | + self.assertValidationError("Empty value for name", config) |
240 | + |
241 | + def test_validate_invalid_name(self): |
242 | + config = self.get_config("[hwpack]\nname = ~~\n") |
243 | + self.assertValidationError("Invalid name: ~~", config) |
244 | + |
245 | + def test_validate_invalid_include_debs(self): |
246 | + config = self.get_config( |
247 | + "[hwpack]\nname = ahwpack\n" |
248 | + "include-debs = if you don't mind\n") |
249 | + self.assertValidationError( |
250 | + "Invalid value for include-debs: if you don't mind", config) |
251 | + |
252 | + def test_validate_invalid_supported(self): |
253 | + config = self.get_config( |
254 | + "[hwpack]\nname = ahwpack\nsupport = if you pay us\n") |
255 | + self.assertValidationError( |
256 | + "Invalid value for support: if you pay us", config) |
257 | + |
258 | + def test_validate_no_other_sections(self): |
259 | + config = self.get_config("[hwpack]\nname = ahwpack\n") |
260 | + self.assertValidationError( |
261 | + "No sections other than [hwpack]", config) |
262 | + |
263 | + def test_validate_other_section_no_sources_entry(self): |
264 | + config = self.get_config( |
265 | + "[hwpack]\nname = ahwpack\n\n[ubuntu]\n") |
266 | + self.assertValidationError( |
267 | + "No sources-entry in the [ubuntu] section", config) |
268 | + |
269 | + def test_validate_other_section_empty_sources_entry(self): |
270 | + config = self.get_config( |
271 | + "[hwpack]\nname = ahwpack\n\n" |
272 | + "[ubuntu]\nsources-entry = \n") |
273 | + self.assertValidationError( |
274 | + "The sources-entry in the [ubuntu] section is missing the URI", |
275 | + config) |
276 | + |
277 | + def test_validate_other_section_only_uri_in_sources_entry(self): |
278 | + config = self.get_config( |
279 | + "[hwpack]\nname = ahwpack\n\n" |
280 | + "[ubuntu]\nsources-entry = foo\n") |
281 | + self.assertValidationError( |
282 | + "The sources-entry in the [ubuntu] section is missing the " |
283 | + "distribution", config) |
284 | + |
285 | + def test_validate_other_section_sources_entry_starting_with_deb(self): |
286 | + config = self.get_config( |
287 | + "[hwpack]\nname = ahwpack\n\n" |
288 | + "[ubuntu]\nsources-entry = deb http://example.org/ " |
289 | + "foo main\n") |
290 | + self.assertValidationError( |
291 | + "The sources-entry in the [ubuntu] section shouldn't start " |
292 | + "with 'deb'", config) |
293 | + |
294 | + def test_validate_other_section_sources_entry_starting_with_deb_src(self): |
295 | + config = self.get_config( |
296 | + "[hwpack]\nname = ahwpack\n\n" |
297 | + "[ubuntu]\nsources-entry = deb-src http://example.org/ " |
298 | + "foo main\n") |
299 | + self.assertValidationError( |
300 | + "The sources-entry in the [ubuntu] section shouldn't start " |
301 | + "with 'deb'", config) |
302 | + |
303 | + def test_validate_other_section_no_packages(self): |
304 | + config = self.get_config( |
305 | + "[hwpack]\nname = ahwpack\n\n" |
306 | + "[ubuntu]\nsources-entry = foo bar\n") |
307 | + self.assertValidationError( |
308 | + "No packages in the [ubuntu] section", config) |
309 | + |
310 | + def test_validate_other_section_empty_packages(self): |
311 | + config = self.get_config( |
312 | + "[hwpack]\nname = ahwpack\n\n" |
313 | + "[ubuntu]\nsources-entry = foo bar\npackages = \n") |
314 | + self.assertValidationError( |
315 | + "The packages in the [ubuntu] section is empty", |
316 | + config) |
317 | + |
318 | + def test_validate_other_section_invalid_package_name(self): |
319 | + config = self.get_config( |
320 | + "[hwpack]\nname = ahwpack\n\n" |
321 | + "[ubuntu]\nsources-entry = foo bar\n" |
322 | + "packages = foo ~~ bar\n") |
323 | + self.assertValidationError( |
324 | + "Invalid value in packages in the [ubuntu] section: ~~", |
325 | + config) |
326 | + |
327 | + def test_validate_valid_config(self): |
328 | + config = self.get_config( |
329 | + "[hwpack]\nname = ahwpack\n\n" |
330 | + "[ubuntu]\nsources-entry = foo bar\n" |
331 | + "packages = foo bar\n") |
332 | + self.assertEqual(None, config.validate()) |
333 | + |
334 | + def test_name(self): |
335 | + config = self.get_config("[hwpack]\nname = ahwpack\n") |
336 | + self.assertEqual("ahwpack", config.name) |
337 | + |
338 | + def test_include_debs(self): |
339 | + config = self.get_config( |
340 | + "[hwpack]\nname = ahwpack\ninclude-debs = false\n") |
341 | + self.assertEqual(False, config.include_debs) |
342 | + |
343 | + def test_include_debs_defaults_true(self): |
344 | + config = self.get_config( |
345 | + "[hwpack]\nname = ahwpack\n") |
346 | + self.assertEqual(True, config.include_debs) |
347 | + |
348 | + def test_include_debs_defaults_true_on_empty(self): |
349 | + config = self.get_config( |
350 | + "[hwpack]\nname = ahwpack\ninclude-debs = \n") |
351 | + self.assertEqual(True, config.include_debs) |
352 | + |
353 | + def test_origin(self): |
354 | + config = self.get_config( |
355 | + "[hwpack]\nname = ahwpack\norigin = linaro\n") |
356 | + self.assertEqual("linaro", config.origin) |
357 | + |
358 | + def test_origin_default_None(self): |
359 | + config = self.get_config( |
360 | + "[hwpack]\nname = ahwpack\n") |
361 | + self.assertEqual(None, config.origin) |
362 | + |
363 | + def test_origin_None_on_empty(self): |
364 | + config = self.get_config( |
365 | + "[hwpack]\nname = ahwpack\norigin = \n") |
366 | + self.assertEqual(None, config.origin) |
367 | + |
368 | + def test_maintainer(self): |
369 | + maintainer = "Linaro Developers <linaro-dev@lists.linaro.org>" |
370 | + config = self.get_config( |
371 | + "[hwpack]\nname = ahwpack\nmaintainer = %s\n" % maintainer) |
372 | + self.assertEqual(maintainer, config.maintainer) |
373 | + |
374 | + def test_maintainer_default_None(self): |
375 | + config = self.get_config( |
376 | + "[hwpack]\nname = ahwpack\n") |
377 | + self.assertEqual(None, config.maintainer) |
378 | + |
379 | + def test_maintainer_None_on_empty(self): |
380 | + config = self.get_config( |
381 | + "[hwpack]\nname = ahwpack\nmaintainer = \n") |
382 | + self.assertEqual(None, config.maintainer) |
383 | + |
384 | + def test_support_supported(self): |
385 | + config = self.get_config( |
386 | + "[hwpack]\nname = ahwpack\nsupport = supported\n") |
387 | + self.assertEqual("supported", config.support) |
388 | + |
389 | + def test_support_unsupported(self): |
390 | + config = self.get_config( |
391 | + "[hwpack]\nname = ahwpack\nsupport = unsupported\n") |
392 | + self.assertEqual("unsupported", config.support) |
393 | + |
394 | + def test_support_default_None(self): |
395 | + config = self.get_config( |
396 | + "[hwpack]\nname = ahwpack\n") |
397 | + self.assertEqual(None, config.support) |
398 | + |
399 | + def test_support_None_on_empty(self): |
400 | + config = self.get_config( |
401 | + "[hwpack]\nname = ahwpack\nsupport = \n") |
402 | + self.assertEqual(None, config.support) |
looks like a good start. merged.