Merge lp:~kissiel/checkbox/validation-rework into lp:checkbox

Proposed by Maciej Kisielewski
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
Reviewer Review Type Date Requested Status
Sylvain Pineau (community) Approve
Review via email: mp+307082@code.launchpad.net

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.

To post a comment you must log in.
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

Great stuff!

Just one question, see below, but applicable to all remaining PresentFieldValidator(severity=Severity.advice).

review: Needs Information
Revision history for this message
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?

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

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

s/bug/big hehe

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plainbox/plainbox/impl/unit/category.py'
--- plainbox/plainbox/impl/unit/category.py 2016-05-11 14:36:13 +0000
+++ plainbox/plainbox/impl/unit/category.py 2016-09-28 20:21:08 +0000
@@ -30,16 +30,10 @@
3030
31import logging31import logging
3232
33from plainbox.i18n import gettext as _
34from plainbox.i18n import gettext_noop as N_33from plainbox.i18n import gettext_noop as N_
35from plainbox.impl.symbol import SymbolDef34from plainbox.impl.symbol import SymbolDef
35from plainbox.impl.unit import concrete_validators
36from plainbox.impl.unit.unit_with_id import UnitWithId36from plainbox.impl.unit.unit_with_id import UnitWithId
37from plainbox.impl.unit.validators import CorrectFieldValueValidator
38from plainbox.impl.unit.validators import PresentFieldValidator
39from plainbox.impl.unit.validators import TemplateVariantFieldValidator
40from plainbox.impl.unit.validators import TranslatableFieldValidator
41from plainbox.impl.validation import Problem
42from plainbox.impl.validation import Severity
4337
44__all__ = ['CategoryUnit']38__all__ = ['CategoryUnit']
4539
@@ -108,20 +102,10 @@
108102
109 field_validators = {103 field_validators = {
110 fields.name: [104 fields.name: [
111 TranslatableFieldValidator,105 concrete_validators.translatable,
112 TemplateVariantFieldValidator,106 concrete_validators.templateVariant,
113 PresentFieldValidator,107 concrete_validators.present,
114 # We want the name to be a single line108 concrete_validators.oneLine,
115 CorrectFieldValueValidator(109 concrete_validators.shortValue,
116 lambda name: name.count("\n") == 0,
117 Problem.wrong, Severity.warning,
118 message=_("please use only one line"),
119 onlyif=lambda unit: unit.name is not None),
120 # We want the name to be relatively short
121 CorrectFieldValueValidator(
122 lambda name: len(name) <= 80,
123 Problem.wrong, Severity.warning,
124 message=_("please stay under 80 characters"),
125 onlyif=lambda unit: unit.name is not None),
126 ]110 ]
127 }111 }
128112
=== added file 'plainbox/plainbox/impl/unit/concrete_validators.py'
--- plainbox/plainbox/impl/unit/concrete_validators.py 1970-01-01 00:00:00 +0000
+++ plainbox/plainbox/impl/unit/concrete_validators.py 2016-09-28 20:21:08 +0000
@@ -0,0 +1,57 @@
1# This file is part of Checkbox.
2#
3# Copyright 2016 Canonical Ltd.
4# Written by:
5# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#
7# Checkbox is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3,
9# as published by the Free Software Foundation.
10#
11# Checkbox is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
18"""
19:mod:`plainbox.impl.unit.concrete_validators` -- common validator instances
20===========================================================================
21
22This module gathers common validator instances that can be shared among
23multiple unit types as their field_validators.
24"""
25
26from plainbox.i18n import gettext as _
27from plainbox.impl.unit.validators import CorrectFieldValueValidator
28from plainbox.impl.validation import Problem
29from plainbox.impl.validation import Severity
30
31from plainbox.impl.unit.validators import PresentFieldValidator
32from plainbox.impl.unit.validators import TemplateInvariantFieldValidator
33from plainbox.impl.unit.validators import TemplateVariantFieldValidator
34from plainbox.impl.unit.validators import TranslatableFieldValidator
35from plainbox.impl.unit.validators import UntranslatableFieldValidator
36
37
38translatable = TranslatableFieldValidator()
39templateVariant = TemplateVariantFieldValidator()
40templateInvariant = TemplateInvariantFieldValidator()
41untranslatable = UntranslatableFieldValidator()
42present = PresentFieldValidator()
43
44localDeprecated = CorrectFieldValueValidator(
45 lambda plugin: plugin != 'local', Problem.deprecated, Severity.advice,
46 message=_("please migrate to job templates, see plainbox-template-unit(7)"
47 " for details"))
48
49oneLine = CorrectFieldValueValidator(
50 lambda field: field is not None and field.count("\n") == 0,
51 Problem.wrong, Severity.warning,
52 message=_("please use only one line"))
53
54shortValue = CorrectFieldValueValidator(
55 lambda field: field is not None and len(field) <= 80,
56 Problem.wrong, Severity.warning,
57 message=_("please stay under 80 characters"))
058
=== modified file 'plainbox/plainbox/impl/unit/exporter.py'
--- plainbox/plainbox/impl/unit/exporter.py 2015-06-25 11:52:05 +0000
+++ plainbox/plainbox/impl/unit/exporter.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2015 Canonical Ltd.3# Copyright 2015-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Sylvain Pineau <sylvain.pineau@canonical.com>5# Sylvain Pineau <sylvain.pineau@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -26,11 +27,10 @@
2627
27from plainbox.i18n import gettext as _28from plainbox.i18n import gettext as _
28from plainbox.impl.symbol import SymbolDef29from plainbox.impl.symbol import SymbolDef
30from plainbox.impl.unit import concrete_validators
29from plainbox.impl.unit.unit_with_id import UnitWithId31from plainbox.impl.unit.unit_with_id import UnitWithId
30from plainbox.impl.unit.validators import CorrectFieldValueValidator32from plainbox.impl.unit.validators import CorrectFieldValueValidator
31from plainbox.impl.unit.validators import PresentFieldValidator33from plainbox.impl.unit.validators import PresentFieldValidator
32from plainbox.impl.unit.validators import TranslatableFieldValidator
33from plainbox.impl.unit.validators import UntranslatableFieldValidator
34from plainbox.impl.validation import Problem34from plainbox.impl.validation import Problem
35from plainbox.impl.validation import Severity35from plainbox.impl.validation import Severity
3636
@@ -115,40 +115,30 @@
115 field_validators = {115 field_validators = {
116 fields.summary: [116 fields.summary: [
117 PresentFieldValidator(severity=Severity.advice),117 PresentFieldValidator(severity=Severity.advice),
118 TranslatableFieldValidator,118 concrete_validators.translatable,
119 # We want the summary to be a single line119 concrete_validators.oneLine,
120 CorrectFieldValueValidator(120 concrete_validators.shortValue,
121 lambda summary: summary.count("\n") == 0,
122 Problem.wrong, Severity.warning,
123 message=_("please use only one line"),
124 onlyif=lambda unit: unit.summary is not None),
125 # We want the summary to be relatively short
126 CorrectFieldValueValidator(
127 lambda summary: len(summary) <= 80,
128 Problem.wrong, Severity.warning,
129 message=_("please stay under 80 characters"),
130 onlyif=lambda unit: unit.summary is not None),
131 ],121 ],
132 fields.entry_point: [122 fields.entry_point: [
133 PresentFieldValidator,123 concrete_validators.present,
134 UntranslatableFieldValidator,124 concrete_validators.untranslatable,
135 CorrectFieldValueValidator(125 CorrectFieldValueValidator(
136 lambda entry_point: pkg_resources.load_entry_point(126 lambda entry_point: pkg_resources.load_entry_point(
137 'plainbox', 'plainbox.exporter', entry_point),127 'plainbox', 'plainbox.exporter', entry_point),
138 Problem.wrong, Severity.error),128 Problem.wrong, Severity.error),
139 ],129 ],
140 fields.file_extension: [130 fields.file_extension: [
141 PresentFieldValidator,131 concrete_validators.present,
142 UntranslatableFieldValidator,132 concrete_validators.untranslatable,
143 CorrectFieldValueValidator(133 CorrectFieldValueValidator(
144 lambda extension: re.search("^[\w\.\-]+$", extension),134 lambda extension: re.search("^[\w\.\-]+$", extension),
145 Problem.syntax_error, Severity.error),135 Problem.syntax_error, Severity.error),
146 ],136 ],
147 fields.options: [137 fields.options: [
148 UntranslatableFieldValidator,138 concrete_validators.untranslatable,
149 ],139 ],
150 fields.data: [140 fields.data: [
151 UntranslatableFieldValidator,141 concrete_validators.untranslatable,
152 CorrectFieldValueValidator(142 CorrectFieldValueValidator(
153 lambda value, unit: json.loads(value),143 lambda value, unit: json.loads(value),
154 Problem.syntax_error, Severity.error,144 Problem.syntax_error, Severity.error,
155145
=== modified file 'plainbox/plainbox/impl/unit/file.py'
--- plainbox/plainbox/impl/unit/file.py 2015-02-06 15:30:54 +0000
+++ plainbox/plainbox/impl/unit/file.py 2016-09-28 20:21:08 +0000
@@ -30,6 +30,7 @@
30from plainbox.impl.unit.job import propertywithsymbols30from plainbox.impl.unit.job import propertywithsymbols
31from plainbox.impl.unit.unit import Unit, UnitValidator31from plainbox.impl.unit.unit import Unit, UnitValidator
32from plainbox.impl.unit.validators import CorrectFieldValueValidator32from plainbox.impl.unit.validators import CorrectFieldValueValidator
33from plainbox.impl.unit.validators import MemberOfFieldValidator
33from plainbox.impl.validation import Problem34from plainbox.impl.validation import Problem
34from plainbox.impl.validation import Severity35from plainbox.impl.validation import Severity
3536
@@ -146,11 +147,5 @@
146 'faq.html#faq-1'147 'faq.html#faq-1'
147 )),148 )),
148 ],149 ],
149 fields.role: [150 fields.role: [MemberOfFieldValidator(FileRole.get_all_symbols())]
150 CorrectFieldValueValidator(
151 lambda value: value in FileRole.get_all_symbols(),
152 message=_('valid values are: {}').format(
153 ', '.join(str(sym) for sym in sorted(
154 FileRole.get_all_symbols())))),
155 ]
156 }151 }
157152
=== modified file 'plainbox/plainbox/impl/unit/job.py'
--- plainbox/plainbox/impl/unit/job.py 2016-09-22 18:53:53 +0000
+++ plainbox/plainbox/impl/unit/job.py 2016-09-28 20:21:08 +0000
@@ -1,9 +1,10 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2014 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Sylvain Pineau <sylvain.pineau@canonical.com>6# Sylvain Pineau <sylvain.pineau@canonical.com>
7# Maciej Kisielewski <maciej.kisielewski@canonical.com>
7#8#
8# Checkbox is free software: you can redistribute it and/or modify9# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -34,18 +35,17 @@
34from plainbox.impl.secure.origin import JobOutputTextSource35from plainbox.impl.secure.origin import JobOutputTextSource
35from plainbox.impl.secure.origin import Origin36from plainbox.impl.secure.origin import Origin
36from plainbox.impl.symbol import SymbolDef37from plainbox.impl.symbol import SymbolDef
38from plainbox.impl.unit import concrete_validators
37from plainbox.impl.unit.unit_with_id import UnitWithId39from plainbox.impl.unit.unit_with_id import UnitWithId
38from plainbox.impl.unit.validators import CorrectFieldValueValidator40from plainbox.impl.unit.validators import CorrectFieldValueValidator
39from plainbox.impl.unit.validators import DeprecatedFieldValidator41from plainbox.impl.unit.validators import DeprecatedFieldValidator
42from plainbox.impl.unit.validators import MemberOfFieldValidator
40from plainbox.impl.unit.validators import PresentFieldValidator43from plainbox.impl.unit.validators import PresentFieldValidator
41from plainbox.impl.unit.validators import ReferenceConstraint44from plainbox.impl.unit.validators import ReferenceConstraint
42from plainbox.impl.unit.validators import ShellProgramValidator45from plainbox.impl.unit.validators import ShellProgramValidator
43from plainbox.impl.unit.validators import TemplateInvariantFieldValidator
44from plainbox.impl.unit.validators import TemplateVariantFieldValidator
45from plainbox.impl.unit.validators import TranslatableFieldValidator
46from plainbox.impl.unit.validators import UnitReferenceValidator46from plainbox.impl.unit.validators import UnitReferenceValidator
47from plainbox.impl.unit.validators import UntranslatableFieldValidator
48from plainbox.impl.unit.validators import UselessFieldValidator47from plainbox.impl.unit.validators import UselessFieldValidator
48
49from plainbox.impl.validation import Problem49from plainbox.impl.validation import Problem
50from plainbox.impl.validation import Severity50from plainbox.impl.validation import Severity
51from plainbox.impl.xparsers import Error51from plainbox.impl.xparsers import Error
@@ -700,51 +700,32 @@
700700
701 field_validators = {701 field_validators = {
702 fields.name: [702 fields.name: [
703 UntranslatableFieldValidator,703 concrete_validators.untranslatable,
704 TemplateVariantFieldValidator,704 concrete_validators.templateVariant,
705 DeprecatedFieldValidator(705 DeprecatedFieldValidator(
706 _("use 'id' and 'summary' instead of 'name'")),706 _("use 'id' and 'summary' instead of 'name'")),
707 ],707 ],
708 # NOTE: 'id' validators are "inherited" so we don't have it here708 # NOTE: 'id' validators are "inherited" so we don't have it here
709 fields.summary: [709 fields.summary: [
710 TranslatableFieldValidator,710 concrete_validators.translatable,
711 TemplateVariantFieldValidator,711 concrete_validators.templateVariant,
712 PresentFieldValidator(severity=Severity.advice),712 PresentFieldValidator(severity=Severity.advice),
713 # We want the summary to be a single line713 concrete_validators.oneLine,
714 CorrectFieldValueValidator(714 concrete_validators.shortValue,
715 lambda summary: summary.count("\n") == 0,
716 Problem.wrong, Severity.warning,
717 message=_("please use only one line"),
718 onlyif=lambda unit: unit.summary is not None),
719 # We want the summary to be relatively short
720 CorrectFieldValueValidator(
721 lambda summary: len(summary) <= 80,
722 Problem.wrong, Severity.warning,
723 message=_("please stay under 80 characters"),
724 onlyif=lambda unit: unit.summary is not None),
725 ],715 ],
726 fields.plugin: [716 fields.plugin: [
727 UntranslatableFieldValidator,717 concrete_validators.untranslatable,
728 TemplateInvariantFieldValidator,718 concrete_validators.templateInvariant,
729 PresentFieldValidator,719 concrete_validators.present,
730 CorrectFieldValueValidator(720 MemberOfFieldValidator(_PluginValues.get_all_symbols()),
731 lambda plugin: (721 concrete_validators.localDeprecated,
732 plugin in JobDefinition.plugin.get_all_symbols()),
733 message=_('valid values are: {}').format(
734 ', '.join(str(sym) for sym in sorted(
735 _PluginValues.get_all_symbols())))),
736 CorrectFieldValueValidator(
737 lambda plugin: plugin != 'local',
738 Problem.deprecated, Severity.advice,
739 message=_("please migrate to job templates, "
740 "see plainbox-template-unit(7) for details")),
741 CorrectFieldValueValidator(722 CorrectFieldValueValidator(
742 lambda plugin: plugin != 'user-verify',723 lambda plugin: plugin != 'user-verify',
743 Problem.deprecated, Severity.advice,724 Problem.deprecated, Severity.advice,
744 message=_("please migrate to user-interact-verify")),725 message=_("please migrate to user-interact-verify")),
745 ],726 ],
746 fields.command: [727 fields.command: [
747 UntranslatableFieldValidator,728 concrete_validators.untranslatable,
748 # All jobs except for manual must have a command729 # All jobs except for manual must have a command
749 PresentFieldValidator(730 PresentFieldValidator(
750 message=_("command is mandatory for non-manual jobs"),731 message=_("command is mandatory for non-manual jobs"),
@@ -768,11 +749,11 @@
768 " instead of CHECKBOX_DATA"),749 " instead of CHECKBOX_DATA"),
769 onlyif=lambda unit: unit.command is not None),750 onlyif=lambda unit: unit.command is not None),
770 # We want to catch silly mistakes that shlex can detect751 # We want to catch silly mistakes that shlex can detect
771 ShellProgramValidator,752 ShellProgramValidator(),
772 ],753 ],
773 fields.description: [754 fields.description: [
774 TranslatableFieldValidator,755 concrete_validators.translatable,
775 TemplateVariantFieldValidator,756 concrete_validators.templateVariant,
776 # Description is mandatory for manual jobs757 # Description is mandatory for manual jobs
777 PresentFieldValidator(758 PresentFieldValidator(
778 message=_("manual jobs must have a description field, or a"759 message=_("manual jobs must have a description field, or a"
@@ -796,7 +777,7 @@
796 unit.verification is None))),777 unit.verification is None))),
797 ],778 ],
798 fields.purpose: [779 fields.purpose: [
799 TranslatableFieldValidator,780 concrete_validators.translatable,
800 PresentFieldValidator(781 PresentFieldValidator(
801 severity=Severity.advice,782 severity=Severity.advice,
802 message=("please use purpose, steps, and verification"783 message=("please use purpose, steps, and verification"
@@ -807,7 +788,7 @@
807 unit.get_record_value('summary') is None),788 unit.get_record_value('summary') is None),
808 ],789 ],
809 fields.steps: [790 fields.steps: [
810 TranslatableFieldValidator,791 concrete_validators.translatable,
811 PresentFieldValidator(792 PresentFieldValidator(
812 severity=Severity.advice,793 severity=Severity.advice,
813 message=("please use purpose, steps, and verification"794 message=("please use purpose, steps, and verification"
@@ -817,7 +798,7 @@
817 unit.startup_user_interaction_required),798 unit.startup_user_interaction_required),
818 ],799 ],
819 fields.verification: [800 fields.verification: [
820 TranslatableFieldValidator,801 concrete_validators.translatable,
821 PresentFieldValidator(802 PresentFieldValidator(
822 severity=Severity.advice,803 severity=Severity.advice,
823 message=("please use purpose, steps, and verification"804 message=("please use purpose, steps, and verification"
@@ -827,8 +808,8 @@
827 'manual', 'user-verify', 'user-interact-verify')),808 'manual', 'user-verify', 'user-interact-verify')),
828 ],809 ],
829 fields.user: [810 fields.user: [
830 UntranslatableFieldValidator,811 concrete_validators.untranslatable,
831 TemplateInvariantFieldValidator,812 concrete_validators.templateInvariant,
832 # User should be either None or 'root'813 # User should be either None or 'root'
833 CorrectFieldValueValidator(814 CorrectFieldValueValidator(
834 message=_("user can only be 'root'"),815 message=_("user can only be 'root'"),
@@ -839,16 +820,16 @@
839 onlyif=lambda unit: unit.command is None)820 onlyif=lambda unit: unit.command is None)
840 ],821 ],
841 fields.environ: [822 fields.environ: [
842 UntranslatableFieldValidator,823 concrete_validators.untranslatable,
843 TemplateInvariantFieldValidator,824 concrete_validators.templateInvariant,
844 # Environ is useless without a command to run825 # Environ is useless without a command to run
845 UselessFieldValidator(826 UselessFieldValidator(
846 message=_("environ without a command makes no sense"),827 message=_("environ without a command makes no sense"),
847 onlyif=lambda unit: unit.command is None),828 onlyif=lambda unit: unit.command is None),
848 ],829 ],
849 fields.estimated_duration: [830 fields.estimated_duration: [
850 UntranslatableFieldValidator,831 concrete_validators.untranslatable,
851 TemplateInvariantFieldValidator,832 concrete_validators.templateInvariant,
852 PresentFieldValidator(833 PresentFieldValidator(
853 severity=Severity.advice,834 severity=Severity.advice,
854 onlyif=lambda unit: 'simple' not in unit.get_flag_set()835 onlyif=lambda unit: 'simple' not in unit.get_flag_set()
@@ -860,7 +841,7 @@
860 unit.get_record_value('estimated_duration'))),841 unit.get_record_value('estimated_duration'))),
861 ],842 ],
862 fields.depends: [843 fields.depends: [
863 UntranslatableFieldValidator,844 concrete_validators.untranslatable,
864 CorrectFieldValueValidator(845 CorrectFieldValueValidator(
865 lambda value, unit: (846 lambda value, unit: (
866 unit.get_direct_dependencies() is not None)),847 unit.get_direct_dependencies() is not None)),
@@ -874,7 +855,7 @@
874 # onlyif job itself is not deprecated855 # onlyif job itself is not deprecated
875 ],856 ],
876 fields.after: [857 fields.after: [
877 UntranslatableFieldValidator,858 concrete_validators.untranslatable,
878 CorrectFieldValueValidator(859 CorrectFieldValueValidator(
879 lambda value, unit: (860 lambda value, unit: (
880 unit.get_after_dependencies() is not None)),861 unit.get_after_dependencies() is not None)),
@@ -886,7 +867,7 @@
886 message=_("the referenced unit is not a job"))])867 message=_("the referenced unit is not a job"))])
887 ],868 ],
888 fields.requires: [869 fields.requires: [
889 UntranslatableFieldValidator,870 concrete_validators.untranslatable,
890 CorrectFieldValueValidator(871 CorrectFieldValueValidator(
891 lambda value, unit: unit.get_resource_program(),872 lambda value, unit: unit.get_resource_program(),
892 onlyif=lambda unit: unit.requires is not None),873 onlyif=lambda unit: unit.requires is not None),
@@ -908,16 +889,16 @@
908 # onlyif job itself is not deprecated889 # onlyif job itself is not deprecated
909 ],890 ],
910 fields.shell: [891 fields.shell: [
911 UntranslatableFieldValidator,892 concrete_validators.untranslatable,
912 TemplateInvariantFieldValidator,893 concrete_validators.templateInvariant,
913 # Shell should be only '/bin/sh', or None (which gives bash)894 # Shell should be only '/bin/sh', or None (which gives bash)
914 CorrectFieldValueValidator(895 MemberOfFieldValidator(
915 lambda shell: shell in ('/bin/sh', '/bin/bash', 'bash'),896 ['/bin/sh', '/bin/bash', 'bash'],
916 message=_("only /bin/sh and /bin/bash are allowed")),897 message=_("only /bin/sh and /bin/bash are allowed")),
917 ],898 ],
918 fields.imports: [899 fields.imports: [
919 UntranslatableFieldValidator,900 concrete_validators.untranslatable,
920 TemplateInvariantFieldValidator,901 concrete_validators.templateInvariant,
921 CorrectFieldValueValidator(902 CorrectFieldValueValidator(
922 lambda value, unit: (903 lambda value, unit: (
923 list(unit.get_imported_jobs()) is not None)),904 list(unit.get_imported_jobs()) is not None)),
@@ -933,8 +914,8 @@
933 # onlyif job itself is not deprecated914 # onlyif job itself is not deprecated
934 ],915 ],
935 fields.category_id: [916 fields.category_id: [
936 UntranslatableFieldValidator,917 concrete_validators.untranslatable,
937 TemplateInvariantFieldValidator,918 concrete_validators.templateInvariant,
938 UnitReferenceValidator(919 UnitReferenceValidator(
939 lambda unit: (920 lambda unit: (
940 [unit.get_category_id()] if unit.category_id else ()),921 [unit.get_category_id()] if unit.category_id else ()),
@@ -948,8 +929,8 @@
948 # onlyif job itself is not deprecated929 # onlyif job itself is not deprecated
949 ],930 ],
950 fields.flags: [931 fields.flags: [
951 UntranslatableFieldValidator,932 concrete_validators.untranslatable,
952 TemplateInvariantFieldValidator,933 concrete_validators.templateInvariant,
953 CorrectFieldValueValidator(934 CorrectFieldValueValidator(
954 lambda value, unit: (935 lambda value, unit: (
955 'simple' in unit.get_flag_set() or936 'simple' in unit.get_flag_set() or
@@ -999,8 +980,8 @@
999 onlyif=lambda unit: unit.command is None),980 onlyif=lambda unit: unit.command is None),
1000 ],981 ],
1001 fields.qml_file: [982 fields.qml_file: [
1002 UntranslatableFieldValidator,983 concrete_validators.untranslatable,
1003 TemplateInvariantFieldValidator,984 concrete_validators.templateInvariant,
1004 PresentFieldValidator(985 PresentFieldValidator(
1005 onlyif=lambda unit: unit.plugin == 'qml'),986 onlyif=lambda unit: unit.plugin == 'qml'),
1006 CorrectFieldValueValidator(987 CorrectFieldValueValidator(
@@ -1016,14 +997,9 @@
1016 unit.qml_file)),997 unit.qml_file)),
1017 ],998 ],
1018 fields.certification_status: [999 fields.certification_status: [
1019 UntranslatableFieldValidator,1000 concrete_validators.untranslatable,
1020 TemplateInvariantFieldValidator,1001 concrete_validators.templateInvariant,
1021 CorrectFieldValueValidator(1002 MemberOfFieldValidator(
1022 lambda certification_status: (1003 _CertificationStatusValues.get_all_symbols()),
1023 certification_status in
1024 _CertificationStatusValues.get_all_symbols()),
1025 message=_('valid values are: {}').format(
1026 ', '.join(str(sym) for sym in sorted(
1027 _CertificationStatusValues.get_all_symbols())))),
1028 ],1004 ],
1029 }1005 }
10301006
=== modified file 'plainbox/plainbox/impl/unit/manifest.py'
--- plainbox/plainbox/impl/unit/manifest.py 2015-03-30 17:35:30 +0000
+++ plainbox/plainbox/impl/unit/manifest.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2015 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -20,12 +21,9 @@
20import logging21import logging
2122
22from plainbox.impl.symbol import SymbolDef23from plainbox.impl.symbol import SymbolDef
24from plainbox.impl.unit import concrete_validators
23from plainbox.impl.unit.unit_with_id import UnitWithId25from plainbox.impl.unit.unit_with_id import UnitWithId
24from plainbox.impl.unit.validators import CorrectFieldValueValidator26from plainbox.impl.unit.validators import MemberOfFieldValidator
25from plainbox.impl.unit.validators import PresentFieldValidator
26from plainbox.impl.unit.validators import TemplateVariantFieldValidator
27from plainbox.impl.unit.validators import TranslatableFieldValidator
28from plainbox.impl.unit.validators import UntranslatableFieldValidator
2927
30logger = logging.getLogger("plainbox.unit.manifest")28logger = logging.getLogger("plainbox.unit.manifest")
3129
@@ -98,20 +96,19 @@
9896
99 field_validators = {97 field_validators = {
100 fields.name: [98 fields.name: [
101 TranslatableFieldValidator,99 concrete_validators.translatable,
102 TemplateVariantFieldValidator,100 concrete_validators.templateVariant,
103 PresentFieldValidator,101 concrete_validators.present,
104 ],102 ],
105 fields.value_type: [103 fields.value_type: [
106 UntranslatableFieldValidator,104 concrete_validators.untranslatable,
107 PresentFieldValidator(),105 concrete_validators.present,
108 CorrectFieldValueValidator(106 MemberOfFieldValidator(['bool', 'natural']),
109 lambda value_type: value_type in ('bool', 'natural')),
110 ],107 ],
111 fields.value_unit: [108 fields.value_unit: [
112 # OPTIONAL109 # OPTIONAL
113 ],110 ],
114 fields.resource_key: [111 fields.resource_key: [
115 UntranslatableFieldValidator,112 concrete_validators.untranslatable
116 ]113 ]
117 }114 }
118115
=== modified file 'plainbox/plainbox/impl/unit/packaging.py'
--- plainbox/plainbox/impl/unit/packaging.py 2016-05-20 13:54:59 +0000
+++ plainbox/plainbox/impl/unit/packaging.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2015 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -120,9 +121,8 @@
120from plainbox.i18n import gettext as _121from plainbox.i18n import gettext as _
121from plainbox.impl.device import get_os_release122from plainbox.impl.device import get_os_release
122from plainbox.impl.symbol import SymbolDef123from plainbox.impl.symbol import SymbolDef
124from plainbox.impl.unit import concrete_validators
123from plainbox.impl.unit.unit import Unit125from plainbox.impl.unit.unit import Unit
124from plainbox.impl.unit.validators import PresentFieldValidator
125from plainbox.impl.unit.validators import UntranslatableFieldValidator
126126
127_logger = logging.getLogger("plainbox.unit.packaging")127_logger = logging.getLogger("plainbox.unit.packaging")
128128
@@ -164,11 +164,11 @@
164164
165 field_validators = {165 field_validators = {
166 fields.os_id: [166 fields.os_id: [
167 UntranslatableFieldValidator,167 concrete_validators.untranslatable,
168 PresentFieldValidator,168 concrete_validators.present,
169 ],169 ],
170 fields.os_version_id: [170 fields.os_version_id: [
171 UntranslatableFieldValidator,171 concrete_validators.untranslatable,
172 ],172 ],
173 }173 }
174174
175175
=== modified file 'plainbox/plainbox/impl/unit/template.py'
--- plainbox/plainbox/impl/unit/template.py 2016-05-11 14:36:13 +0000
+++ plainbox/plainbox/impl/unit/template.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2014 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -32,14 +33,13 @@
32from plainbox.impl.secure.origin import Origin33from plainbox.impl.secure.origin import Origin
33from plainbox.impl.symbol import SymbolDef34from plainbox.impl.symbol import SymbolDef
34from plainbox.impl.unit import all_units35from plainbox.impl.unit import all_units
36from plainbox.impl.unit import concrete_validators
35from plainbox.impl.unit import get_accessed_parameters37from plainbox.impl.unit import get_accessed_parameters
36from plainbox.impl.unit.unit import Unit38from plainbox.impl.unit.unit import Unit
37from plainbox.impl.unit.unit import UnitValidator39from plainbox.impl.unit.unit import UnitValidator
38from plainbox.impl.unit.validators import CorrectFieldValueValidator40from plainbox.impl.unit.validators import CorrectFieldValueValidator
39from plainbox.impl.unit.validators import PresentFieldValidator
40from plainbox.impl.unit.validators import ReferenceConstraint41from plainbox.impl.unit.validators import ReferenceConstraint
41from plainbox.impl.unit.validators import UnitReferenceValidator42from plainbox.impl.unit.validators import UnitReferenceValidator
42from plainbox.impl.unit.validators import UntranslatableFieldValidator
43from plainbox.impl.validation import Problem43from plainbox.impl.validation import Problem
44from plainbox.impl.validation import Severity44from plainbox.impl.validation import Severity
4545
@@ -427,7 +427,7 @@
427427
428 field_validators = {428 field_validators = {
429 fields.template_unit: [429 fields.template_unit: [
430 UntranslatableFieldValidator,430 concrete_validators.untranslatable,
431 CorrectFieldValueValidator(431 CorrectFieldValueValidator(
432 lambda value, unit: (432 lambda value, unit: (
433 unit.get_record_value('template-unit') is not None),433 unit.get_record_value('template-unit') is not None),
@@ -436,8 +436,8 @@
436 " unit type")),436 " unit type")),
437 ],437 ],
438 fields.template_resource: [438 fields.template_resource: [
439 UntranslatableFieldValidator,439 concrete_validators.untranslatable,
440 PresentFieldValidator,440 concrete_validators.present,
441 UnitReferenceValidator(441 UnitReferenceValidator(
442 lambda unit: (442 lambda unit: (
443 [unit.resource_id] if unit.resource_id else []),443 [unit.resource_id] if unit.resource_id else []),
@@ -457,7 +457,7 @@
457 # onlyif job itself is not deprecated457 # onlyif job itself is not deprecated
458 ],458 ],
459 fields.template_filter: [459 fields.template_filter: [
460 UntranslatableFieldValidator,460 concrete_validators.untranslatable,
461 # All templates need a valid (or empty) template filter461 # All templates need a valid (or empty) template filter
462 CorrectFieldValueValidator(462 CorrectFieldValueValidator(
463 lambda value, unit: unit.get_filter_program(),463 lambda value, unit: unit.get_filter_program(),
@@ -465,7 +465,7 @@
465 # TODO: must refer to the same job as template-resource465 # TODO: must refer to the same job as template-resource
466 ],466 ],
467 fields.template_imports: [467 fields.template_imports: [
468 UntranslatableFieldValidator,468 concrete_validators.untranslatable,
469 CorrectFieldValueValidator(469 CorrectFieldValueValidator(
470 lambda value, unit: (470 lambda value, unit: (
471 list(unit.get_imported_jobs()) is not None)),471 list(unit.get_imported_jobs()) is not None)),
472472
=== modified file 'plainbox/plainbox/impl/unit/testplan.py'
--- plainbox/plainbox/impl/unit/testplan.py 2016-06-09 20:12:35 +0000
+++ plainbox/plainbox/impl/unit/testplan.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2014 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -32,16 +33,14 @@
32from plainbox.impl.secure.qualifiers import OperatorMatcher33from plainbox.impl.secure.qualifiers import OperatorMatcher
33from plainbox.impl.secure.qualifiers import PatternMatcher34from plainbox.impl.secure.qualifiers import PatternMatcher
34from plainbox.impl.symbol import SymbolDef35from plainbox.impl.symbol import SymbolDef
36from plainbox.impl.unit import concrete_validators
35from plainbox.impl.unit.unit_with_id import UnitWithId37from plainbox.impl.unit.unit_with_id import UnitWithId
36from plainbox.impl.unit.validators import CorrectFieldValueValidator38from plainbox.impl.unit.validators import CorrectFieldValueValidator
37from plainbox.impl.unit.validators import FieldValidatorBase39from plainbox.impl.unit.validators import FieldValidatorBase
38from plainbox.impl.unit.validators import PresentFieldValidator40from plainbox.impl.unit.validators import PresentFieldValidator
39from plainbox.impl.unit.validators import ReferenceConstraint41from plainbox.impl.unit.validators import ReferenceConstraint
40from plainbox.impl.unit.validators import TemplateInvariantFieldValidator42from plainbox.impl.unit.validators import TemplateInvariantFieldValidator
41from plainbox.impl.unit.validators import TemplateVariantFieldValidator
42from plainbox.impl.unit.validators import TranslatableFieldValidator
43from plainbox.impl.unit.validators import UnitReferenceValidator43from plainbox.impl.unit.validators import UnitReferenceValidator
44from plainbox.impl.unit.validators import UntranslatableFieldValidator
45from plainbox.impl.unit.validators import compute_value_map44from plainbox.impl.unit.validators import compute_value_map
46from plainbox.impl.validation import Problem45from plainbox.impl.validation import Problem
47from plainbox.impl.validation import Severity46from plainbox.impl.validation import Severity
@@ -609,40 +608,30 @@
609608
610 field_validators = {609 field_validators = {
611 fields.name: [610 fields.name: [
612 TranslatableFieldValidator,611 concrete_validators.translatable,
613 TemplateVariantFieldValidator,612 concrete_validators.templateVariant,
614 PresentFieldValidator,613 concrete_validators.present,
615 # We want the summary to be a single line614 concrete_validators.oneLine,
616 CorrectFieldValueValidator(615 concrete_validators.shortValue,
617 lambda name: name.count("\n") == 0,
618 Problem.wrong, Severity.warning,
619 message=_("please use only one line"),
620 onlyif=lambda unit: unit.name is not None),
621 # We want the summary to be relatively short
622 CorrectFieldValueValidator(
623 lambda name: len(name) <= 80,
624 Problem.wrong, Severity.warning,
625 message=_("please stay under 80 characters"),
626 onlyif=lambda unit: unit.name is not None),
627 ],616 ],
628 fields.description: [617 fields.description: [
629 TranslatableFieldValidator,618 concrete_validators.translatable,
630 TemplateVariantFieldValidator,619 concrete_validators.templateVariant,
631 PresentFieldValidator(620 PresentFieldValidator(
632 severity=Severity.advice,621 severity=Severity.advice,
633 onlyif=lambda unit: unit.virtual is False),622 onlyif=lambda unit: unit.virtual is False),
634 ],623 ],
635 fields.include: [624 fields.include: [
636 NonEmptyPatternIntersectionValidator,625 NonEmptyPatternIntersectionValidator(),
637 PresentFieldValidator(),626 concrete_validators.present,
638 ],627 ],
639 fields.mandatory_include: [628 fields.mandatory_include: [
640 NonEmptyPatternIntersectionValidator,629 NonEmptyPatternIntersectionValidator(),
641 NoBaseIncludeValidator,630 NoBaseIncludeValidator(),
642 ],631 ],
643 fields.bootstrap_include: [632 fields.bootstrap_include: [
644 UntranslatableFieldValidator,633 concrete_validators.untranslatable,
645 NoBaseIncludeValidator,634 NoBaseIncludeValidator(),
646 UnitReferenceValidator(635 UnitReferenceValidator(
647 lambda unit: unit.get_bootstrap_job_ids(),636 lambda unit: unit.get_bootstrap_job_ids(),
648 constraints=[637 constraints=[
@@ -656,14 +645,14 @@
656 "allowed in bootstrapping_include"))])645 "allowed in bootstrapping_include"))])
657 ],646 ],
658 fields.exclude: [647 fields.exclude: [
659 NonEmptyPatternIntersectionValidator,648 NonEmptyPatternIntersectionValidator(),
660 ],649 ],
661 fields.nested_part: [650 fields.nested_part: [
662 NonEmptyPatternIntersectionValidator,651 NonEmptyPatternIntersectionValidator(),
663 ],652 ],
664 fields.estimated_duration: [653 fields.estimated_duration: [
665 UntranslatableFieldValidator,654 concrete_validators.untranslatable,
666 TemplateInvariantFieldValidator,655 concrete_validators.templateInvariant,
667 PresentFieldValidator(656 PresentFieldValidator(
668 severity=Severity.advice,657 severity=Severity.advice,
669 onlyif=lambda unit: unit.virtual is False),658 onlyif=lambda unit: unit.virtual is False),
@@ -675,7 +664,7 @@
675 unit.get_record_value('estimated_duration'))),664 unit.get_record_value('estimated_duration'))),
676 ],665 ],
677 fields.icon: [666 fields.icon: [
678 UntranslatableFieldValidator,667 concrete_validators.untranslatable,
679 ],668 ],
680 fields.category_overrides: [669 fields.category_overrides: [
681 # optional670 # optional
682671
=== modified file 'plainbox/plainbox/impl/unit/unit.py'
--- plainbox/plainbox/impl/unit/unit.py 2016-05-20 13:54:59 +0000
+++ plainbox/plainbox/impl/unit/unit.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2014 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -35,13 +36,12 @@
35from plainbox.impl.symbol import SymbolDef36from plainbox.impl.symbol import SymbolDef
36from plainbox.impl.symbol import SymbolDefMeta37from plainbox.impl.symbol import SymbolDefMeta
37from plainbox.impl.symbol import SymbolDefNs38from plainbox.impl.symbol import SymbolDefNs
39from plainbox.impl.unit import concrete_validators
38from plainbox.impl.unit import get_accessed_parameters40from plainbox.impl.unit import get_accessed_parameters
39from plainbox.impl.unit.validators import IFieldValidator41from plainbox.impl.unit.validators import IFieldValidator
40from plainbox.impl.unit.validators import MultiUnitFieldIssue42from plainbox.impl.unit.validators import MultiUnitFieldIssue
41from plainbox.impl.unit.validators import PresentFieldValidator43from plainbox.impl.unit.validators import PresentFieldValidator
42from plainbox.impl.unit.validators import TemplateInvariantFieldValidator
43from plainbox.impl.unit.validators import UnitFieldIssue44from plainbox.impl.unit.validators import UnitFieldIssue
44from plainbox.impl.unit.validators import UntranslatableFieldValidator
45from plainbox.impl.validation import Problem45from plainbox.impl.validation import Problem
46from plainbox.impl.validation import Severity46from plainbox.impl.validation import Severity
4747
@@ -77,9 +77,10 @@
77 :returns:77 :returns:
78 A generator yielding subsequent issues78 A generator yielding subsequent issues
79 """79 """
80 for field_validator, field in self.make_field_validators(unit):80 for field, validators in sorted(unit.Meta.field_validators.items()):
81 for issue in field_validator.check(self, unit, field):81 for validator in validators:
82 yield issue82 for issue in validator.check(self, unit, field):
83 yield issue
8384
84 def check_in_context(self, unit, context):85 def check_in_context(self, unit, context):
85 """86 """
@@ -92,41 +93,11 @@
92 :returns:93 :returns:
93 A generator yielding subsequent issues94 A generator yielding subsequent issues
94 """95 """
95 for field_validator, field in self.make_field_validators(unit):96 for field, validators in sorted(unit.Meta.field_validators.items()):
96 for issue in field_validator.check_in_context(97 for validator in validators:
97 self, unit, field, context):98 for issue in validator.check_in_context(
98 yield issue99 self, unit, field, context):
99100 yield issue
100 def make_field_validators(self, unit):
101 """
102 Convert unit meta-data to a sequence of validators
103
104 :returns:
105 A generator for pairs (field_validator, field) where
106 field_validator is an instance of :class:`IFieldValidator` and
107 field is a symbol with the field name.
108 """
109 for field, spec in sorted(unit.Meta.field_validators.items()):
110 if isinstance(spec, type):
111 validator_list = [spec]
112 elif isinstance(spec, list):
113 validator_list = spec
114 else:
115 raise TypeError(_(
116 "{}.Meta.fields[{!r}] is not a validator"
117 ).format(unit.__class__.__name__, field))
118 for index, spec in enumerate(validator_list):
119 # If it's a validator class, instantiate it
120 if isinstance(spec, type) \
121 and issubclass(spec, IFieldValidator):
122 yield spec(), field
123 # If it's a validator instance, just return it
124 elif isinstance(spec, IFieldValidator):
125 yield spec, field
126 else:
127 raise TypeError(_(
128 "{}.Meta.fields[{!r}][{}] is not a validator"
129 ).format(unit.__class__.__name__, field, index))
130101
131 def advice(self, unit, field, kind, message=None, *, offset=0,102 def advice(self, unit, field, kind, message=None, *, offset=0,
132 origin=None):103 origin=None):
@@ -840,12 +811,8 @@
840811
841 field_validators = {812 field_validators = {
842 fields.unit: [813 fields.unit: [
843 # We don't want anyone marking unit type up for translation814 concrete_validators.untranslatable,
844 UntranslatableFieldValidator,815 concrete_validators.templateInvariant,
845 # We want each instantiated template to define same unit type
846 TemplateInvariantFieldValidator,
847 # We want to gently advise everyone to mark all units with
848 # and explicit unit type so that we can disable default 'job'
849 PresentFieldValidator(816 PresentFieldValidator(
850 severity=Severity.advice,817 severity=Severity.advice,
851 message=_("unit should explicitly define its type")),818 message=_("unit should explicitly define its type")),
852819
=== modified file 'plainbox/plainbox/impl/unit/unit_with_id.py'
--- plainbox/plainbox/impl/unit/unit_with_id.py 2016-05-11 14:36:13 +0000
+++ plainbox/plainbox/impl/unit/unit_with_id.py 2016-09-28 20:21:08 +0000
@@ -1,8 +1,9 @@
1# This file is part of Checkbox.1# This file is part of Checkbox.
2#2#
3# Copyright 2012-2014 Canonical Ltd.3# Copyright 2012-2016 Canonical Ltd.
4# Written by:4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6# Maciej Kisielewski <maciej.kisielewski@canonical.com>
6#7#
7# Checkbox is free software: you can redistribute it and/or modify8# Checkbox is free software: you can redistribute it and/or modify
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,
@@ -26,13 +27,11 @@
26from plainbox.i18n import gettext as _27from plainbox.i18n import gettext as _
27from plainbox.i18n import gettext_noop as N_28from plainbox.i18n import gettext_noop as N_
28from plainbox.impl.symbol import SymbolDef29from plainbox.impl.symbol import SymbolDef
30from plainbox.impl.unit import concrete_validators
29from plainbox.impl.unit.unit import Unit31from plainbox.impl.unit.unit import Unit
30from plainbox.impl.unit.unit import UnitValidator32from plainbox.impl.unit.unit import UnitValidator
31from plainbox.impl.unit.validators import CorrectFieldValueValidator33from plainbox.impl.unit.validators import CorrectFieldValueValidator
32from plainbox.impl.unit.validators import PresentFieldValidator
33from plainbox.impl.unit.validators import TemplateVariantFieldValidator
34from plainbox.impl.unit.validators import UniqueValueValidator34from plainbox.impl.unit.validators import UniqueValueValidator
35from plainbox.impl.unit.validators import UntranslatableFieldValidator
3635
37__all__ = ['UnitWithId']36__all__ = ['UnitWithId']
3837
@@ -111,14 +110,10 @@
111110
112 field_validators = {111 field_validators = {
113 fields.id: [112 fields.id: [
114 # We don't want anyone marking id up for translation113 concrete_validators.untranslatable,
115 UntranslatableFieldValidator,114 concrete_validators.present,
116 # We want this field to be present at all times115 concrete_validators.templateVariant,
117 PresentFieldValidator,116 UniqueValueValidator(),
118 # We want each instance to have a different identifier
119 TemplateVariantFieldValidator,
120 # When checking in a globally, all units need an unique value
121 UniqueValueValidator,
122 # We want to have bare, namespace-less identifiers117 # We want to have bare, namespace-less identifiers
123 CorrectFieldValueValidator(118 CorrectFieldValueValidator(
124 lambda value, unit: (119 lambda value, unit: (
125120
=== modified file 'plainbox/plainbox/impl/unit/validators.py'
--- plainbox/plainbox/impl/unit/validators.py 2016-05-20 13:54:59 +0000
+++ plainbox/plainbox/impl/unit/validators.py 2016-09-28 20:21:08 +0000
@@ -364,6 +364,36 @@
364 super().__init__(correct_fn, kind, severity, message, onlyif)364 super().__init__(correct_fn, kind, severity, message, onlyif)
365365
366366
367class MemberOfFieldValidator(CorrectFieldValueValidator):
368 """Validator ensuring the value is a member of a given set."""
369
370 def __init__(self, possible_values, kind=None, severity=None, message=None,
371 onlyif=None):
372 """
373 possible_values:
374 Iterable with values that the membership will be testsed against.
375 kind:
376 Kind of issue to report. By default this is Problem.useless
377 severity:
378 Severity of the issue to report. By default this is
379 Severity.warning
380 message:
381 Customized error message. This message will be used to report the
382 issue if the validation fails. By default it is derived from the
383 specified issue ``kind`` by :meth:`UnitValidator.explain()`.
384 onlyif:
385 An optional function that checks if this validator should be
386 applied or not. The function is called with the `unit` as the only
387 argument. If it returns True then the validator proceeds to
388 perform its check.
389 """
390 def correct_fn(value): return value in possible_values
391 if not message:
392 message = _('valid values are: {}').format(
393 ', '.join(str(val) for val in sorted(possible_values)))
394 super().__init__(correct_fn, kind, severity, message, onlyif)
395
396
367class DeprecatedFieldValidator(FieldValidatorBase):397class DeprecatedFieldValidator(FieldValidatorBase):
368 """398 """
369 Validator ensuring that deprecated field is not used (passed a value)399 Validator ensuring that deprecated field is not used (passed a value)

Subscribers

People subscribed via source and target branches