Example #1
0
 def test_multiple(self):
   superclasses_of_a_or_b = SuperclassesOf(self.A, self.B)
   self.assertEqual((self.A, self.B), superclasses_of_a_or_b.types)
   self.assertTrue(superclasses_of_a_or_b.satisfied_by(self.A()))
   self.assertTrue(superclasses_of_a_or_b.satisfied_by(self.B()))
   self.assertFalse(superclasses_of_a_or_b.satisfied_by(self.BPrime()))
   self.assertFalse(superclasses_of_a_or_b.satisfied_by(self.C()))
Example #2
0
 def test_single(self):
   superclasses_of_b = SuperclassesOf(self.B)
   self.assertEqual((self.B,), superclasses_of_b.types)
   self.assertTrue(superclasses_of_b.satisfied_by(self.A()))
   self.assertTrue(superclasses_of_b.satisfied_by(self.B()))
   self.assertFalse(superclasses_of_b.satisfied_by(self.BPrime()))
   self.assertFalse(superclasses_of_b.satisfied_by(self.C()))
Example #3
0
 def test_multiple(self):
     superclasses_of_a_or_b = SuperclassesOf(self.A, self.B)
     self.assertEqual((self.A, self.B), superclasses_of_a_or_b.types)
     self.assertTrue(superclasses_of_a_or_b.satisfied_by(self.A()))
     self.assertTrue(superclasses_of_a_or_b.satisfied_by(self.B()))
     self.assertFalse(superclasses_of_a_or_b.satisfied_by(self.BPrime()))
     self.assertFalse(superclasses_of_a_or_b.satisfied_by(self.C()))
Example #4
0
 def test_single(self):
     superclasses_of_b = SuperclassesOf(self.B)
     self.assertEqual((self.B, ), superclasses_of_b.types)
     self.assertTrue(superclasses_of_b.satisfied_by(self.A()))
     self.assertTrue(superclasses_of_b.satisfied_by(self.B()))
     self.assertFalse(superclasses_of_b.satisfied_by(self.BPrime()))
     self.assertFalse(superclasses_of_b.satisfied_by(self.C()))
Example #5
0
    def __init__(self, abstract=False, extends=None, merges=None, **kwargs):
        """Creates a new configuration data blob.

    By default configurations are anonymous (un-named), concrete (not `abstract`), and they neither
    inherit nor merge another configuration.

    Inheritance is only allowed via one of the `extends` or `merges` channels, it is an error to
    specify both.  A configuration can be semantically abstract without setting `abstract=True`.
    The `abstract` value can serve as documentation, or, for subclasses that provide an
    implementation for `validate_concrete`, it allows skipping validation for abstract instances.

    :param bool abstract: `True` to mark this configuration item as abstract, in which case no
                          validation is performed (see `validate_concrete`); `False` by default.
    :param extends: The configuration instance to inherit field values from.  Any shared fields are
                    over-written with this instances values.
    :type extends: An addressed or concrete configuration instance that is a type compatible with
                   this configuration or this configurations superclasses.
    :param merges: The configuration instance to merge this instances field values with.  Merging is
                   like extension except for containers, which are extended instead of replaced; ie:
                   any `dict` values are updated with this instances items and any `list` values are
                   extended with this instances items.
    :type merges: An addressed or concrete configuration instance that is a type compatible with
                  this configuration or this configurations superclasses.
    :param **kwargs: The configuration parameters.
    """
        self._kwargs = kwargs

        self._kwargs['abstract'] = abstract

        # It only makes sense to inherit a subset of our own fields (we should not inherit new fields!),
        # our superclasses logically provide fields within this constrained set.
        # NB: Since Configuration is at base an ~unconstrained struct, a superclass does allow for
        # arbitrary and thus more fields to be defined than a subclass might logically support.  We
        # accept this hole in a trade for generally expected behavior when Configuration is subclassed
        # in the style of constructors with named parameters representing the full complete set of
        # expected parameters leaving **kwargs only for use by 'the system'; ie for `typename` and
        # `address` plumbing for example.
        self._kwargs['extends'] = addressable(SuperclassesOf(type(self)),
                                              extends)
        self._kwargs['merges'] = addressable(SuperclassesOf(type(self)),
                                             merges)

        # Allow for configuration items that are directly constructed in memory.  These can have an
        # address directly assigned (vs. inferred from name + source file location) and we only require
        # that if they do, their name - if also assigned, matches the address.
        if self.address:
            if self.name and self.name != self.address.target_name:
                self.report_validation_error(
                    'Address and name do not match! address: {}, name: {}'.
                    format(self.address, self.name))
            self._kwargs['name'] = self.address.target_name

        self._hashable_key = None
Example #6
0
 def test(self):
     self.assertTrue(SuperclassesOf(self.B).satisfied_by(self.A()))
     self.assertTrue(SuperclassesOf(self.B).satisfied_by(self.B()))
     self.assertFalse(SuperclassesOf(self.B).satisfied_by(self.BPrime()))
     self.assertFalse(SuperclassesOf(self.B).satisfied_by(self.C()))