class Severity(SymbolDef, allow_outer={"N_"}): """ Symbols for class:`Issue` severity """ error = N_('error') warning = N_('warning') advice = N_('advice')
class Meta: name = N_('unit-with-id') class fields(SymbolDef): id = 'id' validator_cls = UnitWithIdValidator field_validators = { fields.id: [ # We don't want anyone marking id up for translation UntranslatableFieldValidator, # We want this field to be present at all times PresentFieldValidator, # We want each instance to have a different identifier TemplateVariantFieldValidator, # When checking in a globally, all units need an unique value UniqueValueValidator, # We want to have bare, namespace-less identifiers CorrectFieldValueValidator( lambda value, unit: ( "::" not in unit.get_record_value('id')), message=_("identifier cannot define a custom namespace"), onlyif=lambda unit: unit.get_record_value('id')), ] }
class Meta: name = N_('file') validator_cls = FileUnitValidator class fields(SymbolDef): """ Symbols for each field that a FileUnit can have """ path = 'path' role = 'role' base = 'base' field_validators = { fields.path: [ CorrectFieldValueValidator( lambda value: os.path.splitext(value)[1] == '.pxu', Problem.deprecated, Severity.advice, onlyif=lambda unit: unit.role == FileRole.unit_source, message=_( "please use .pxu as an extension for all" " files with plainbox units, see: {}").format( 'http://plainbox.readthedocs.org/en/latest/author/' 'faq.html#faq-1')), ], fields.role: [MemberOfFieldValidator(FileRole.get_all_symbols())] }
class Meta: name = N_('category') class fields(SymbolDef): """ Symbols for each field that a JobDefinition can have """ name = 'name' field_validators = { fields.name: [ TranslatableFieldValidator, TemplateVariantFieldValidator, PresentFieldValidator, # We want the name to be a single line CorrectFieldValueValidator( lambda name: name.count("\n") == 0, Problem.wrong, Severity.warning, message=_("please use only one line"), onlyif=lambda unit: unit.name is not None), # We want the name to be relatively short CorrectFieldValueValidator( lambda name: len(name) <= 80, Problem.wrong, Severity.warning, message=_("please stay under 80 characters"), onlyif=lambda unit: unit.name is not None), ] }
def get_stubbox_def(): """ Get a Provider1Definition for stubbox """ stubbox_def = Provider1Definition() stubbox_def.name = "com.canonical.plainbox:stubbox" stubbox_def.version = "1.0" stubbox_def.description = N_("StubBox (dummy data for development)") stubbox_def.secure = False stubbox_def.gettext_domain = "plainbox-provider-stubbox" stubbox_def.location = os.path.join( get_plainbox_dir(), "impl/providers/stubbox") return stubbox_def
def get_categories_def(): """ Get a Provider1Definition for the provider that knows all the categories """ categories_def = Provider1Definition() categories_def.name = "com.canonical.plainbox:categories" categories_def.version = "1.0" categories_def.description = N_("Common test category definitions") categories_def.secure = False categories_def.gettext_domain = "plainbox-provider-categories" categories_def.location = os.path.join( get_plainbox_dir(), "impl/providers/categories") return categories_def
def get_manifest_def(): """ Get a Provider1Definition for the provider that handles the manifest machinery. """ manifest_def = Provider1Definition() manifest_def.name = "com.canonical.plainbox:manifest" manifest_def.version = "1.0" manifest_def.description = N_("Hardware Manifest Provider") manifest_def.secure = False manifest_def.gettext_domain = "plainbox-provider-manifest" manifest_def.location = os.path.join( get_plainbox_dir(), "impl/providers/manifest") return manifest_def
def get_exporters_def(): """ Get a Provider1Definition for the provider that handles the exporters machinery. """ exporters_def = Provider1Definition() exporters_def.name = "com.canonical.plainbox:exporters" exporters_def.version = "1.0" exporters_def.description = N_("Exporters Provider") exporters_def.secure = False exporters_def.gettext_domain = "plainbox-provider-exporters" exporters_def.location = os.path.join( get_plainbox_dir(), "impl/providers/exporters") return exporters_def
class Meta: name = N_('file') validator_cls = FileUnitValidator class fields(SymbolDef): """ Symbols for each field that a FileUnit can have """ path = 'path' role = 'role' base = 'base' field_validators = { fields.role: [MemberOfFieldValidator(FileRole.get_all_symbols())] }
class Meta: name = N_('category') class fields(SymbolDef): """ Symbols for each field that a JobDefinition can have """ name = 'name' field_validators = { fields.name: [ concrete_validators.translatable, concrete_validators.templateVariant, concrete_validators.present, concrete_validators.oneLine, concrete_validators.shortValue, ] }
class Meta: name = N_('unit-with-id') class fields(SymbolDef): id = 'id' validator_cls = UnitWithIdValidator field_validators = { fields.id: [ concrete_validators.untranslatable, concrete_validators.present, concrete_validators.templateVariant, UniqueValueValidator(), # We want to have bare, namespace-less identifiers CorrectFieldValueValidator( lambda value, unit: ("::" not in unit.get_record_value('id')), message=_("identifier cannot define a custom namespace"), onlyif=lambda unit: unit.get_record_value('id')), ] }
from plainbox.i18n import gettext_noop as N_ from plainbox.impl.applogic import get_all_exporter_names from plainbox.impl.commands import PlainBoxCommand @docstring( N_(""" session management commands This command can be used to list, show and remove sessions owned by the current user. @EPILOG@ Each session has a small amount of meta-data that is available for inspection. Each session has an application identifier (set by the application that created that session), a title, that is human readable piece of text that helps to distinguish sessions, and a set of flags. Flags are particularly useful for determining what is the overall state of any particular session. Two flags are standardized (other flags can be used by applications): incomplete and submitted. The 'incomplete' flag is removed after all desired jobs have been executed. The 'submitted' flag is set after a submission is made using any of the transport mechanisms. """)) class SessionCommand(PlainBoxCommand): def __init__(self, provider_loader): super().__init__() self.provider_loader = provider_loader def invoked(self, ns):
class Meta: name = N_('job') class fields(SymbolDef): """ Symbols for each field that a JobDefinition can have """ name = 'name' summary = 'summary' plugin = 'plugin' command = 'command' description = 'description' user = '******' environ = 'environ' estimated_duration = 'estimated_duration' depends = 'depends' after = 'after' salvages = 'salvages' requires = 'requires' shell = 'shell' imports = 'imports' flags = 'flags' category_id = 'category_id' purpose = 'purpose' steps = 'steps' verification = 'verification' certification_status = 'certification_status' siblings = 'siblings' auto_retry = 'auto_retry' field_validators = { fields.name: [ concrete_validators.untranslatable, concrete_validators.templateVariant, DeprecatedFieldValidator( _("use 'id' and 'summary' instead of 'name'")), ], # NOTE: 'id' validators are "inherited" so we don't have it here fields.summary: [ concrete_validators.translatable, concrete_validators.templateVariant, PresentFieldValidator(severity=Severity.advice), concrete_validators.oneLine, concrete_validators.shortValue, ], fields.plugin: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, concrete_validators.present, MemberOfFieldValidator(_PluginValues.get_all_symbols()), CorrectFieldValueValidator( lambda plugin: plugin != 'user-verify', Problem.deprecated, Severity.advice, message=_("please migrate to user-interact-verify")), ], fields.command: [ concrete_validators.untranslatable, # All jobs except for manual must have a command PresentFieldValidator( message=_("command is mandatory for non-manual jobs"), onlyif=lambda unit: unit.plugin != 'manual'), # Manual jobs cannot have a command UselessFieldValidator( message=_("command on a manual job makes no sense"), onlyif=lambda unit: unit.plugin == 'manual'), # We don't want to refer to CHECKBOX_SHARE anymore CorrectFieldValueValidator( lambda command: "CHECKBOX_SHARE" not in command, Problem.deprecated, Severity.advice, message=_("please use PLAINBOX_PROVIDER_DATA" " instead of CHECKBOX_SHARE"), onlyif=lambda unit: unit.command is not None), # We don't want to refer to CHECKBOX_DATA anymore CorrectFieldValueValidator( lambda command: "CHECKBOX_DATA" not in command, Problem.deprecated, Severity.advice, message=_("please use PLAINBOX_SESSION_SHARE" " instead of CHECKBOX_DATA"), onlyif=lambda unit: unit.command is not None), # We want to catch silly mistakes that shlex can detect ShellProgramValidator(), ], fields.description: [ concrete_validators.translatable, concrete_validators.templateVariant, # Description is mandatory for manual jobs PresentFieldValidator( message=_("manual jobs must have a description field, or a" " set of purpose, steps, and verification " "fields"), onlyif=lambda unit: unit.plugin == 'manual' and unit. purpose is None and unit.steps is None and unit. verification is None), # Description or a set of purpose, steps and verification # fields is recommended for all other jobs ], fields.purpose: [ concrete_validators.translatable, ], fields.steps: [ concrete_validators.translatable, ], fields.verification: [ concrete_validators.translatable, ], fields.user: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, # User should be either None or 'root' CorrectFieldValueValidator( message=_("user can only be 'root'"), correct_fn=lambda user: user in (None, 'root')), # User is useless without a command to run UselessFieldValidator( message=_("user without a command makes no sense"), onlyif=lambda unit: unit.command is None) ], fields.environ: [ concrete_validators.untranslatable, # Environ is useless without a command to run UselessFieldValidator( message=_("environ without a command makes no sense"), onlyif=lambda unit: unit.command is None), ], fields.estimated_duration: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, CorrectFieldValueValidator( lambda duration: float(duration) > 0, message="value must be a positive number", onlyif=lambda unit: (unit.get_record_value('estimated_duration'))), ], fields.depends: [ concrete_validators.untranslatable, CorrectFieldValueValidator(lambda value, unit: ( unit.get_direct_dependencies() is not None)), UnitReferenceValidator( lambda unit: unit.get_direct_dependencies(), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job")) ]) # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], fields.after: [ concrete_validators.untranslatable, CorrectFieldValueValidator(lambda value, unit: ( unit.get_after_dependencies() is not None)), UnitReferenceValidator( lambda unit: unit.get_after_dependencies(), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job")) ]) ], fields.requires: [ concrete_validators.untranslatable, CorrectFieldValueValidator( lambda value, unit: unit.get_resource_program(), onlyif=lambda unit: unit.requires is not None), UnitReferenceValidator( lambda unit: unit.get_resource_dependencies(), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job")), ReferenceConstraint( lambda referrer, referee: (referee.plugin == 'resource'), onlyif=lambda referrer, referee: (referee.unit == 'job'), message=_( "the referenced job is not a resource job")), ]), # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], fields.shell: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, # Shell should be only '/bin/sh', or None (which gives bash) MemberOfFieldValidator( ['/bin/sh', '/bin/bash', 'bash'], message=_("only /bin/sh and /bin/bash are allowed")), ], fields.imports: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, CorrectFieldValueValidator(lambda value, unit: (list( unit.get_imported_jobs()) is not None)), UnitReferenceValidator( lambda unit: [ job_id for job_id, identifier in unit.get_imported_jobs() ], constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job")) ]), # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], fields.category_id: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, UnitReferenceValidator( lambda unit: ([unit.get_category_id()] if unit.category_id else ()), constraints=[ ReferenceConstraint( lambda referrer, referee: (referee.unit == 'category'), message=_("the referenced unit is not a category")) ]), # TODO: should not refer to deprecated categories, # onlyif job itself is not deprecated ], fields.flags: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, ], fields.certification_status: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, MemberOfFieldValidator( _CertificationStatusValues.get_all_symbols()), ], fields.siblings: [ concrete_validators.translatable, CorrectFieldValueValidator( lambda value, unit: json.loads(value), Problem.syntax_error, Severity.error, onlyif=lambda unit: unit.siblings), CorrectFieldValueValidator( lambda value, unit: type(json.loads(value)) is list, Problem.syntax_error, Severity.error, onlyif=lambda unit: unit.siblings), CorrectFieldValueValidator(lambda value, unit: all( [type(s) is dict for s in json.loads(value)]), Problem.syntax_error, Severity.error, onlyif=lambda unit: unit.siblings), CorrectFieldValueValidator( lambda value, unit: all([ all([ hasattr(JobDefinition, k.lstrip('_')) for k in s.keys() ]) for s in json.loads(value) ]), Problem.bad_reference, Severity.error, message=_('unknown override job field'), onlyif=lambda unit: unit.siblings), ], fields.auto_retry: [ concrete_validators.untranslatable, concrete_validators.templateInvariant, MemberOfFieldValidator(_AutoRetryValues.get_all_symbols()), ], }
_("Successfully sent, server response" ": {0}").format(result)) @docstring( # TRANSLATORS: please leave various options (both long and short forms), # environment variables and paths in their original form. Also keep the # special @EPILOG@ string. The first line of the translation is special and # is used as the help message. Please keep the pseudo-statement form and # don't finish the sentence with a dot. Pay extra attention to whitespace. # It must be correctly preserved or the result won't work. In particular # the leading whitespace *must* be preserved and *must* have the same # length on each line. N_(""" submit test results to the Canonical certification website This command sends the XML results file to the Certification website. """)) class SubmitCommand(PlainBoxCommand): gettext_domain = "checkbox-ng" def __init__(self, config_loader): self.config = config_loader() def invoked(self, ns): return SubmitInvocation(ns).run() def register_parser(self, subparsers): parser = subparsers.add_parser( "submit",
# special @EPILOG@ string. The first line of the translation is special and # is used as the help message. Please keep the pseudo-statement form and # don't finish the sentence with a dot. Pay extra attention to whitespace. # It must be correctly preserved or the result won't work. In particular # the leading whitespace *must* be preserved and *must* have the same # length on each line. N_(""" create a new provider (directory) Creates a new provider from a built-in skeleton. @EPILOG@ The name of the provider must follow the pattern ``YYYY.example.org:name`` where ``YYYY`` is a four-digit year when the author of the provider owned the domain (here, ``example.org``) and ``name`` is arbitrary identifier that is managed by the owner of that domain. The identifier should be constrained to ASCII, digits and the dash character. This naming scheme allows anyone that ever owned a domain name to come up with non-clashing provider identifiers. Those identifiers are going to be used in fully qualified names of various objects. This command creates a new skeleton test provider for PlainBox. The generated content should be edited to fit a particular purpose. """)) class StartProviderCommand(PlainBoxCommand): def invoked(self, ns): return StartProviderInvocation(ns.name).run() def register_parser(self, subparsers):
# the leading whitespace *must* be preserved and *must* have the same # length on each line. N_(""" run qml job in standalone shell Runs specified file as it would be a plainbox' qml job. Returns 0 if job returned 'pass', 1 if job returned 'fail', or other value in case of an error. @EPILOG@ General purpose of this command is to make development of qml-native jobs faster, by making it easier to test qml file(s) that constitute to job without resorting to installation of provider and running plainbox run. Typical approach to the development of new qml job would be as follows: - have an idea for a job - create a qml file in Ubuntu-SDK or Your Favourite Editor - hack on the file and iterate using qmlscene (or use plainbox-qml-shell immediately if you start with next point) - make it conformant to plainbox qml-native API described in CEP-5 (calling test-done at the end) - copy qml file over to data dir of a provider and add a job unit to it """)) class QmlShellCommand(PlainBoxCommand): def register_parser(self, subparsers):
class Meta: name = N_('template') class fields(SymbolDef): """Symbols for each field that a TemplateUnit can have.""" template_unit = 'template-unit' template_resource = 'template-resource' template_filter = 'template-filter' template_imports = 'template-imports' validator_cls = TemplateUnitValidator field_validators = { fields.template_unit: [ concrete_validators.untranslatable, CorrectFieldValueValidator( lambda value, unit: (unit.get_record_value('template-unit') is not None), Problem.missing, Severity.advice, message=_("template should explicitly define instantiated" " unit type")), ], fields.template_resource: [ concrete_validators.untranslatable, concrete_validators.present, UnitReferenceValidator( lambda unit: ([unit.resource_id] if unit.resource_id else []), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job")), ReferenceConstraint( lambda referrer, referee: (referee.plugin == 'resource'), onlyif=lambda referrer, referee: (referee.unit == 'job'), message=_( "the referenced job is not a resource job")), ]), # TODO: should not refer to deprecated job, # onlyif job itself is not deprecated ], fields.template_filter: [ concrete_validators.untranslatable, # All templates need a valid (or empty) template filter CorrectFieldValueValidator( lambda value, unit: unit.get_filter_program(), onlyif=lambda unit: unit.template_filter is not None), # TODO: must refer to the same job as template-resource ], fields.template_imports: [ concrete_validators.untranslatable, CorrectFieldValueValidator(lambda value, unit: (list( unit.get_imported_jobs()) is not None)), CorrectFieldValueValidator( lambda value, unit: (len(list(unit.get_imported_jobs())) in (0, 1)), message=_("at most one import statement is allowed")), # TODO: must refer to known or possibly-known job # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], }
This module contains the user interface parts of the 'plainbox device' command. """ from logging import getLogger from plainbox.i18n import docstring from plainbox.i18n import gettext_noop as N_ from plainbox.impl.commands import PlainBoxCommand logger = getLogger("plainbox.commands.device") @docstring( N_(""" device management commands This command can be used to show the device that plainbox is executing @EPILOG@ TBD """)) class DeviceCommand(PlainBoxCommand): def invoked(self, ns): from plainbox.impl.commands.inv_device import DeviceInvocation return DeviceInvocation(ns).run() def register_parser(self, subparsers): parser = self.add_subcommand(subparsers) parser.prog = 'plainbox device'
class Meta: name = N_('job') class fields(SymbolDef): """ Symbols for each field that a JobDefinition can have """ name = 'name' summary = 'summary' plugin = 'plugin' command = 'command' description = 'description' user = '******' environ = 'environ' estimated_duration = 'estimated_duration' depends = 'depends' after = 'after' requires = 'requires' shell = 'shell' imports = 'imports' flags = 'flags' category_id = 'category_id' purpose = 'purpose' steps = 'steps' verification = 'verification' qml_file = 'qml_file' certification_status = 'certification_status' field_validators = { fields.name: [ UntranslatableFieldValidator, TemplateVariantFieldValidator, DeprecatedFieldValidator( _("use 'id' and 'summary' instead of 'name'")), ], # NOTE: 'id' validators are "inherited" so we don't have it here fields.summary: [ TranslatableFieldValidator, TemplateVariantFieldValidator, PresentFieldValidator(severity=Severity.advice), # We want the summary to be a single line CorrectFieldValueValidator( lambda summary: summary.count("\n") == 0, Problem.wrong, Severity.warning, message=_("please use only one line"), onlyif=lambda unit: unit.summary is not None), # We want the summary to be relatively short CorrectFieldValueValidator( lambda summary: len(summary) <= 80, Problem.wrong, Severity.warning, message=_("please stay under 80 characters"), onlyif=lambda unit: unit.summary is not None), ], fields.plugin: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, PresentFieldValidator, CorrectFieldValueValidator( lambda plugin: ( plugin in JobDefinition.plugin.get_all_symbols()), message=_('valid values are: {}').format( ', '.join(str(sym) for sym in sorted( _PluginValues.get_all_symbols())))), CorrectFieldValueValidator( lambda plugin: plugin != 'local', Problem.deprecated, Severity.advice, message=_("please migrate to job templates, " "see plainbox-template-unit(7) for details")), CorrectFieldValueValidator( lambda plugin: plugin != 'user-verify', Problem.deprecated, Severity.advice, message=_("please migrate to user-interact-verify")), ], fields.command: [ UntranslatableFieldValidator, # All jobs except for manual must have a command PresentFieldValidator( message=_("command is mandatory for non-manual jobs"), onlyif=lambda unit: unit.plugin not in ('manual', 'qml')), # Manual jobs cannot have a command UselessFieldValidator( message=_("command on a manual or qml job makes no sense"), onlyif=lambda unit: unit.plugin in ('manual', 'qml')), # We don't want to refer to CHECKBOX_SHARE anymore CorrectFieldValueValidator( lambda command: "CHECKBOX_SHARE" not in command, Problem.deprecated, Severity.advice, message=_("please use PLAINBOX_PROVIDER_DATA" " instead of CHECKBOX_SHARE"), onlyif=lambda unit: unit.command is not None), # We don't want to refer to CHECKBOX_DATA anymore CorrectFieldValueValidator( lambda command: "CHECKBOX_DATA" not in command, Problem.deprecated, Severity.advice, message=_("please use PLAINBOX_SESSION_SHARE" " instead of CHECKBOX_DATA"), onlyif=lambda unit: unit.command is not None), # We want to catch silly mistakes that shlex can detect ShellProgramValidator, ], fields.description: [ TranslatableFieldValidator, TemplateVariantFieldValidator, # Description is mandatory for manual jobs PresentFieldValidator( message=_("manual jobs must have a description field, or a" " set of purpose, steps, and verification " "fields"), onlyif=lambda unit: unit.plugin == 'manual' and unit.purpose is None and unit.steps is None and unit.verification is None ), # Description or a set of purpose, steps and verification # fields is recommended for all other jobs PresentFieldValidator( severity=Severity.advice, message=_("all jobs should have a description field, or a " "set of purpose, steps and verification fields"), onlyif=lambda unit: ( 'simple' not in unit.get_flag_set() and unit.plugin != 'manual' and ( unit.purpose is None and unit.steps is None and unit.verification is None))), ], fields.purpose: [ TranslatableFieldValidator, PresentFieldValidator( severity=Severity.advice, message=("please use purpose, steps, and verification" " fields. See http://plainbox.readthedocs.org" "/en/latest/author/faq.html#faq-2"), onlyif=lambda unit: unit.startup_user_interaction_required and unit.get_record_value('summary') is None), ], fields.steps: [ TranslatableFieldValidator, PresentFieldValidator( severity=Severity.advice, message=("please use purpose, steps, and verification" " fields. See http://plainbox.readthedocs.org" "/en/latest/author/faq.html#faq-2"), onlyif=lambda unit: unit.startup_user_interaction_required), ], fields.verification: [ TranslatableFieldValidator, PresentFieldValidator( severity=Severity.advice, message=("please use purpose, steps, and verification" " fields. See http://plainbox.readthedocs.org" "/en/latest/author/faq.html#faq-2"), onlyif=lambda unit: unit.plugin in ( 'manual', 'user-verify', 'user-interact-verify')), ], fields.user: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, # User should be either None or 'root' CorrectFieldValueValidator( message=_("user can only be 'root'"), correct_fn=lambda user: user in (None, 'root')), # User is useless without a command to run UselessFieldValidator( message=_("user without a command makes no sense"), onlyif=lambda unit: unit.command is None) ], fields.environ: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, # Environ is useless without a command to run UselessFieldValidator( message=_("environ without a command makes no sense"), onlyif=lambda unit: unit.command is None), ], fields.estimated_duration: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, PresentFieldValidator( severity=Severity.advice, onlyif=lambda unit: 'simple' not in unit.get_flag_set() ), CorrectFieldValueValidator( lambda duration: float(duration) > 0, message="value must be a positive number", onlyif=lambda unit: ( unit.get_record_value('estimated_duration'))), ], fields.depends: [ UntranslatableFieldValidator, CorrectFieldValueValidator( lambda value, unit: ( unit.get_direct_dependencies() is not None)), UnitReferenceValidator( lambda unit: unit.get_direct_dependencies(), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job"))]) # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], fields.after: [ UntranslatableFieldValidator, CorrectFieldValueValidator( lambda value, unit: ( unit.get_after_dependencies() is not None)), UnitReferenceValidator( lambda unit: unit.get_after_dependencies(), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job"))]) ], fields.requires: [ UntranslatableFieldValidator, CorrectFieldValueValidator( lambda value, unit: unit.get_resource_program(), onlyif=lambda unit: unit.requires is not None), UnitReferenceValidator( lambda unit: unit.get_resource_dependencies(), constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job")), ReferenceConstraint( lambda referrer, referee: ( referee.plugin == 'resource'), onlyif=lambda referrer, referee: ( referee.unit == 'job'), message=_( "the referenced job is not a resource job")), ]), # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], fields.shell: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, # Shell should be only '/bin/sh', or None (which gives bash) CorrectFieldValueValidator( lambda shell: shell in ('/bin/sh', '/bin/bash', 'bash'), message=_("only /bin/sh and /bin/bash are allowed")), ], fields.imports: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, CorrectFieldValueValidator( lambda value, unit: ( list(unit.get_imported_jobs()) is not None)), UnitReferenceValidator( lambda unit: [ job_id for job_id, identifier in unit.get_imported_jobs()], constraints=[ ReferenceConstraint( lambda referrer, referee: referee.unit == 'job', message=_("the referenced unit is not a job"))]), # TODO: should not refer to deprecated jobs, # onlyif job itself is not deprecated ], fields.category_id: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, UnitReferenceValidator( lambda unit: ( [unit.get_category_id()] if unit.category_id else ()), constraints=[ ReferenceConstraint( lambda referrer, referee: ( referee.unit == 'category'), message=_( "the referenced unit is not a category"))]), # TODO: should not refer to deprecated categories, # onlyif job itself is not deprecated ], fields.flags: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, CorrectFieldValueValidator( lambda value, unit: ( 'simple' in unit.get_flag_set() or 'preserve-locale' in unit.get_flag_set()), Problem.expected_i18n, Severity.advice, message=_( 'please ensure that the command supports' ' non-C locale then set the preserve-locale flag' ), onlyif=lambda unit: unit.command), CorrectFieldValueValidator( lambda value, unit: ( not ('explicit-fail' in unit.get_flag_set() and unit.plugin in { 'shell', 'user-interact', 'attachment', 'local', 'resource'})), Problem.useless, Severity.advice, message=_('explicit-fail makes no sense for job which ' 'outcome is automatically determined.') ), # The has-leftovers flag is useless without a command CorrectFieldValueValidator( lambda value, unit: ( 'has-leftovers' not in unit.get_flag_set()), Problem.useless, Severity.advice, message=_( 'has-leftovers makes no sense without a command' ), onlyif=lambda unit: unit.command is None), ], fields.qml_file: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, PresentFieldValidator( onlyif=lambda unit: unit.plugin == 'qml'), CorrectFieldValueValidator( lambda value: value.endswith('.qml'), Problem.wrong, Severity.advice, message=_('use the .qml extension for all QML files'), onlyif=lambda unit: (unit.plugin == 'qml' and unit.qml_file)), CorrectFieldValueValidator( lambda value, unit: os.path.isfile(unit.qml_file), message=_('please point to an existing QML file'), onlyif=lambda unit: (unit.plugin == 'qml' and unit.qml_file)), ], fields.certification_status: [ UntranslatableFieldValidator, TemplateInvariantFieldValidator, CorrectFieldValueValidator( lambda certification_status: ( certification_status in _CertificationStatusValues.get_all_symbols()), message=_('valid values are: {}').format( ', '.join(str(sym) for sym in sorted( _CertificationStatusValues.get_all_symbols())))), ], }
N_(""" install this provider in the system This command installs the provider to the specified prefix. @EPILOG@ Installation Layouts ==================== There are two possible installation layouts: flat, perfect for keeping the whole provider in one directory, and unix, which is optimized for packaging and respecting the filesystem hierarchy. In both cases, a generated file is created at a fixed location: {prefix}/share/plainbox-providers-1/{provider.name}.provider This file is essential for plainbox to discover providers. It contains meta-data collected from the manage.py setup() call. For Packaging ------------- System-wide installations should typically use `--prefix=/usr` coupled with `--layout=unix`. For packaging you will want to use the `--root=` argument to place all of the copied and generated files into your packaging system staging area. This will not affect generated content, which only respects the prefix argument. UNIX Layout ----------- In the unix layout, following transformation is applied: @LAYOUT[unix]@ Flat Layout ----------- @LAYOUT[flat]@ """))