From 4ea6fbc2b71c019021b318def1edc6fdb1b40431 Mon Sep 17 00:00:00 2001 From: Pierre Equoy Date: Mon, 12 Feb 2024 21:41:16 +0800 Subject: [PATCH 1/4] Add template-summary and template-description fields and validators Add two fields for the Template Unit: - template-summary - template-description These fields mimick the summary and description fields of the Job Unit to provide a quick explanation and a longer form one about what a template unit does. Both these fields are translatable, and validation is added for the template-summary field to make sure if a value is provided, it is one line only and is less than 80 characters. --- checkbox-ng/plainbox/impl/unit/template.py | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/checkbox-ng/plainbox/impl/unit/template.py b/checkbox-ng/plainbox/impl/unit/template.py index 3df94fc07e..8941138ff9 100644 --- a/checkbox-ng/plainbox/impl/unit/template.py +++ b/checkbox-ng/plainbox/impl/unit/template.py @@ -27,6 +27,7 @@ from plainbox.i18n import gettext as _ from plainbox.i18n import gettext_noop as N_ +from plainbox.impl.decorators import instance_method_lru_cache from plainbox.impl.resource import ExpressionFailedError from plainbox.impl.resource import Resource from plainbox.impl.resource import ResourceProgram @@ -39,10 +40,12 @@ from plainbox.impl.unit.unit_with_id import UnitWithId from plainbox.impl.unit.unit_with_id import UnitWithIdValidator from plainbox.impl.unit.validators import CorrectFieldValueValidator +from plainbox.impl.unit.validators import PresentFieldValidator from plainbox.impl.unit.validators import ReferenceConstraint from plainbox.impl.unit.validators import UnitReferenceValidator from plainbox.impl.unit.validators import UniqueValueValidator from plainbox.impl.validation import Problem +from plainbox.impl.validation import Severity __all__ = ['TemplateUnit'] @@ -295,6 +298,40 @@ def template_imports(self): """ return self.get_record_value('template-imports') + @property + def template_summary(self): + """ + Value of the 'template-summary' field. + + This attribute stores the summary of a template, that is a human + readable name for that template. + """ + return self.get_record_value("template-summary") + + @instance_method_lru_cache(maxsize=None) + def tr_template_summary(self): + """ + Get the translated version of :meth:`template_summary`. + """ + return self.get_translated_record_value("template-summary") + + @property + def template_description(self): + """ + Value of the 'template-description' field. + + This attribute stores the definition of a template which can be used + to provide more information about this template. + """ + return self.get_record_value("template-description") + + @instance_method_lru_cache(maxsize=None) + def tr_template_description(self): + """ + Get the translated version of :meth:`template_description`. + """ + return self.get_translated_record_value("template-description") + @property def template_unit(self): """ @@ -488,6 +525,8 @@ class fields(SymbolDef): """Symbols for each field that a TemplateUnit can have.""" template_id = "template-id" + template_summary = "template-summary" + template_description = "template-description" template_unit = 'template-unit' template_resource = 'template-resource' template_filter = 'template-filter' @@ -507,6 +546,23 @@ class fields(SymbolDef): message=_("identifier cannot define a custom namespace"), onlyif=lambda unit: unit.get_record_value("template-id")), ], + fields.template_summary: [ + concrete_validators.translatable, + PresentFieldValidator(severity=Severity.advice), + CorrectFieldValueValidator( + lambda field: field.count("\n") == 0, + Problem.wrong, Severity.warning, + message=_("please use only one line"), + onlyif=lambda unit: unit.template_summary), + CorrectFieldValueValidator( + lambda field: len(field) <= 80, + Problem.wrong, Severity.warning, + message=_("please stay under 80 characters"), + onlyif=lambda unit: unit.template_summary) + ], + fields.template_description: [ + concrete_validators.translatable, + ], fields.template_unit: [ concrete_validators.untranslatable, ], From 83904fa2e1f21af29703443e1a4d0a3f32ce1674 Mon Sep 17 00:00:00 2001 From: Pierre Equoy Date: Tue, 13 Feb 2024 12:38:13 +0800 Subject: [PATCH 2/4] Add unit tests for the new Template Unit fields --- .../plainbox/impl/unit/test_template.py | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/checkbox-ng/plainbox/impl/unit/test_template.py b/checkbox-ng/plainbox/impl/unit/test_template.py index 180ddb2708..4473794a19 100644 --- a/checkbox-ng/plainbox/impl/unit/test_template.py +++ b/checkbox-ng/plainbox/impl/unit/test_template.py @@ -223,6 +223,30 @@ def test_template_id__precedence_jinja2(self): "id": "job_id_{{ param }}", }).template_id, "template_id") + def test_template_summary(self): + self.assertEqual(TemplateUnit({ + "template-summary": "summary", + }).template_summary, "summary") + + def test_template_description(self): + self.assertEqual(TemplateUnit({ + "template-description": "description", + }).template_description, "description") + + def test_tr_template_summary(self): + """Ensure template_summary is populated with the translated field.""" + self.assertEqual(TemplateUnit({ + "_template-summary": "summary", + }).template_summary, "summary") + + def test_tr_template_description(self): + """ + Ensure template_description is populated with the translated field. + """ + self.assertEqual(TemplateUnit({ + "_template-description": "description", + }).template_description, "description") + def test_template_resource__empty(self): self.assertEqual(TemplateUnit({}).template_resource, None) @@ -496,6 +520,50 @@ def test_template_unit__untranslatable(self): issue_list, self.unit_cls.Meta.fields.template_unit, Problem.unexpected_i18n, Severity.warning) + def test_template_summary__translatable(self): + issue_list = self.unit_cls({ + 'template-summary': 'template_summary' + }, provider=self.provider).check() + self.assertIssueFound(issue_list, + self.unit_cls.Meta.fields.template_summary, + Problem.expected_i18n, + Severity.warning) + + def test_template_summary__present(self): + issue_list = self.unit_cls({ + }, provider=self.provider).check() + self.assertIssueFound(issue_list, + self.unit_cls.Meta.fields.template_summary, + Problem.missing, + Severity.advice) + + def test_template_summary__one_line(self): + issue_list = self.unit_cls({ + 'template-summary': 'line1\nline2' + }, provider=self.provider).check() + self.assertIssueFound(issue_list, + self.unit_cls.Meta.fields.template_summary, + Problem.wrong, + Severity.warning) + + def test_template_summary__short_line(self): + issue_list = self.unit_cls({ + 'template-summary': 'x' * 81 + }, provider=self.provider).check() + self.assertIssueFound(issue_list, + self.unit_cls.Meta.fields.template_summary, + Problem.wrong, + Severity.warning) + + def test_template_description__translatable(self): + issue_list = self.unit_cls({ + 'template-description': 'template_description' + }, provider=self.provider).check() + self.assertIssueFound(issue_list, + self.unit_cls.Meta.fields.template_description, + Problem.expected_i18n, + Severity.warning) + def test_template_resource__untranslatable(self): issue_list = self.unit_cls({ '_template-resource': 'template_resource' From f2dc015685f218e586540979595ea764e516a4b5 Mon Sep 17 00:00:00 2001 From: Pierre Equoy Date: Tue, 13 Feb 2024 12:50:36 +0800 Subject: [PATCH 3/4] Update Template Unit documentation --- docs/reference/units/template.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/reference/units/template.rst b/docs/reference/units/template.rst index eeb013defc..109e99f088 100644 --- a/docs/reference/units/template.rst +++ b/docs/reference/units/template.rst @@ -41,6 +41,24 @@ Template-Specific Fields ``stress/reboot_{iterations}_times``, the computed ``template-id`` field will be ``stress/reboot_iterations_times``. +.. _Template template-summary field: + +``template-summary`` + A human readable name for the template. This value is available for + translation into other languages. It must be one line long, ideally it + should be short (50-70 characters max). + + This field is optional (Checkbox will only advise you to provide one when + running provider validation). + +.. _Template template-description field: + +``template-description`` + A long form description of what the template does or the kind of jobs it + instantiates. This value is available for translation into other languages. + + This field is optional. + .. _Template template-unit field: ``template-unit`` From 989c0f68d31d22568d365ccdb8b7b8d5f9fae297 Mon Sep 17 00:00:00 2001 From: Pierre Equoy Date: Tue, 13 Feb 2024 13:52:19 +0800 Subject: [PATCH 4/4] Add unit tests for the translation methods of the new fields --- checkbox-ng/plainbox/impl/unit/test_template.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/checkbox-ng/plainbox/impl/unit/test_template.py b/checkbox-ng/plainbox/impl/unit/test_template.py index 4473794a19..ead808f35d 100644 --- a/checkbox-ng/plainbox/impl/unit/test_template.py +++ b/checkbox-ng/plainbox/impl/unit/test_template.py @@ -234,12 +234,24 @@ def test_template_description(self): }).template_description, "description") def test_tr_template_summary(self): + template = TemplateUnit({ + "_template-summary": "summary", + }) + self.assertEqual(template.tr_template_summary(), "summary") + + def test_translated_template_summary(self): """Ensure template_summary is populated with the translated field.""" self.assertEqual(TemplateUnit({ "_template-summary": "summary", }).template_summary, "summary") def test_tr_template_description(self): + template = TemplateUnit({ + "_template-description": "description", + }) + self.assertEqual(template.tr_template_description(), "description") + + def test_translated_template_description(self): """ Ensure template_description is populated with the translated field. """