plainbox:unit:validators: don't use collections.abc

This patch removes the need for collections.abc that doesn't exist on
python3.2 that we still support.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: silence validate() deprecation warnings in tests

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: correct module docstring

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: add new UnitValidator class

This patch adds the new base unit validator class. Unlike in the past,
the new class should almost never have to be subclassed and extended
as it relies on field validators to do most of the heavy lifting.

The core APIs are the two new methods UnitValidator.check(unit)
and UnitValidator.check_in_context(unit, context) which look at
a particular unit and generate subsequent Issue instances that describe
all of the detected issues.

The check_in_context() method gets an additional UnitValidationContext
instance that allows to perform global analysis. This allows to verify
correctness of units in context of other units (checking that references
are correct, that identifiers are unique, etc).

In addition to the check() methods there are report_issue() family
of methods (including advice(), warning() and error() short-cuts) that
collaborate with the particular field validators to simplify the process
of reporting issues. All of the issues detected by a particular validator
are now collected and exposed as the new `all_issues` attribute.

Lastly there is the new explain() method that collaborates with
report_issue() to provide human-readable strings for various Problem
constants. It may be overridden in other classes to provide more accurate
error messages

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: make UnitValidator.make_field_validators() deterministic

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: fix PEP-8 issue

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: add Unit.is_translatable_field()

This patch adds a method that can be used to check if a given field
in the unit data was marked as translatable or not.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: remove Unit.get_unit_type()

This method is now also avialable via the UnitLegacyAPI so we should not
need a second copy here.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: add Unit.qualify_id()

This patch adds a method that can resolve relative unit identifiers
based on the namespace of the resolving unit's provider reference.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: add Unit.check()

This patch adds a high-level API for checking units for correctness.
It entirely replaces the old validate() method and offers more features
with a simpler interface.

The main difference is that *all* issues related to a unit are reported.
The checker code no longer stops at the first encountered problem.

The method offers two keyword-only arguments: the context argument allows
to perform context-aware checks (global validation) and the live argument
allows to return issues as soon as they are found instead of buffering
them to an intermediate list.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: add IssueMixIn

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: add Unit.Meta meta-data for the new validation code

This patch adds validation meta-data to the base Unit class.
The meta-data consists of three attributes:

    fields: this is a symbol definition class that has a symbol for each
    field that may be present in the unit. It is used by the validation
    stack and by the field_validators attribute.

    validator_cls: this attribute refers to the validator class to use
    for all new-style checks. Here it refers to the UnitValdidator base
        class.

    field_validators: this attribute contains a dictionary mapping from
    each field (from fields symbol def) to a list of validator classes
    that are used to check that particular field.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit: drop default value from Unit.unit

This patch removes the default value of the Unit.unit property. This
allows us to validate the actual value of the unit field.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: fix typo

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: fix partial_id docstring

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: add docstring for the id property

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: fix UnitWithId.id

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: fix logger definition

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: add UnitWithIdValidator

This patch adds a custom validator subclass for UnitWithId. It offers
a better explain() method that can use the partial_id property to
help users understand to which unit each problem is related to

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
plainbox:unit:unit_with_id: add UnitWithId.tr_unit()

This patch adds UnitWithId.tr_unit(). This method should be
implemented by all Unit subclasses so let's just do it even though
we don't expect to see any unit-with-id in the wild.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>