coalib.bearlib.aspects.taste — coala 0.9.0.dev99999999999999 documentation

# Source code for coalib.bearlib.aspects.taste

    from coala_utils.decorators import enforce_signature

    from coalib.bearlib.languages import Languages

    class TasteError(AttributeError):
        """
        A taste is not allowed to be accessed.
        """

    class TasteMeta(type):
        """
        Metaclass for :class:`coalib.bearlib.aspectclasses.Taste`

        Allows defining taste cast type via :meth:`.__getitem__`, like:

        >>> Taste[int]().cast_type
        <class 'int'>
        """

        def __getitem__(cls, _cast_type):
            class Taste(cls):
                cast_type = _cast_type

            Taste.__name__ = Taste.__qualname__ = '%s[%s]' % (
                cls.__name__, _cast_type.__name__)
            return Taste

    class Taste(metaclass=TasteMeta):
        """
        Defines tastes in aspectclass definitions.

        Tastes can be made only available for certain languages by
        providing a ``tuple`` of language identifiers on instantiation:

        >>> Taste[bool](
        ...     'Ignore ``using`` directives in C#.',
        ...     (True, False), default=False,
        ...     languages=('CSharp', )
        ... ).languages
        (C#,)

        If no `languages` are given, they will be available for any language.
        See :class:`coalib.bearlib.aspectclasses.Root` for further usage.
        """
        cast_type = str

        @enforce_signature
        def __init__(self, description: str='', suggested_values: tuple=(),
                     default=None, languages: tuple=()):
            """
            Creates a new taste that can be optionally only available for the
            given `languages`, which must be language identifiers supported by
            :class:`coalib.bearlib.languages.Language`.

            No need to specify name an cast type:

            The taste name is defined by the taste's attribute name in an
            aspectclass definition.

            The value cast type is defined via indexing on class level.
            """
            self.description = description
            self.suggested_values = suggested_values
            self.default = default
            self.languages = Languages(languages)

        def __get__(self, obj, owner=None):
            """
            Checks availability of taste for aspectclass instance `obj`'s
            ``.language`` before returning the specific taste value.
            """
            if obj is not None:
                # ==> access from aspectclass instance
                if self.languages and obj.language not in self.languages:
                    raise TasteError('%s.%s is not available for %s.' % (
                        type(obj).__qualname__, self.name, obj.language))
                return obj.__dict__[self.name]
            # ==> access from aspectclass
            return self

        def __set__(self, obj, value):
            """
            Ensures that `value` is only set once in `obj`'s ``.__dict__``.
            """
            if self.name in obj.__dict__:
                raise AttributeError(
                    "can't set taste values of aspectclass instances")
            obj.__dict__[self.name] = self.cast_type(value)