Merge lp:~kissiel/checkbox/validation-rework into lp:checkbox
- validation-rework
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Sylvain Pineau |
Approved revision: | 4514 |
Merged at revision: | 4511 |
Proposed branch: | lp:~kissiel/checkbox/validation-rework |
Merge into: | lp:checkbox |
Diff against target: |
969 lines (+222/-242) 12 files modified
plainbox/plainbox/impl/unit/category.py (+6/-22) plainbox/plainbox/impl/unit/concrete_validators.py (+57/-0) plainbox/plainbox/impl/unit/exporter.py (+12/-22) plainbox/plainbox/impl/unit/file.py (+2/-7) plainbox/plainbox/impl/unit/job.py (+48/-72) plainbox/plainbox/impl/unit/manifest.py (+11/-14) plainbox/plainbox/impl/unit/packaging.py (+6/-6) plainbox/plainbox/impl/unit/template.py (+8/-8) plainbox/plainbox/impl/unit/testplan.py (+21/-32) plainbox/plainbox/impl/unit/unit.py (+14/-47) plainbox/plainbox/impl/unit/unit_with_id.py (+7/-12) plainbox/plainbox/impl/unit/validators.py (+30/-0) |
To merge this branch: | bzr merge lp:~kissiel/checkbox/validation-rework |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sylvain Pineau (community) | Approve | ||
Review via email: mp+307082@code.launchpad.net |
Commit message
Description of the change
This MR refactors validation a bit. Three goals achieved here:
1) readability improvements (my opinion)
2) better performance (every plainbox invocation runs validation, the code on this branch runs a few percent faster)
3) less code!
4) more in line with zen of python
Important change here is what field_validators are. Previously this could have been an instance of a validator, a type of a validator or list of any of the above. This branch makes it instance-only.
In terms of testing, there should be no tangible changes in how *boxes work.
Sylvain Pineau (sylvain-pineau) wrote : | # |
Maciej Kisielewski (kissiel) wrote : | # |
This way present() would have to be a function yielding a concrete_validator (a constructor, really), so I wanted to stick to explicit and very oop-clear rules.
Right?
Sylvain Pineau (sylvain-pineau) wrote : | # |
It's ok and I like the new syntax a lot. It's finally good to have the old way in a few places in case we want to change severity (as a example). But getting rid of all those lambdas is a bug win.
+1
Sylvain Pineau (sylvain-pineau) wrote : | # |
s/bug/big hehe
Preview Diff
1 | === modified file 'plainbox/plainbox/impl/unit/category.py' | |||
2 | --- plainbox/plainbox/impl/unit/category.py 2016-05-11 14:36:13 +0000 | |||
3 | +++ plainbox/plainbox/impl/unit/category.py 2016-09-28 20:21:08 +0000 | |||
4 | @@ -30,16 +30,10 @@ | |||
5 | 30 | 30 | ||
6 | 31 | import logging | 31 | import logging |
7 | 32 | 32 | ||
8 | 33 | from plainbox.i18n import gettext as _ | ||
9 | 34 | from plainbox.i18n import gettext_noop as N_ | 33 | from plainbox.i18n import gettext_noop as N_ |
10 | 35 | from plainbox.impl.symbol import SymbolDef | 34 | from plainbox.impl.symbol import SymbolDef |
11 | 35 | from plainbox.impl.unit import concrete_validators | ||
12 | 36 | from plainbox.impl.unit.unit_with_id import UnitWithId | 36 | from plainbox.impl.unit.unit_with_id import UnitWithId |
13 | 37 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | ||
14 | 38 | from plainbox.impl.unit.validators import PresentFieldValidator | ||
15 | 39 | from plainbox.impl.unit.validators import TemplateVariantFieldValidator | ||
16 | 40 | from plainbox.impl.unit.validators import TranslatableFieldValidator | ||
17 | 41 | from plainbox.impl.validation import Problem | ||
18 | 42 | from plainbox.impl.validation import Severity | ||
19 | 43 | 37 | ||
20 | 44 | __all__ = ['CategoryUnit'] | 38 | __all__ = ['CategoryUnit'] |
21 | 45 | 39 | ||
22 | @@ -108,20 +102,10 @@ | |||
23 | 108 | 102 | ||
24 | 109 | field_validators = { | 103 | field_validators = { |
25 | 110 | fields.name: [ | 104 | fields.name: [ |
41 | 111 | TranslatableFieldValidator, | 105 | concrete_validators.translatable, |
42 | 112 | TemplateVariantFieldValidator, | 106 | concrete_validators.templateVariant, |
43 | 113 | PresentFieldValidator, | 107 | concrete_validators.present, |
44 | 114 | # We want the name to be a single line | 108 | concrete_validators.oneLine, |
45 | 115 | CorrectFieldValueValidator( | 109 | concrete_validators.shortValue, |
31 | 116 | lambda name: name.count("\n") == 0, | ||
32 | 117 | Problem.wrong, Severity.warning, | ||
33 | 118 | message=_("please use only one line"), | ||
34 | 119 | onlyif=lambda unit: unit.name is not None), | ||
35 | 120 | # We want the name to be relatively short | ||
36 | 121 | CorrectFieldValueValidator( | ||
37 | 122 | lambda name: len(name) <= 80, | ||
38 | 123 | Problem.wrong, Severity.warning, | ||
39 | 124 | message=_("please stay under 80 characters"), | ||
40 | 125 | onlyif=lambda unit: unit.name is not None), | ||
46 | 126 | ] | 110 | ] |
47 | 127 | } | 111 | } |
48 | 128 | 112 | ||
49 | === added file 'plainbox/plainbox/impl/unit/concrete_validators.py' | |||
50 | --- plainbox/plainbox/impl/unit/concrete_validators.py 1970-01-01 00:00:00 +0000 | |||
51 | +++ plainbox/plainbox/impl/unit/concrete_validators.py 2016-09-28 20:21:08 +0000 | |||
52 | @@ -0,0 +1,57 @@ | |||
53 | 1 | # This file is part of Checkbox. | ||
54 | 2 | # | ||
55 | 3 | # Copyright 2016 Canonical Ltd. | ||
56 | 4 | # Written by: | ||
57 | 5 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
58 | 6 | # | ||
59 | 7 | # Checkbox is free software: you can redistribute it and/or modify | ||
60 | 8 | # it under the terms of the GNU General Public License version 3, | ||
61 | 9 | # as published by the Free Software Foundation. | ||
62 | 10 | # | ||
63 | 11 | # Checkbox is distributed in the hope that it will be useful, | ||
64 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
65 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
66 | 14 | # GNU General Public License for more details. | ||
67 | 15 | # | ||
68 | 16 | # You should have received a copy of the GNU General Public License | ||
69 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | ||
70 | 18 | """ | ||
71 | 19 | :mod:`plainbox.impl.unit.concrete_validators` -- common validator instances | ||
72 | 20 | =========================================================================== | ||
73 | 21 | |||
74 | 22 | This module gathers common validator instances that can be shared among | ||
75 | 23 | multiple unit types as their field_validators. | ||
76 | 24 | """ | ||
77 | 25 | |||
78 | 26 | from plainbox.i18n import gettext as _ | ||
79 | 27 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | ||
80 | 28 | from plainbox.impl.validation import Problem | ||
81 | 29 | from plainbox.impl.validation import Severity | ||
82 | 30 | |||
83 | 31 | from plainbox.impl.unit.validators import PresentFieldValidator | ||
84 | 32 | from plainbox.impl.unit.validators import TemplateInvariantFieldValidator | ||
85 | 33 | from plainbox.impl.unit.validators import TemplateVariantFieldValidator | ||
86 | 34 | from plainbox.impl.unit.validators import TranslatableFieldValidator | ||
87 | 35 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
88 | 36 | |||
89 | 37 | |||
90 | 38 | translatable = TranslatableFieldValidator() | ||
91 | 39 | templateVariant = TemplateVariantFieldValidator() | ||
92 | 40 | templateInvariant = TemplateInvariantFieldValidator() | ||
93 | 41 | untranslatable = UntranslatableFieldValidator() | ||
94 | 42 | present = PresentFieldValidator() | ||
95 | 43 | |||
96 | 44 | localDeprecated = CorrectFieldValueValidator( | ||
97 | 45 | lambda plugin: plugin != 'local', Problem.deprecated, Severity.advice, | ||
98 | 46 | message=_("please migrate to job templates, see plainbox-template-unit(7)" | ||
99 | 47 | " for details")) | ||
100 | 48 | |||
101 | 49 | oneLine = CorrectFieldValueValidator( | ||
102 | 50 | lambda field: field is not None and field.count("\n") == 0, | ||
103 | 51 | Problem.wrong, Severity.warning, | ||
104 | 52 | message=_("please use only one line")) | ||
105 | 53 | |||
106 | 54 | shortValue = CorrectFieldValueValidator( | ||
107 | 55 | lambda field: field is not None and len(field) <= 80, | ||
108 | 56 | Problem.wrong, Severity.warning, | ||
109 | 57 | message=_("please stay under 80 characters")) | ||
110 | 0 | 58 | ||
111 | === modified file 'plainbox/plainbox/impl/unit/exporter.py' | |||
112 | --- plainbox/plainbox/impl/unit/exporter.py 2015-06-25 11:52:05 +0000 | |||
113 | +++ plainbox/plainbox/impl/unit/exporter.py 2016-09-28 20:21:08 +0000 | |||
114 | @@ -1,8 +1,9 @@ | |||
115 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
116 | 2 | # | 2 | # |
118 | 3 | # Copyright 2015 Canonical Ltd. | 3 | # Copyright 2015-2016 Canonical Ltd. |
119 | 4 | # Written by: | 4 | # Written by: |
120 | 5 | # Sylvain Pineau <sylvain.pineau@canonical.com> | 5 | # Sylvain Pineau <sylvain.pineau@canonical.com> |
121 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
122 | 6 | # | 7 | # |
123 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
124 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
125 | @@ -26,11 +27,10 @@ | |||
126 | 26 | 27 | ||
127 | 27 | from plainbox.i18n import gettext as _ | 28 | from plainbox.i18n import gettext as _ |
128 | 28 | from plainbox.impl.symbol import SymbolDef | 29 | from plainbox.impl.symbol import SymbolDef |
129 | 30 | from plainbox.impl.unit import concrete_validators | ||
130 | 29 | from plainbox.impl.unit.unit_with_id import UnitWithId | 31 | from plainbox.impl.unit.unit_with_id import UnitWithId |
131 | 30 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 32 | from plainbox.impl.unit.validators import CorrectFieldValueValidator |
132 | 31 | from plainbox.impl.unit.validators import PresentFieldValidator | 33 | from plainbox.impl.unit.validators import PresentFieldValidator |
133 | 32 | from plainbox.impl.unit.validators import TranslatableFieldValidator | ||
134 | 33 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
135 | 34 | from plainbox.impl.validation import Problem | 34 | from plainbox.impl.validation import Problem |
136 | 35 | from plainbox.impl.validation import Severity | 35 | from plainbox.impl.validation import Severity |
137 | 36 | 36 | ||
138 | @@ -115,40 +115,30 @@ | |||
139 | 115 | field_validators = { | 115 | field_validators = { |
140 | 116 | fields.summary: [ | 116 | fields.summary: [ |
141 | 117 | PresentFieldValidator(severity=Severity.advice), | 117 | PresentFieldValidator(severity=Severity.advice), |
155 | 118 | TranslatableFieldValidator, | 118 | concrete_validators.translatable, |
156 | 119 | # We want the summary to be a single line | 119 | concrete_validators.oneLine, |
157 | 120 | CorrectFieldValueValidator( | 120 | concrete_validators.shortValue, |
145 | 121 | lambda summary: summary.count("\n") == 0, | ||
146 | 122 | Problem.wrong, Severity.warning, | ||
147 | 123 | message=_("please use only one line"), | ||
148 | 124 | onlyif=lambda unit: unit.summary is not None), | ||
149 | 125 | # We want the summary to be relatively short | ||
150 | 126 | CorrectFieldValueValidator( | ||
151 | 127 | lambda summary: len(summary) <= 80, | ||
152 | 128 | Problem.wrong, Severity.warning, | ||
153 | 129 | message=_("please stay under 80 characters"), | ||
154 | 130 | onlyif=lambda unit: unit.summary is not None), | ||
158 | 131 | ], | 121 | ], |
159 | 132 | fields.entry_point: [ | 122 | fields.entry_point: [ |
162 | 133 | PresentFieldValidator, | 123 | concrete_validators.present, |
163 | 134 | UntranslatableFieldValidator, | 124 | concrete_validators.untranslatable, |
164 | 135 | CorrectFieldValueValidator( | 125 | CorrectFieldValueValidator( |
165 | 136 | lambda entry_point: pkg_resources.load_entry_point( | 126 | lambda entry_point: pkg_resources.load_entry_point( |
166 | 137 | 'plainbox', 'plainbox.exporter', entry_point), | 127 | 'plainbox', 'plainbox.exporter', entry_point), |
167 | 138 | Problem.wrong, Severity.error), | 128 | Problem.wrong, Severity.error), |
168 | 139 | ], | 129 | ], |
169 | 140 | fields.file_extension: [ | 130 | fields.file_extension: [ |
172 | 141 | PresentFieldValidator, | 131 | concrete_validators.present, |
173 | 142 | UntranslatableFieldValidator, | 132 | concrete_validators.untranslatable, |
174 | 143 | CorrectFieldValueValidator( | 133 | CorrectFieldValueValidator( |
175 | 144 | lambda extension: re.search("^[\w\.\-]+$", extension), | 134 | lambda extension: re.search("^[\w\.\-]+$", extension), |
176 | 145 | Problem.syntax_error, Severity.error), | 135 | Problem.syntax_error, Severity.error), |
177 | 146 | ], | 136 | ], |
178 | 147 | fields.options: [ | 137 | fields.options: [ |
180 | 148 | UntranslatableFieldValidator, | 138 | concrete_validators.untranslatable, |
181 | 149 | ], | 139 | ], |
182 | 150 | fields.data: [ | 140 | fields.data: [ |
184 | 151 | UntranslatableFieldValidator, | 141 | concrete_validators.untranslatable, |
185 | 152 | CorrectFieldValueValidator( | 142 | CorrectFieldValueValidator( |
186 | 153 | lambda value, unit: json.loads(value), | 143 | lambda value, unit: json.loads(value), |
187 | 154 | Problem.syntax_error, Severity.error, | 144 | Problem.syntax_error, Severity.error, |
188 | 155 | 145 | ||
189 | === modified file 'plainbox/plainbox/impl/unit/file.py' | |||
190 | --- plainbox/plainbox/impl/unit/file.py 2015-02-06 15:30:54 +0000 | |||
191 | +++ plainbox/plainbox/impl/unit/file.py 2016-09-28 20:21:08 +0000 | |||
192 | @@ -30,6 +30,7 @@ | |||
193 | 30 | from plainbox.impl.unit.job import propertywithsymbols | 30 | from plainbox.impl.unit.job import propertywithsymbols |
194 | 31 | from plainbox.impl.unit.unit import Unit, UnitValidator | 31 | from plainbox.impl.unit.unit import Unit, UnitValidator |
195 | 32 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 32 | from plainbox.impl.unit.validators import CorrectFieldValueValidator |
196 | 33 | from plainbox.impl.unit.validators import MemberOfFieldValidator | ||
197 | 33 | from plainbox.impl.validation import Problem | 34 | from plainbox.impl.validation import Problem |
198 | 34 | from plainbox.impl.validation import Severity | 35 | from plainbox.impl.validation import Severity |
199 | 35 | 36 | ||
200 | @@ -146,11 +147,5 @@ | |||
201 | 146 | 'faq.html#faq-1' | 147 | 'faq.html#faq-1' |
202 | 147 | )), | 148 | )), |
203 | 148 | ], | 149 | ], |
211 | 149 | fields.role: [ | 150 | fields.role: [MemberOfFieldValidator(FileRole.get_all_symbols())] |
205 | 150 | CorrectFieldValueValidator( | ||
206 | 151 | lambda value: value in FileRole.get_all_symbols(), | ||
207 | 152 | message=_('valid values are: {}').format( | ||
208 | 153 | ', '.join(str(sym) for sym in sorted( | ||
209 | 154 | FileRole.get_all_symbols())))), | ||
210 | 155 | ] | ||
212 | 156 | } | 151 | } |
213 | 157 | 152 | ||
214 | === modified file 'plainbox/plainbox/impl/unit/job.py' | |||
215 | --- plainbox/plainbox/impl/unit/job.py 2016-09-22 18:53:53 +0000 | |||
216 | +++ plainbox/plainbox/impl/unit/job.py 2016-09-28 20:21:08 +0000 | |||
217 | @@ -1,9 +1,10 @@ | |||
218 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
219 | 2 | # | 2 | # |
221 | 3 | # Copyright 2012-2014 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
222 | 4 | # Written by: | 4 | # Written by: |
223 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
224 | 6 | # Sylvain Pineau <sylvain.pineau@canonical.com> | 6 | # Sylvain Pineau <sylvain.pineau@canonical.com> |
225 | 7 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
226 | 7 | # | 8 | # |
227 | 8 | # Checkbox is free software: you can redistribute it and/or modify | 9 | # Checkbox is free software: you can redistribute it and/or modify |
228 | 9 | # it under the terms of the GNU General Public License version 3, | 10 | # it under the terms of the GNU General Public License version 3, |
229 | @@ -34,18 +35,17 @@ | |||
230 | 34 | from plainbox.impl.secure.origin import JobOutputTextSource | 35 | from plainbox.impl.secure.origin import JobOutputTextSource |
231 | 35 | from plainbox.impl.secure.origin import Origin | 36 | from plainbox.impl.secure.origin import Origin |
232 | 36 | from plainbox.impl.symbol import SymbolDef | 37 | from plainbox.impl.symbol import SymbolDef |
233 | 38 | from plainbox.impl.unit import concrete_validators | ||
234 | 37 | from plainbox.impl.unit.unit_with_id import UnitWithId | 39 | from plainbox.impl.unit.unit_with_id import UnitWithId |
235 | 38 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 40 | from plainbox.impl.unit.validators import CorrectFieldValueValidator |
236 | 39 | from plainbox.impl.unit.validators import DeprecatedFieldValidator | 41 | from plainbox.impl.unit.validators import DeprecatedFieldValidator |
237 | 42 | from plainbox.impl.unit.validators import MemberOfFieldValidator | ||
238 | 40 | from plainbox.impl.unit.validators import PresentFieldValidator | 43 | from plainbox.impl.unit.validators import PresentFieldValidator |
239 | 41 | from plainbox.impl.unit.validators import ReferenceConstraint | 44 | from plainbox.impl.unit.validators import ReferenceConstraint |
240 | 42 | from plainbox.impl.unit.validators import ShellProgramValidator | 45 | from plainbox.impl.unit.validators import ShellProgramValidator |
241 | 43 | from plainbox.impl.unit.validators import TemplateInvariantFieldValidator | ||
242 | 44 | from plainbox.impl.unit.validators import TemplateVariantFieldValidator | ||
243 | 45 | from plainbox.impl.unit.validators import TranslatableFieldValidator | ||
244 | 46 | from plainbox.impl.unit.validators import UnitReferenceValidator | 46 | from plainbox.impl.unit.validators import UnitReferenceValidator |
245 | 47 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
246 | 48 | from plainbox.impl.unit.validators import UselessFieldValidator | 47 | from plainbox.impl.unit.validators import UselessFieldValidator |
247 | 48 | |||
248 | 49 | from plainbox.impl.validation import Problem | 49 | from plainbox.impl.validation import Problem |
249 | 50 | from plainbox.impl.validation import Severity | 50 | from plainbox.impl.validation import Severity |
250 | 51 | from plainbox.impl.xparsers import Error | 51 | from plainbox.impl.xparsers import Error |
251 | @@ -700,51 +700,32 @@ | |||
252 | 700 | 700 | ||
253 | 701 | field_validators = { | 701 | field_validators = { |
254 | 702 | fields.name: [ | 702 | fields.name: [ |
257 | 703 | UntranslatableFieldValidator, | 703 | concrete_validators.untranslatable, |
258 | 704 | TemplateVariantFieldValidator, | 704 | concrete_validators.templateVariant, |
259 | 705 | DeprecatedFieldValidator( | 705 | DeprecatedFieldValidator( |
260 | 706 | _("use 'id' and 'summary' instead of 'name'")), | 706 | _("use 'id' and 'summary' instead of 'name'")), |
261 | 707 | ], | 707 | ], |
262 | 708 | # NOTE: 'id' validators are "inherited" so we don't have it here | 708 | # NOTE: 'id' validators are "inherited" so we don't have it here |
263 | 709 | fields.summary: [ | 709 | fields.summary: [ |
266 | 710 | TranslatableFieldValidator, | 710 | concrete_validators.translatable, |
267 | 711 | TemplateVariantFieldValidator, | 711 | concrete_validators.templateVariant, |
268 | 712 | PresentFieldValidator(severity=Severity.advice), | 712 | PresentFieldValidator(severity=Severity.advice), |
281 | 713 | # We want the summary to be a single line | 713 | concrete_validators.oneLine, |
282 | 714 | CorrectFieldValueValidator( | 714 | concrete_validators.shortValue, |
271 | 715 | lambda summary: summary.count("\n") == 0, | ||
272 | 716 | Problem.wrong, Severity.warning, | ||
273 | 717 | message=_("please use only one line"), | ||
274 | 718 | onlyif=lambda unit: unit.summary is not None), | ||
275 | 719 | # We want the summary to be relatively short | ||
276 | 720 | CorrectFieldValueValidator( | ||
277 | 721 | lambda summary: len(summary) <= 80, | ||
278 | 722 | Problem.wrong, Severity.warning, | ||
279 | 723 | message=_("please stay under 80 characters"), | ||
280 | 724 | onlyif=lambda unit: unit.summary is not None), | ||
283 | 725 | ], | 715 | ], |
284 | 726 | fields.plugin: [ | 716 | fields.plugin: [ |
299 | 727 | UntranslatableFieldValidator, | 717 | concrete_validators.untranslatable, |
300 | 728 | TemplateInvariantFieldValidator, | 718 | concrete_validators.templateInvariant, |
301 | 729 | PresentFieldValidator, | 719 | concrete_validators.present, |
302 | 730 | CorrectFieldValueValidator( | 720 | MemberOfFieldValidator(_PluginValues.get_all_symbols()), |
303 | 731 | lambda plugin: ( | 721 | concrete_validators.localDeprecated, |
290 | 732 | plugin in JobDefinition.plugin.get_all_symbols()), | ||
291 | 733 | message=_('valid values are: {}').format( | ||
292 | 734 | ', '.join(str(sym) for sym in sorted( | ||
293 | 735 | _PluginValues.get_all_symbols())))), | ||
294 | 736 | CorrectFieldValueValidator( | ||
295 | 737 | lambda plugin: plugin != 'local', | ||
296 | 738 | Problem.deprecated, Severity.advice, | ||
297 | 739 | message=_("please migrate to job templates, " | ||
298 | 740 | "see plainbox-template-unit(7) for details")), | ||
304 | 741 | CorrectFieldValueValidator( | 722 | CorrectFieldValueValidator( |
305 | 742 | lambda plugin: plugin != 'user-verify', | 723 | lambda plugin: plugin != 'user-verify', |
306 | 743 | Problem.deprecated, Severity.advice, | 724 | Problem.deprecated, Severity.advice, |
307 | 744 | message=_("please migrate to user-interact-verify")), | 725 | message=_("please migrate to user-interact-verify")), |
308 | 745 | ], | 726 | ], |
309 | 746 | fields.command: [ | 727 | fields.command: [ |
311 | 747 | UntranslatableFieldValidator, | 728 | concrete_validators.untranslatable, |
312 | 748 | # All jobs except for manual must have a command | 729 | # All jobs except for manual must have a command |
313 | 749 | PresentFieldValidator( | 730 | PresentFieldValidator( |
314 | 750 | message=_("command is mandatory for non-manual jobs"), | 731 | message=_("command is mandatory for non-manual jobs"), |
315 | @@ -768,11 +749,11 @@ | |||
316 | 768 | " instead of CHECKBOX_DATA"), | 749 | " instead of CHECKBOX_DATA"), |
317 | 769 | onlyif=lambda unit: unit.command is not None), | 750 | onlyif=lambda unit: unit.command is not None), |
318 | 770 | # We want to catch silly mistakes that shlex can detect | 751 | # We want to catch silly mistakes that shlex can detect |
320 | 771 | ShellProgramValidator, | 752 | ShellProgramValidator(), |
321 | 772 | ], | 753 | ], |
322 | 773 | fields.description: [ | 754 | fields.description: [ |
325 | 774 | TranslatableFieldValidator, | 755 | concrete_validators.translatable, |
326 | 775 | TemplateVariantFieldValidator, | 756 | concrete_validators.templateVariant, |
327 | 776 | # Description is mandatory for manual jobs | 757 | # Description is mandatory for manual jobs |
328 | 777 | PresentFieldValidator( | 758 | PresentFieldValidator( |
329 | 778 | message=_("manual jobs must have a description field, or a" | 759 | message=_("manual jobs must have a description field, or a" |
330 | @@ -796,7 +777,7 @@ | |||
331 | 796 | unit.verification is None))), | 777 | unit.verification is None))), |
332 | 797 | ], | 778 | ], |
333 | 798 | fields.purpose: [ | 779 | fields.purpose: [ |
335 | 799 | TranslatableFieldValidator, | 780 | concrete_validators.translatable, |
336 | 800 | PresentFieldValidator( | 781 | PresentFieldValidator( |
337 | 801 | severity=Severity.advice, | 782 | severity=Severity.advice, |
338 | 802 | message=("please use purpose, steps, and verification" | 783 | message=("please use purpose, steps, and verification" |
339 | @@ -807,7 +788,7 @@ | |||
340 | 807 | unit.get_record_value('summary') is None), | 788 | unit.get_record_value('summary') is None), |
341 | 808 | ], | 789 | ], |
342 | 809 | fields.steps: [ | 790 | fields.steps: [ |
344 | 810 | TranslatableFieldValidator, | 791 | concrete_validators.translatable, |
345 | 811 | PresentFieldValidator( | 792 | PresentFieldValidator( |
346 | 812 | severity=Severity.advice, | 793 | severity=Severity.advice, |
347 | 813 | message=("please use purpose, steps, and verification" | 794 | message=("please use purpose, steps, and verification" |
348 | @@ -817,7 +798,7 @@ | |||
349 | 817 | unit.startup_user_interaction_required), | 798 | unit.startup_user_interaction_required), |
350 | 818 | ], | 799 | ], |
351 | 819 | fields.verification: [ | 800 | fields.verification: [ |
353 | 820 | TranslatableFieldValidator, | 801 | concrete_validators.translatable, |
354 | 821 | PresentFieldValidator( | 802 | PresentFieldValidator( |
355 | 822 | severity=Severity.advice, | 803 | severity=Severity.advice, |
356 | 823 | message=("please use purpose, steps, and verification" | 804 | message=("please use purpose, steps, and verification" |
357 | @@ -827,8 +808,8 @@ | |||
358 | 827 | 'manual', 'user-verify', 'user-interact-verify')), | 808 | 'manual', 'user-verify', 'user-interact-verify')), |
359 | 828 | ], | 809 | ], |
360 | 829 | fields.user: [ | 810 | fields.user: [ |
363 | 830 | UntranslatableFieldValidator, | 811 | concrete_validators.untranslatable, |
364 | 831 | TemplateInvariantFieldValidator, | 812 | concrete_validators.templateInvariant, |
365 | 832 | # User should be either None or 'root' | 813 | # User should be either None or 'root' |
366 | 833 | CorrectFieldValueValidator( | 814 | CorrectFieldValueValidator( |
367 | 834 | message=_("user can only be 'root'"), | 815 | message=_("user can only be 'root'"), |
368 | @@ -839,16 +820,16 @@ | |||
369 | 839 | onlyif=lambda unit: unit.command is None) | 820 | onlyif=lambda unit: unit.command is None) |
370 | 840 | ], | 821 | ], |
371 | 841 | fields.environ: [ | 822 | fields.environ: [ |
374 | 842 | UntranslatableFieldValidator, | 823 | concrete_validators.untranslatable, |
375 | 843 | TemplateInvariantFieldValidator, | 824 | concrete_validators.templateInvariant, |
376 | 844 | # Environ is useless without a command to run | 825 | # Environ is useless without a command to run |
377 | 845 | UselessFieldValidator( | 826 | UselessFieldValidator( |
378 | 846 | message=_("environ without a command makes no sense"), | 827 | message=_("environ without a command makes no sense"), |
379 | 847 | onlyif=lambda unit: unit.command is None), | 828 | onlyif=lambda unit: unit.command is None), |
380 | 848 | ], | 829 | ], |
381 | 849 | fields.estimated_duration: [ | 830 | fields.estimated_duration: [ |
384 | 850 | UntranslatableFieldValidator, | 831 | concrete_validators.untranslatable, |
385 | 851 | TemplateInvariantFieldValidator, | 832 | concrete_validators.templateInvariant, |
386 | 852 | PresentFieldValidator( | 833 | PresentFieldValidator( |
387 | 853 | severity=Severity.advice, | 834 | severity=Severity.advice, |
388 | 854 | onlyif=lambda unit: 'simple' not in unit.get_flag_set() | 835 | onlyif=lambda unit: 'simple' not in unit.get_flag_set() |
389 | @@ -860,7 +841,7 @@ | |||
390 | 860 | unit.get_record_value('estimated_duration'))), | 841 | unit.get_record_value('estimated_duration'))), |
391 | 861 | ], | 842 | ], |
392 | 862 | fields.depends: [ | 843 | fields.depends: [ |
394 | 863 | UntranslatableFieldValidator, | 844 | concrete_validators.untranslatable, |
395 | 864 | CorrectFieldValueValidator( | 845 | CorrectFieldValueValidator( |
396 | 865 | lambda value, unit: ( | 846 | lambda value, unit: ( |
397 | 866 | unit.get_direct_dependencies() is not None)), | 847 | unit.get_direct_dependencies() is not None)), |
398 | @@ -874,7 +855,7 @@ | |||
399 | 874 | # onlyif job itself is not deprecated | 855 | # onlyif job itself is not deprecated |
400 | 875 | ], | 856 | ], |
401 | 876 | fields.after: [ | 857 | fields.after: [ |
403 | 877 | UntranslatableFieldValidator, | 858 | concrete_validators.untranslatable, |
404 | 878 | CorrectFieldValueValidator( | 859 | CorrectFieldValueValidator( |
405 | 879 | lambda value, unit: ( | 860 | lambda value, unit: ( |
406 | 880 | unit.get_after_dependencies() is not None)), | 861 | unit.get_after_dependencies() is not None)), |
407 | @@ -886,7 +867,7 @@ | |||
408 | 886 | message=_("the referenced unit is not a job"))]) | 867 | message=_("the referenced unit is not a job"))]) |
409 | 887 | ], | 868 | ], |
410 | 888 | fields.requires: [ | 869 | fields.requires: [ |
412 | 889 | UntranslatableFieldValidator, | 870 | concrete_validators.untranslatable, |
413 | 890 | CorrectFieldValueValidator( | 871 | CorrectFieldValueValidator( |
414 | 891 | lambda value, unit: unit.get_resource_program(), | 872 | lambda value, unit: unit.get_resource_program(), |
415 | 892 | onlyif=lambda unit: unit.requires is not None), | 873 | onlyif=lambda unit: unit.requires is not None), |
416 | @@ -908,16 +889,16 @@ | |||
417 | 908 | # onlyif job itself is not deprecated | 889 | # onlyif job itself is not deprecated |
418 | 909 | ], | 890 | ], |
419 | 910 | fields.shell: [ | 891 | fields.shell: [ |
422 | 911 | UntranslatableFieldValidator, | 892 | concrete_validators.untranslatable, |
423 | 912 | TemplateInvariantFieldValidator, | 893 | concrete_validators.templateInvariant, |
424 | 913 | # Shell should be only '/bin/sh', or None (which gives bash) | 894 | # Shell should be only '/bin/sh', or None (which gives bash) |
427 | 914 | CorrectFieldValueValidator( | 895 | MemberOfFieldValidator( |
428 | 915 | lambda shell: shell in ('/bin/sh', '/bin/bash', 'bash'), | 896 | ['/bin/sh', '/bin/bash', 'bash'], |
429 | 916 | message=_("only /bin/sh and /bin/bash are allowed")), | 897 | message=_("only /bin/sh and /bin/bash are allowed")), |
430 | 917 | ], | 898 | ], |
431 | 918 | fields.imports: [ | 899 | fields.imports: [ |
434 | 919 | UntranslatableFieldValidator, | 900 | concrete_validators.untranslatable, |
435 | 920 | TemplateInvariantFieldValidator, | 901 | concrete_validators.templateInvariant, |
436 | 921 | CorrectFieldValueValidator( | 902 | CorrectFieldValueValidator( |
437 | 922 | lambda value, unit: ( | 903 | lambda value, unit: ( |
438 | 923 | list(unit.get_imported_jobs()) is not None)), | 904 | list(unit.get_imported_jobs()) is not None)), |
439 | @@ -933,8 +914,8 @@ | |||
440 | 933 | # onlyif job itself is not deprecated | 914 | # onlyif job itself is not deprecated |
441 | 934 | ], | 915 | ], |
442 | 935 | fields.category_id: [ | 916 | fields.category_id: [ |
445 | 936 | UntranslatableFieldValidator, | 917 | concrete_validators.untranslatable, |
446 | 937 | TemplateInvariantFieldValidator, | 918 | concrete_validators.templateInvariant, |
447 | 938 | UnitReferenceValidator( | 919 | UnitReferenceValidator( |
448 | 939 | lambda unit: ( | 920 | lambda unit: ( |
449 | 940 | [unit.get_category_id()] if unit.category_id else ()), | 921 | [unit.get_category_id()] if unit.category_id else ()), |
450 | @@ -948,8 +929,8 @@ | |||
451 | 948 | # onlyif job itself is not deprecated | 929 | # onlyif job itself is not deprecated |
452 | 949 | ], | 930 | ], |
453 | 950 | fields.flags: [ | 931 | fields.flags: [ |
456 | 951 | UntranslatableFieldValidator, | 932 | concrete_validators.untranslatable, |
457 | 952 | TemplateInvariantFieldValidator, | 933 | concrete_validators.templateInvariant, |
458 | 953 | CorrectFieldValueValidator( | 934 | CorrectFieldValueValidator( |
459 | 954 | lambda value, unit: ( | 935 | lambda value, unit: ( |
460 | 955 | 'simple' in unit.get_flag_set() or | 936 | 'simple' in unit.get_flag_set() or |
461 | @@ -999,8 +980,8 @@ | |||
462 | 999 | onlyif=lambda unit: unit.command is None), | 980 | onlyif=lambda unit: unit.command is None), |
463 | 1000 | ], | 981 | ], |
464 | 1001 | fields.qml_file: [ | 982 | fields.qml_file: [ |
467 | 1002 | UntranslatableFieldValidator, | 983 | concrete_validators.untranslatable, |
468 | 1003 | TemplateInvariantFieldValidator, | 984 | concrete_validators.templateInvariant, |
469 | 1004 | PresentFieldValidator( | 985 | PresentFieldValidator( |
470 | 1005 | onlyif=lambda unit: unit.plugin == 'qml'), | 986 | onlyif=lambda unit: unit.plugin == 'qml'), |
471 | 1006 | CorrectFieldValueValidator( | 987 | CorrectFieldValueValidator( |
472 | @@ -1016,14 +997,9 @@ | |||
473 | 1016 | unit.qml_file)), | 997 | unit.qml_file)), |
474 | 1017 | ], | 998 | ], |
475 | 1018 | fields.certification_status: [ | 999 | fields.certification_status: [ |
485 | 1019 | UntranslatableFieldValidator, | 1000 | concrete_validators.untranslatable, |
486 | 1020 | TemplateInvariantFieldValidator, | 1001 | concrete_validators.templateInvariant, |
487 | 1021 | CorrectFieldValueValidator( | 1002 | MemberOfFieldValidator( |
488 | 1022 | lambda certification_status: ( | 1003 | _CertificationStatusValues.get_all_symbols()), |
480 | 1023 | certification_status in | ||
481 | 1024 | _CertificationStatusValues.get_all_symbols()), | ||
482 | 1025 | message=_('valid values are: {}').format( | ||
483 | 1026 | ', '.join(str(sym) for sym in sorted( | ||
484 | 1027 | _CertificationStatusValues.get_all_symbols())))), | ||
489 | 1028 | ], | 1004 | ], |
490 | 1029 | } | 1005 | } |
491 | 1030 | 1006 | ||
492 | === modified file 'plainbox/plainbox/impl/unit/manifest.py' | |||
493 | --- plainbox/plainbox/impl/unit/manifest.py 2015-03-30 17:35:30 +0000 | |||
494 | +++ plainbox/plainbox/impl/unit/manifest.py 2016-09-28 20:21:08 +0000 | |||
495 | @@ -1,8 +1,9 @@ | |||
496 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
497 | 2 | # | 2 | # |
499 | 3 | # Copyright 2012-2015 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
500 | 4 | # Written by: | 4 | # Written by: |
501 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
502 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
503 | 6 | # | 7 | # |
504 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
505 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
506 | @@ -20,12 +21,9 @@ | |||
507 | 20 | import logging | 21 | import logging |
508 | 21 | 22 | ||
509 | 22 | from plainbox.impl.symbol import SymbolDef | 23 | from plainbox.impl.symbol import SymbolDef |
510 | 24 | from plainbox.impl.unit import concrete_validators | ||
511 | 23 | from plainbox.impl.unit.unit_with_id import UnitWithId | 25 | from plainbox.impl.unit.unit_with_id import UnitWithId |
517 | 24 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 26 | from plainbox.impl.unit.validators import MemberOfFieldValidator |
513 | 25 | from plainbox.impl.unit.validators import PresentFieldValidator | ||
514 | 26 | from plainbox.impl.unit.validators import TemplateVariantFieldValidator | ||
515 | 27 | from plainbox.impl.unit.validators import TranslatableFieldValidator | ||
516 | 28 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
518 | 29 | 27 | ||
519 | 30 | logger = logging.getLogger("plainbox.unit.manifest") | 28 | logger = logging.getLogger("plainbox.unit.manifest") |
520 | 31 | 29 | ||
521 | @@ -98,20 +96,19 @@ | |||
522 | 98 | 96 | ||
523 | 99 | field_validators = { | 97 | field_validators = { |
524 | 100 | fields.name: [ | 98 | fields.name: [ |
528 | 101 | TranslatableFieldValidator, | 99 | concrete_validators.translatable, |
529 | 102 | TemplateVariantFieldValidator, | 100 | concrete_validators.templateVariant, |
530 | 103 | PresentFieldValidator, | 101 | concrete_validators.present, |
531 | 104 | ], | 102 | ], |
532 | 105 | fields.value_type: [ | 103 | fields.value_type: [ |
537 | 106 | UntranslatableFieldValidator, | 104 | concrete_validators.untranslatable, |
538 | 107 | PresentFieldValidator(), | 105 | concrete_validators.present, |
539 | 108 | CorrectFieldValueValidator( | 106 | MemberOfFieldValidator(['bool', 'natural']), |
536 | 109 | lambda value_type: value_type in ('bool', 'natural')), | ||
540 | 110 | ], | 107 | ], |
541 | 111 | fields.value_unit: [ | 108 | fields.value_unit: [ |
542 | 112 | # OPTIONAL | 109 | # OPTIONAL |
543 | 113 | ], | 110 | ], |
544 | 114 | fields.resource_key: [ | 111 | fields.resource_key: [ |
546 | 115 | UntranslatableFieldValidator, | 112 | concrete_validators.untranslatable |
547 | 116 | ] | 113 | ] |
548 | 117 | } | 114 | } |
549 | 118 | 115 | ||
550 | === modified file 'plainbox/plainbox/impl/unit/packaging.py' | |||
551 | --- plainbox/plainbox/impl/unit/packaging.py 2016-05-20 13:54:59 +0000 | |||
552 | +++ plainbox/plainbox/impl/unit/packaging.py 2016-09-28 20:21:08 +0000 | |||
553 | @@ -1,8 +1,9 @@ | |||
554 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
555 | 2 | # | 2 | # |
557 | 3 | # Copyright 2012-2015 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
558 | 4 | # Written by: | 4 | # Written by: |
559 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
560 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
561 | 6 | # | 7 | # |
562 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
563 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
564 | @@ -120,9 +121,8 @@ | |||
565 | 120 | from plainbox.i18n import gettext as _ | 121 | from plainbox.i18n import gettext as _ |
566 | 121 | from plainbox.impl.device import get_os_release | 122 | from plainbox.impl.device import get_os_release |
567 | 122 | from plainbox.impl.symbol import SymbolDef | 123 | from plainbox.impl.symbol import SymbolDef |
568 | 124 | from plainbox.impl.unit import concrete_validators | ||
569 | 123 | from plainbox.impl.unit.unit import Unit | 125 | from plainbox.impl.unit.unit import Unit |
570 | 124 | from plainbox.impl.unit.validators import PresentFieldValidator | ||
571 | 125 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
572 | 126 | 126 | ||
573 | 127 | _logger = logging.getLogger("plainbox.unit.packaging") | 127 | _logger = logging.getLogger("plainbox.unit.packaging") |
574 | 128 | 128 | ||
575 | @@ -164,11 +164,11 @@ | |||
576 | 164 | 164 | ||
577 | 165 | field_validators = { | 165 | field_validators = { |
578 | 166 | fields.os_id: [ | 166 | fields.os_id: [ |
581 | 167 | UntranslatableFieldValidator, | 167 | concrete_validators.untranslatable, |
582 | 168 | PresentFieldValidator, | 168 | concrete_validators.present, |
583 | 169 | ], | 169 | ], |
584 | 170 | fields.os_version_id: [ | 170 | fields.os_version_id: [ |
586 | 171 | UntranslatableFieldValidator, | 171 | concrete_validators.untranslatable, |
587 | 172 | ], | 172 | ], |
588 | 173 | } | 173 | } |
589 | 174 | 174 | ||
590 | 175 | 175 | ||
591 | === modified file 'plainbox/plainbox/impl/unit/template.py' | |||
592 | --- plainbox/plainbox/impl/unit/template.py 2016-05-11 14:36:13 +0000 | |||
593 | +++ plainbox/plainbox/impl/unit/template.py 2016-09-28 20:21:08 +0000 | |||
594 | @@ -1,8 +1,9 @@ | |||
595 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
596 | 2 | # | 2 | # |
598 | 3 | # Copyright 2012-2014 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
599 | 4 | # Written by: | 4 | # Written by: |
600 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
601 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
602 | 6 | # | 7 | # |
603 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
604 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
605 | @@ -32,14 +33,13 @@ | |||
606 | 32 | from plainbox.impl.secure.origin import Origin | 33 | from plainbox.impl.secure.origin import Origin |
607 | 33 | from plainbox.impl.symbol import SymbolDef | 34 | from plainbox.impl.symbol import SymbolDef |
608 | 34 | from plainbox.impl.unit import all_units | 35 | from plainbox.impl.unit import all_units |
609 | 36 | from plainbox.impl.unit import concrete_validators | ||
610 | 35 | from plainbox.impl.unit import get_accessed_parameters | 37 | from plainbox.impl.unit import get_accessed_parameters |
611 | 36 | from plainbox.impl.unit.unit import Unit | 38 | from plainbox.impl.unit.unit import Unit |
612 | 37 | from plainbox.impl.unit.unit import UnitValidator | 39 | from plainbox.impl.unit.unit import UnitValidator |
613 | 38 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 40 | from plainbox.impl.unit.validators import CorrectFieldValueValidator |
614 | 39 | from plainbox.impl.unit.validators import PresentFieldValidator | ||
615 | 40 | from plainbox.impl.unit.validators import ReferenceConstraint | 41 | from plainbox.impl.unit.validators import ReferenceConstraint |
616 | 41 | from plainbox.impl.unit.validators import UnitReferenceValidator | 42 | from plainbox.impl.unit.validators import UnitReferenceValidator |
617 | 42 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
618 | 43 | from plainbox.impl.validation import Problem | 43 | from plainbox.impl.validation import Problem |
619 | 44 | from plainbox.impl.validation import Severity | 44 | from plainbox.impl.validation import Severity |
620 | 45 | 45 | ||
621 | @@ -427,7 +427,7 @@ | |||
622 | 427 | 427 | ||
623 | 428 | field_validators = { | 428 | field_validators = { |
624 | 429 | fields.template_unit: [ | 429 | fields.template_unit: [ |
626 | 430 | UntranslatableFieldValidator, | 430 | concrete_validators.untranslatable, |
627 | 431 | CorrectFieldValueValidator( | 431 | CorrectFieldValueValidator( |
628 | 432 | lambda value, unit: ( | 432 | lambda value, unit: ( |
629 | 433 | unit.get_record_value('template-unit') is not None), | 433 | unit.get_record_value('template-unit') is not None), |
630 | @@ -436,8 +436,8 @@ | |||
631 | 436 | " unit type")), | 436 | " unit type")), |
632 | 437 | ], | 437 | ], |
633 | 438 | fields.template_resource: [ | 438 | fields.template_resource: [ |
636 | 439 | UntranslatableFieldValidator, | 439 | concrete_validators.untranslatable, |
637 | 440 | PresentFieldValidator, | 440 | concrete_validators.present, |
638 | 441 | UnitReferenceValidator( | 441 | UnitReferenceValidator( |
639 | 442 | lambda unit: ( | 442 | lambda unit: ( |
640 | 443 | [unit.resource_id] if unit.resource_id else []), | 443 | [unit.resource_id] if unit.resource_id else []), |
641 | @@ -457,7 +457,7 @@ | |||
642 | 457 | # onlyif job itself is not deprecated | 457 | # onlyif job itself is not deprecated |
643 | 458 | ], | 458 | ], |
644 | 459 | fields.template_filter: [ | 459 | fields.template_filter: [ |
646 | 460 | UntranslatableFieldValidator, | 460 | concrete_validators.untranslatable, |
647 | 461 | # All templates need a valid (or empty) template filter | 461 | # All templates need a valid (or empty) template filter |
648 | 462 | CorrectFieldValueValidator( | 462 | CorrectFieldValueValidator( |
649 | 463 | lambda value, unit: unit.get_filter_program(), | 463 | lambda value, unit: unit.get_filter_program(), |
650 | @@ -465,7 +465,7 @@ | |||
651 | 465 | # TODO: must refer to the same job as template-resource | 465 | # TODO: must refer to the same job as template-resource |
652 | 466 | ], | 466 | ], |
653 | 467 | fields.template_imports: [ | 467 | fields.template_imports: [ |
655 | 468 | UntranslatableFieldValidator, | 468 | concrete_validators.untranslatable, |
656 | 469 | CorrectFieldValueValidator( | 469 | CorrectFieldValueValidator( |
657 | 470 | lambda value, unit: ( | 470 | lambda value, unit: ( |
658 | 471 | list(unit.get_imported_jobs()) is not None)), | 471 | list(unit.get_imported_jobs()) is not None)), |
659 | 472 | 472 | ||
660 | === modified file 'plainbox/plainbox/impl/unit/testplan.py' | |||
661 | --- plainbox/plainbox/impl/unit/testplan.py 2016-06-09 20:12:35 +0000 | |||
662 | +++ plainbox/plainbox/impl/unit/testplan.py 2016-09-28 20:21:08 +0000 | |||
663 | @@ -1,8 +1,9 @@ | |||
664 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
665 | 2 | # | 2 | # |
667 | 3 | # Copyright 2012-2014 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
668 | 4 | # Written by: | 4 | # Written by: |
669 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
670 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
671 | 6 | # | 7 | # |
672 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
673 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
674 | @@ -32,16 +33,14 @@ | |||
675 | 32 | from plainbox.impl.secure.qualifiers import OperatorMatcher | 33 | from plainbox.impl.secure.qualifiers import OperatorMatcher |
676 | 33 | from plainbox.impl.secure.qualifiers import PatternMatcher | 34 | from plainbox.impl.secure.qualifiers import PatternMatcher |
677 | 34 | from plainbox.impl.symbol import SymbolDef | 35 | from plainbox.impl.symbol import SymbolDef |
678 | 36 | from plainbox.impl.unit import concrete_validators | ||
679 | 35 | from plainbox.impl.unit.unit_with_id import UnitWithId | 37 | from plainbox.impl.unit.unit_with_id import UnitWithId |
680 | 36 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 38 | from plainbox.impl.unit.validators import CorrectFieldValueValidator |
681 | 37 | from plainbox.impl.unit.validators import FieldValidatorBase | 39 | from plainbox.impl.unit.validators import FieldValidatorBase |
682 | 38 | from plainbox.impl.unit.validators import PresentFieldValidator | 40 | from plainbox.impl.unit.validators import PresentFieldValidator |
683 | 39 | from plainbox.impl.unit.validators import ReferenceConstraint | 41 | from plainbox.impl.unit.validators import ReferenceConstraint |
684 | 40 | from plainbox.impl.unit.validators import TemplateInvariantFieldValidator | 42 | from plainbox.impl.unit.validators import TemplateInvariantFieldValidator |
685 | 41 | from plainbox.impl.unit.validators import TemplateVariantFieldValidator | ||
686 | 42 | from plainbox.impl.unit.validators import TranslatableFieldValidator | ||
687 | 43 | from plainbox.impl.unit.validators import UnitReferenceValidator | 43 | from plainbox.impl.unit.validators import UnitReferenceValidator |
688 | 44 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
689 | 45 | from plainbox.impl.unit.validators import compute_value_map | 44 | from plainbox.impl.unit.validators import compute_value_map |
690 | 46 | from plainbox.impl.validation import Problem | 45 | from plainbox.impl.validation import Problem |
691 | 47 | from plainbox.impl.validation import Severity | 46 | from plainbox.impl.validation import Severity |
692 | @@ -609,40 +608,30 @@ | |||
693 | 609 | 608 | ||
694 | 610 | field_validators = { | 609 | field_validators = { |
695 | 611 | fields.name: [ | 610 | fields.name: [ |
711 | 612 | TranslatableFieldValidator, | 611 | concrete_validators.translatable, |
712 | 613 | TemplateVariantFieldValidator, | 612 | concrete_validators.templateVariant, |
713 | 614 | PresentFieldValidator, | 613 | concrete_validators.present, |
714 | 615 | # We want the summary to be a single line | 614 | concrete_validators.oneLine, |
715 | 616 | CorrectFieldValueValidator( | 615 | concrete_validators.shortValue, |
701 | 617 | lambda name: name.count("\n") == 0, | ||
702 | 618 | Problem.wrong, Severity.warning, | ||
703 | 619 | message=_("please use only one line"), | ||
704 | 620 | onlyif=lambda unit: unit.name is not None), | ||
705 | 621 | # We want the summary to be relatively short | ||
706 | 622 | CorrectFieldValueValidator( | ||
707 | 623 | lambda name: len(name) <= 80, | ||
708 | 624 | Problem.wrong, Severity.warning, | ||
709 | 625 | message=_("please stay under 80 characters"), | ||
710 | 626 | onlyif=lambda unit: unit.name is not None), | ||
716 | 627 | ], | 616 | ], |
717 | 628 | fields.description: [ | 617 | fields.description: [ |
720 | 629 | TranslatableFieldValidator, | 618 | concrete_validators.translatable, |
721 | 630 | TemplateVariantFieldValidator, | 619 | concrete_validators.templateVariant, |
722 | 631 | PresentFieldValidator( | 620 | PresentFieldValidator( |
723 | 632 | severity=Severity.advice, | 621 | severity=Severity.advice, |
724 | 633 | onlyif=lambda unit: unit.virtual is False), | 622 | onlyif=lambda unit: unit.virtual is False), |
725 | 634 | ], | 623 | ], |
726 | 635 | fields.include: [ | 624 | fields.include: [ |
729 | 636 | NonEmptyPatternIntersectionValidator, | 625 | NonEmptyPatternIntersectionValidator(), |
730 | 637 | PresentFieldValidator(), | 626 | concrete_validators.present, |
731 | 638 | ], | 627 | ], |
732 | 639 | fields.mandatory_include: [ | 628 | fields.mandatory_include: [ |
735 | 640 | NonEmptyPatternIntersectionValidator, | 629 | NonEmptyPatternIntersectionValidator(), |
736 | 641 | NoBaseIncludeValidator, | 630 | NoBaseIncludeValidator(), |
737 | 642 | ], | 631 | ], |
738 | 643 | fields.bootstrap_include: [ | 632 | fields.bootstrap_include: [ |
741 | 644 | UntranslatableFieldValidator, | 633 | concrete_validators.untranslatable, |
742 | 645 | NoBaseIncludeValidator, | 634 | NoBaseIncludeValidator(), |
743 | 646 | UnitReferenceValidator( | 635 | UnitReferenceValidator( |
744 | 647 | lambda unit: unit.get_bootstrap_job_ids(), | 636 | lambda unit: unit.get_bootstrap_job_ids(), |
745 | 648 | constraints=[ | 637 | constraints=[ |
746 | @@ -656,14 +645,14 @@ | |||
747 | 656 | "allowed in bootstrapping_include"))]) | 645 | "allowed in bootstrapping_include"))]) |
748 | 657 | ], | 646 | ], |
749 | 658 | fields.exclude: [ | 647 | fields.exclude: [ |
751 | 659 | NonEmptyPatternIntersectionValidator, | 648 | NonEmptyPatternIntersectionValidator(), |
752 | 660 | ], | 649 | ], |
753 | 661 | fields.nested_part: [ | 650 | fields.nested_part: [ |
755 | 662 | NonEmptyPatternIntersectionValidator, | 651 | NonEmptyPatternIntersectionValidator(), |
756 | 663 | ], | 652 | ], |
757 | 664 | fields.estimated_duration: [ | 653 | fields.estimated_duration: [ |
760 | 665 | UntranslatableFieldValidator, | 654 | concrete_validators.untranslatable, |
761 | 666 | TemplateInvariantFieldValidator, | 655 | concrete_validators.templateInvariant, |
762 | 667 | PresentFieldValidator( | 656 | PresentFieldValidator( |
763 | 668 | severity=Severity.advice, | 657 | severity=Severity.advice, |
764 | 669 | onlyif=lambda unit: unit.virtual is False), | 658 | onlyif=lambda unit: unit.virtual is False), |
765 | @@ -675,7 +664,7 @@ | |||
766 | 675 | unit.get_record_value('estimated_duration'))), | 664 | unit.get_record_value('estimated_duration'))), |
767 | 676 | ], | 665 | ], |
768 | 677 | fields.icon: [ | 666 | fields.icon: [ |
770 | 678 | UntranslatableFieldValidator, | 667 | concrete_validators.untranslatable, |
771 | 679 | ], | 668 | ], |
772 | 680 | fields.category_overrides: [ | 669 | fields.category_overrides: [ |
773 | 681 | # optional | 670 | # optional |
774 | 682 | 671 | ||
775 | === modified file 'plainbox/plainbox/impl/unit/unit.py' | |||
776 | --- plainbox/plainbox/impl/unit/unit.py 2016-05-20 13:54:59 +0000 | |||
777 | +++ plainbox/plainbox/impl/unit/unit.py 2016-09-28 20:21:08 +0000 | |||
778 | @@ -1,8 +1,9 @@ | |||
779 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
780 | 2 | # | 2 | # |
782 | 3 | # Copyright 2012-2014 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
783 | 4 | # Written by: | 4 | # Written by: |
784 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
785 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
786 | 6 | # | 7 | # |
787 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
788 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
789 | @@ -35,13 +36,12 @@ | |||
790 | 35 | from plainbox.impl.symbol import SymbolDef | 36 | from plainbox.impl.symbol import SymbolDef |
791 | 36 | from plainbox.impl.symbol import SymbolDefMeta | 37 | from plainbox.impl.symbol import SymbolDefMeta |
792 | 37 | from plainbox.impl.symbol import SymbolDefNs | 38 | from plainbox.impl.symbol import SymbolDefNs |
793 | 39 | from plainbox.impl.unit import concrete_validators | ||
794 | 38 | from plainbox.impl.unit import get_accessed_parameters | 40 | from plainbox.impl.unit import get_accessed_parameters |
795 | 39 | from plainbox.impl.unit.validators import IFieldValidator | 41 | from plainbox.impl.unit.validators import IFieldValidator |
796 | 40 | from plainbox.impl.unit.validators import MultiUnitFieldIssue | 42 | from plainbox.impl.unit.validators import MultiUnitFieldIssue |
797 | 41 | from plainbox.impl.unit.validators import PresentFieldValidator | 43 | from plainbox.impl.unit.validators import PresentFieldValidator |
798 | 42 | from plainbox.impl.unit.validators import TemplateInvariantFieldValidator | ||
799 | 43 | from plainbox.impl.unit.validators import UnitFieldIssue | 44 | from plainbox.impl.unit.validators import UnitFieldIssue |
800 | 44 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
801 | 45 | from plainbox.impl.validation import Problem | 45 | from plainbox.impl.validation import Problem |
802 | 46 | from plainbox.impl.validation import Severity | 46 | from plainbox.impl.validation import Severity |
803 | 47 | 47 | ||
804 | @@ -77,9 +77,10 @@ | |||
805 | 77 | :returns: | 77 | :returns: |
806 | 78 | A generator yielding subsequent issues | 78 | A generator yielding subsequent issues |
807 | 79 | """ | 79 | """ |
811 | 80 | for field_validator, field in self.make_field_validators(unit): | 80 | for field, validators in sorted(unit.Meta.field_validators.items()): |
812 | 81 | for issue in field_validator.check(self, unit, field): | 81 | for validator in validators: |
813 | 82 | yield issue | 82 | for issue in validator.check(self, unit, field): |
814 | 83 | yield issue | ||
815 | 83 | 84 | ||
816 | 84 | def check_in_context(self, unit, context): | 85 | def check_in_context(self, unit, context): |
817 | 85 | """ | 86 | """ |
818 | @@ -92,41 +93,11 @@ | |||
819 | 92 | :returns: | 93 | :returns: |
820 | 93 | A generator yielding subsequent issues | 94 | A generator yielding subsequent issues |
821 | 94 | """ | 95 | """ |
857 | 95 | for field_validator, field in self.make_field_validators(unit): | 96 | for field, validators in sorted(unit.Meta.field_validators.items()): |
858 | 96 | for issue in field_validator.check_in_context( | 97 | for validator in validators: |
859 | 97 | self, unit, field, context): | 98 | for issue in validator.check_in_context( |
860 | 98 | yield issue | 99 | self, unit, field, context): |
861 | 99 | 100 | yield issue | |
827 | 100 | def make_field_validators(self, unit): | ||
828 | 101 | """ | ||
829 | 102 | Convert unit meta-data to a sequence of validators | ||
830 | 103 | |||
831 | 104 | :returns: | ||
832 | 105 | A generator for pairs (field_validator, field) where | ||
833 | 106 | field_validator is an instance of :class:`IFieldValidator` and | ||
834 | 107 | field is a symbol with the field name. | ||
835 | 108 | """ | ||
836 | 109 | for field, spec in sorted(unit.Meta.field_validators.items()): | ||
837 | 110 | if isinstance(spec, type): | ||
838 | 111 | validator_list = [spec] | ||
839 | 112 | elif isinstance(spec, list): | ||
840 | 113 | validator_list = spec | ||
841 | 114 | else: | ||
842 | 115 | raise TypeError(_( | ||
843 | 116 | "{}.Meta.fields[{!r}] is not a validator" | ||
844 | 117 | ).format(unit.__class__.__name__, field)) | ||
845 | 118 | for index, spec in enumerate(validator_list): | ||
846 | 119 | # If it's a validator class, instantiate it | ||
847 | 120 | if isinstance(spec, type) \ | ||
848 | 121 | and issubclass(spec, IFieldValidator): | ||
849 | 122 | yield spec(), field | ||
850 | 123 | # If it's a validator instance, just return it | ||
851 | 124 | elif isinstance(spec, IFieldValidator): | ||
852 | 125 | yield spec, field | ||
853 | 126 | else: | ||
854 | 127 | raise TypeError(_( | ||
855 | 128 | "{}.Meta.fields[{!r}][{}] is not a validator" | ||
856 | 129 | ).format(unit.__class__.__name__, field, index)) | ||
862 | 130 | 101 | ||
863 | 131 | def advice(self, unit, field, kind, message=None, *, offset=0, | 102 | def advice(self, unit, field, kind, message=None, *, offset=0, |
864 | 132 | origin=None): | 103 | origin=None): |
865 | @@ -840,12 +811,8 @@ | |||
866 | 840 | 811 | ||
867 | 841 | field_validators = { | 812 | field_validators = { |
868 | 842 | fields.unit: [ | 813 | fields.unit: [ |
875 | 843 | # We don't want anyone marking unit type up for translation | 814 | concrete_validators.untranslatable, |
876 | 844 | UntranslatableFieldValidator, | 815 | concrete_validators.templateInvariant, |
871 | 845 | # We want each instantiated template to define same unit type | ||
872 | 846 | TemplateInvariantFieldValidator, | ||
873 | 847 | # We want to gently advise everyone to mark all units with | ||
874 | 848 | # and explicit unit type so that we can disable default 'job' | ||
877 | 849 | PresentFieldValidator( | 816 | PresentFieldValidator( |
878 | 850 | severity=Severity.advice, | 817 | severity=Severity.advice, |
879 | 851 | message=_("unit should explicitly define its type")), | 818 | message=_("unit should explicitly define its type")), |
880 | 852 | 819 | ||
881 | === modified file 'plainbox/plainbox/impl/unit/unit_with_id.py' | |||
882 | --- plainbox/plainbox/impl/unit/unit_with_id.py 2016-05-11 14:36:13 +0000 | |||
883 | +++ plainbox/plainbox/impl/unit/unit_with_id.py 2016-09-28 20:21:08 +0000 | |||
884 | @@ -1,8 +1,9 @@ | |||
885 | 1 | # This file is part of Checkbox. | 1 | # This file is part of Checkbox. |
886 | 2 | # | 2 | # |
888 | 3 | # Copyright 2012-2014 Canonical Ltd. | 3 | # Copyright 2012-2016 Canonical Ltd. |
889 | 4 | # Written by: | 4 | # Written by: |
890 | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> | 5 | # Zygmunt Krynicki <zygmunt.krynicki@canonical.com> |
891 | 6 | # Maciej Kisielewski <maciej.kisielewski@canonical.com> | ||
892 | 6 | # | 7 | # |
893 | 7 | # Checkbox is free software: you can redistribute it and/or modify | 8 | # Checkbox is free software: you can redistribute it and/or modify |
894 | 8 | # it under the terms of the GNU General Public License version 3, | 9 | # it under the terms of the GNU General Public License version 3, |
895 | @@ -26,13 +27,11 @@ | |||
896 | 26 | from plainbox.i18n import gettext as _ | 27 | from plainbox.i18n import gettext as _ |
897 | 27 | from plainbox.i18n import gettext_noop as N_ | 28 | from plainbox.i18n import gettext_noop as N_ |
898 | 28 | from plainbox.impl.symbol import SymbolDef | 29 | from plainbox.impl.symbol import SymbolDef |
899 | 30 | from plainbox.impl.unit import concrete_validators | ||
900 | 29 | from plainbox.impl.unit.unit import Unit | 31 | from plainbox.impl.unit.unit import Unit |
901 | 30 | from plainbox.impl.unit.unit import UnitValidator | 32 | from plainbox.impl.unit.unit import UnitValidator |
902 | 31 | from plainbox.impl.unit.validators import CorrectFieldValueValidator | 33 | from plainbox.impl.unit.validators import CorrectFieldValueValidator |
903 | 32 | from plainbox.impl.unit.validators import PresentFieldValidator | ||
904 | 33 | from plainbox.impl.unit.validators import TemplateVariantFieldValidator | ||
905 | 34 | from plainbox.impl.unit.validators import UniqueValueValidator | 34 | from plainbox.impl.unit.validators import UniqueValueValidator |
906 | 35 | from plainbox.impl.unit.validators import UntranslatableFieldValidator | ||
907 | 36 | 35 | ||
908 | 37 | __all__ = ['UnitWithId'] | 36 | __all__ = ['UnitWithId'] |
909 | 38 | 37 | ||
910 | @@ -111,14 +110,10 @@ | |||
911 | 111 | 110 | ||
912 | 112 | field_validators = { | 111 | field_validators = { |
913 | 113 | fields.id: [ | 112 | fields.id: [ |
922 | 114 | # We don't want anyone marking id up for translation | 113 | concrete_validators.untranslatable, |
923 | 115 | UntranslatableFieldValidator, | 114 | concrete_validators.present, |
924 | 116 | # We want this field to be present at all times | 115 | concrete_validators.templateVariant, |
925 | 117 | PresentFieldValidator, | 116 | UniqueValueValidator(), |
918 | 118 | # We want each instance to have a different identifier | ||
919 | 119 | TemplateVariantFieldValidator, | ||
920 | 120 | # When checking in a globally, all units need an unique value | ||
921 | 121 | UniqueValueValidator, | ||
926 | 122 | # We want to have bare, namespace-less identifiers | 117 | # We want to have bare, namespace-less identifiers |
927 | 123 | CorrectFieldValueValidator( | 118 | CorrectFieldValueValidator( |
928 | 124 | lambda value, unit: ( | 119 | lambda value, unit: ( |
929 | 125 | 120 | ||
930 | === modified file 'plainbox/plainbox/impl/unit/validators.py' | |||
931 | --- plainbox/plainbox/impl/unit/validators.py 2016-05-20 13:54:59 +0000 | |||
932 | +++ plainbox/plainbox/impl/unit/validators.py 2016-09-28 20:21:08 +0000 | |||
933 | @@ -364,6 +364,36 @@ | |||
934 | 364 | super().__init__(correct_fn, kind, severity, message, onlyif) | 364 | super().__init__(correct_fn, kind, severity, message, onlyif) |
935 | 365 | 365 | ||
936 | 366 | 366 | ||
937 | 367 | class MemberOfFieldValidator(CorrectFieldValueValidator): | ||
938 | 368 | """Validator ensuring the value is a member of a given set.""" | ||
939 | 369 | |||
940 | 370 | def __init__(self, possible_values, kind=None, severity=None, message=None, | ||
941 | 371 | onlyif=None): | ||
942 | 372 | """ | ||
943 | 373 | possible_values: | ||
944 | 374 | Iterable with values that the membership will be testsed against. | ||
945 | 375 | kind: | ||
946 | 376 | Kind of issue to report. By default this is Problem.useless | ||
947 | 377 | severity: | ||
948 | 378 | Severity of the issue to report. By default this is | ||
949 | 379 | Severity.warning | ||
950 | 380 | message: | ||
951 | 381 | Customized error message. This message will be used to report the | ||
952 | 382 | issue if the validation fails. By default it is derived from the | ||
953 | 383 | specified issue ``kind`` by :meth:`UnitValidator.explain()`. | ||
954 | 384 | onlyif: | ||
955 | 385 | An optional function that checks if this validator should be | ||
956 | 386 | applied or not. The function is called with the `unit` as the only | ||
957 | 387 | argument. If it returns True then the validator proceeds to | ||
958 | 388 | perform its check. | ||
959 | 389 | """ | ||
960 | 390 | def correct_fn(value): return value in possible_values | ||
961 | 391 | if not message: | ||
962 | 392 | message = _('valid values are: {}').format( | ||
963 | 393 | ', '.join(str(val) for val in sorted(possible_values))) | ||
964 | 394 | super().__init__(correct_fn, kind, severity, message, onlyif) | ||
965 | 395 | |||
966 | 396 | |||
967 | 367 | class DeprecatedFieldValidator(FieldValidatorBase): | 397 | class DeprecatedFieldValidator(FieldValidatorBase): |
968 | 368 | """ | 398 | """ |
969 | 369 | Validator ensuring that deprecated field is not used (passed a value) | 399 | Validator ensuring that deprecated field is not used (passed a value) |
Great stuff!
Just one question, see below, but applicable to all remaining PresentFieldVal idator( severity= Severity. advice) .