Merge ~kissiel/plainbox:add-none-stock-report into plainbox:master

Proposed by Maciej Kisielewski
Status: Merged
Approved by: Maciej Kisielewski
Approved revision: 1ffc8b5b2773a827f3f970eeebb8e563265baca4
Merged at revision: fdaf5f21358dd3365c04387bbc08f47aac4bc76b
Proposed branch: ~kissiel/plainbox:add-none-stock-report
Merge into: plainbox:master
Diff against target: 111 lines (+71/-3)
3 files modified
plainbox/impl/launcher.py (+8/-3)
plainbox/impl/secure/config.py (+22/-0)
plainbox/impl/secure/test_config.py (+41/-0)
Reviewer Review Type Date Requested Status
Jonathan Cave (community) Approve
Review via email: mp+335821@code.launchpad.net

Description of the change

add option to specify 'none' as a stock_reports value in configs

To test it have a launcher that specifies

stock_reports = none

It should behave in the same way as

stock_reports =

Fixes LP:1741116

To post a comment you must log in.
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

The documentation for the option will come in checkbox-ng's branch that actually has the logic to handle the 'none' value.

Revision history for this message
Jonathan Cave (jocave) wrote :

Had a look at the code and it looks good to me.

The only criticism I have is that it wasn't all that clear to me what the OneOrTheOtherValidator was actually going to do from the name! May be something like DisjointSetValidator would sound a bit more formal and clear?

Approving otherwise.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/plainbox/impl/launcher.py b/plainbox/impl/launcher.py
2index 897d80c..034c613 100644
3--- a/plainbox/impl/launcher.py
4+++ b/plainbox/impl/launcher.py
5@@ -109,9 +109,14 @@ class LauncherDefinition1(LauncherDefinition):
6 stock_reports = config.Variable(
7 section='launcher',
8 kind=list,
9- validator_list=[config.SubsetValidator({
10- 'text', 'certification', 'certification-staging',
11- 'submission_files'})],
12+ validator_list=[
13+ config.SubsetValidator({
14+ 'text', 'certification', 'certification-staging',
15+ 'submission_files', 'none'}),
16+ config.OneOrTheOtherValidator(
17+ {'none'}, {'text', 'certification', 'certification-staging',
18+ 'submission_files'}),
19+ ],
20 default=['text', 'certification', 'submission_files'],
21 help_text=_('List of stock reports to use'))
22
23diff --git a/plainbox/impl/secure/config.py b/plainbox/impl/secure/config.py
24index 5d3b0e8..6d4cdf8 100644
25--- a/plainbox/impl/secure/config.py
26+++ b/plainbox/impl/secure/config.py
27@@ -834,6 +834,28 @@ class SubsetValidator(IValidator):
28 return False
29
30
31+class OneOrTheOtherValidator(IValidator):
32+ """
33+ A validator ensuring that values only from one or the other set are used.
34+ """
35+ def __init__(self, a_set, b_set):
36+ # the sets have to be disjoint
37+ assert(not a_set & b_set)
38+ self.a_set = set(a_set)
39+ self.b_set = set(b_set)
40+
41+ def __call__(self, variable, values):
42+ has_common_with_a = bool(self.a_set & set(values))
43+ has_common_with_b = bool(self.b_set & set(values))
44+ if has_common_with_a and has_common_with_b:
45+ return _('{} can only use values from {} or from {}'.format(
46+ variable.name, self.a_set, self.b_set))
47+
48+ def __eq__(self, other):
49+ if isinstance(other, OneOrTheOtherValidator):
50+ return self.a_set == other.a_set and self.b_set == other.b_set
51+
52+
53 @understands_Unset
54 class NotUnsetValidator(IValidator):
55 """
56diff --git a/plainbox/impl/secure/test_config.py b/plainbox/impl/secure/test_config.py
57index ce6d5d0..1efab12 100644
58--- a/plainbox/impl/secure/test_config.py
59+++ b/plainbox/impl/secure/test_config.py
60@@ -32,6 +32,7 @@ from plainbox.impl.secure.config import ConfigMetaData
61 from plainbox.impl.secure.config import KindValidator
62 from plainbox.impl.secure.config import NotEmptyValidator
63 from plainbox.impl.secure.config import NotUnsetValidator
64+from plainbox.impl.secure.config import OneOrTheOtherValidator
65 from plainbox.impl.secure.config import PatternValidator
66 from plainbox.impl.secure.config import ParametricSection
67 from plainbox.impl.secure.config import PlainBoxConfigParser, Config
68@@ -565,3 +566,43 @@ class NotEmptyValidatorTests(TestCase):
69 self.assertTrue(NotEmptyValidator("?") == NotEmptyValidator("?"))
70 self.assertTrue(NotEmptyValidator() != NotEmptyValidator("?"))
71 self.assertTrue(NotEmptyValidator() != object())
72+
73+
74+class OneOrTheOtherValidatorTests(TestCase):
75+
76+ class _Config(Config):
77+ var = Variable("The Name", kind=list)
78+
79+ def test_pass_validation(self):
80+ validator = OneOrTheOtherValidator({'foo'}, {'bar'})
81+ value = ['foo']
82+ self.assertIsNone(validator(self._Config.var, value))
83+ value = ['bar']
84+ self.assertIsNone(validator(self._Config.var, value))
85+
86+ def test_fail_validation(self):
87+ validator = OneOrTheOtherValidator({'foo'}, {'bar'})
88+ value = ['foo', 'bar']
89+ self.assertEquals(
90+ validator(self._Config.var, value),
91+ "The Name can only use values from {'foo'} or from {'bar'}")
92+
93+ def test_pass_empty(self):
94+ validator = OneOrTheOtherValidator({'foo'}, {'bar'})
95+ value = []
96+ self.assertIsNone(validator(self._Config.var, value))
97+
98+ def test_comparison_works(self):
99+ self.assertEqual(
100+ OneOrTheOtherValidator({'foo'}, {'bar'}),
101+ OneOrTheOtherValidator({'foo'}, {'bar'})
102+ )
103+ self.assertEqual(
104+ OneOrTheOtherValidator({1, 2}, {3, 4}),
105+ OneOrTheOtherValidator({2, 1}, {4, 3})
106+ )
107+ self.assertNotEqual(
108+ OneOrTheOtherValidator({1}, {2}),
109+ OneOrTheOtherValidator({1}, {'foo'})
110+ )
111+ self.assertNotEqual(OneOrTheOtherValidator({1}, {2}), object())

Subscribers

People subscribed via source and target branches