Ejemplo n.º 1
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
Ejemplo n.º 2
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
Ejemplo n.º 3
0
 def __init__(self, default_repo, repos, name=None, **kwargs):
   super(PublishConfiguration, self).__init__(name=name,
                                              default_repo=addressable(Exactly(Configuration),
                                                                       default_repo),
                                              repos=addressable_mapping(Exactly(Configuration),
                                                                        repos),
                                              **kwargs)
Ejemplo n.º 4
0
 def __init__(self, default_repo, repos, name=None, **kwargs):
     super(PublishConfiguration,
           self).__init__(name=name,
                          default_repo=addressable(Exactly(Configuration),
                                                   default_repo),
                          repos=addressable_mapping(Exactly(Configuration),
                                                    repos),
                          **kwargs)
Ejemplo n.º 5
0
    @property
    def path_globs(self):
        """Creates a `PathGlobs` object for the files held by these Sources.

    This field may be projected to request the content of the files for this Sources object.
    """
        return PathGlobs.create(self.spec_path,
                                files=self.files,
                                globs=self.globs,
                                rglobs=self.rglobs,
                                zglobs=self.zglobs)

    @abstractproperty
    def extensions(self):
        """A collection of file extensions collected by this Sources instance.

    An empty collection indicates that any extension will be accepted.
    """

    @property
    def excludes(self):
        """The sources to exclude.

    :rtype: :class:`Sources`
    """


# Since Sources.excludes is recursive on the Sources type, we need to post-class-definition
# re-define excludes in this way.
Sources.excludes = addressable(Exactly(Sources))(Sources.excludes)
Ejemplo n.º 6
0
      for spec, fileset_wrapper_type in ((self.globs, Globs),
                                         (self.rglobs, RGlobs),
                                         (self.zglobs, ZGlobs)):
        if spec:
          fileset = fileset_wrapper_type(base_path)(spec)
          yield fileset

    for rel_path in itertools.chain.from_iterable(file_sources()):
      if select(rel_path):
        file_path = os.path.join(base_path, rel_path)
        if file_path not in excluded_files:
          yield file_path

# Since Sources.excludes is recursive on the Sources type, we need to post-class-definition
# re-define excludes in this way.
Sources.excludes = addressable(Exactly(Sources))(Sources.excludes)


class Target(Configuration):
  """TODO(John Sirois): XXX DOCME"""

  class ConfigurationNotFound(Exception):
    """Indicates a requested configuration of a target could not be found."""

  def __init__(self, name=None, sources=None, configurations=None, dependencies=None, **kwargs):
    """
    :param string name: The name of this target which forms its address in its namespace.
    :param sources: The relative source file paths of sources this target owns.
    :type sources: :class:`Sources`
    :param list configurations: The configurations that apply to this target in various contexts.
    :param list dependencies: The direct dependencies of this target.
Ejemplo n.º 7
0
 def test_type_mismatch(self):
   with self.assertRaises(AddressedError):
     addressable(Exactly(int), 42.0)
Ejemplo n.º 8
0
 def test_pointer(self):
   self.assertEqual(Addressed(Exactly(int), '//:meaning-of-life'),
                    addressable(Exactly(int), '//:meaning-of-life'))
Ejemplo n.º 9
0
 def test_value(self):
   self.assertEqual(42, addressable(Exactly(int), 42))
Ejemplo n.º 10
0
 def test_none(self):
   self.assertIsNone(addressable(Exactly(int), None))
Ejemplo n.º 11
0
 def test_type_mismatch(self):
     with self.assertRaises(AddressedError):
         addressable(Exactly(int), 42.0)
Ejemplo n.º 12
0
 def test_pointer(self):
     self.assertEqual(Addressed(Exactly(int), '//:meaning-of-life'),
                      addressable(Exactly(int), '//:meaning-of-life'))
Ejemplo n.º 13
0
 def test_value(self):
     self.assertEqual(42, addressable(Exactly(int), 42))
Ejemplo n.º 14
0
 def test_none(self):
     self.assertIsNone(addressable(Exactly(int), None))