Merge lp:~james-w/linaro-image-tools/hwpack-create-config into lp:linaro-image-tools/11.11

Proposed by James Westby
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
Reviewer Review Type Date Requested Status
Alexander Sack (community) Approve
Linaro Infrastructure Pending
Review via email: mp+33952@code.launchpad.net

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://wiki.linaro.org/Platform/UserPlatforms/Specs/10.11/HardwarePacks#hwpack-create

Thanks,

James

To post a comment you must log in.
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.

Revision history for this message
Alexander Sack (asac) wrote :

looks like a good start. merged.

review: Approve
Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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)

Subscribers

People subscribed via source and target branches