Esempio n. 1
0
    def test_is_sibling(self):
        """
        Tests :func:`colour.utilities.common.is_sibling` definition.
        """
        class Element(object):
            """
            :func:`is_sibling` unit tests :class:`Element` class.
            """
            def __init__(self, name):
                self.name = name

        class NotElement(object):
            """
            :func:`is_sibling` unit tests :class:`NotElement` class.
            """
            def __init__(self, name):
                self.name = name

        mapping = {
            'Element A': Element('A'),
            'Element B': Element('B'),
            'Element C': Element('C'),
        }

        self.assertTrue(is_sibling(Element('D'), mapping))

        self.assertFalse(is_sibling(NotElement('Not D'), mapping))
Esempio n. 2
0
    def test_is_sibling(self):
        """
        Tests :func:`colour.utilities.common.is_sibling` definition.
        """

        class Element(object):
            """
            :func:`is_sibling` unit tests :class:`Element` class.
            """

            def __init__(self, name):
                self.name = name

        class NotElement(object):
            """
            :func:`is_sibling` unit tests :class:`NotElement` class.
            """

            def __init__(self, name):
                self.name = name

        mapping = {
            'Element A': Element('A'),
            'Element B': Element('B'),
            'Element C': Element('C'),
        }

        self.assertTrue(is_sibling(Element('D'), mapping))

        self.assertFalse(is_sibling(NotElement('Not D'), mapping))
Esempio n. 3
0
def filter_passthrough(mapping,
                       filterers,
                       anchors=True,
                       allow_non_siblings=True,
                       flags=re.IGNORECASE):
    """
    Returns mapping objects matching given filterers while passing through
    class instances whose type is one of the mapping element types.

    This definition allows passing custom but compatible objects to the various
    plotting definitions that by default expect the key from a dataset element.
    For example, a typical call to :func:`colour.plotting.\
plot_multi_illuminant_sds` definition is as follows:

    >>> import colour
    >>> import colour.plotting
    >>> colour.plotting.plot_multi_illuminant_sds(['A'])
    ... # doctest: +SKIP

    But it is also possible to pass a custom spectral distribution as follows:

    >>> data = {
    ...     500: 0.0651,
    ...     520: 0.0705,
    ...     540: 0.0772,
    ...     560: 0.0870,
    ...     580: 0.1128,
    ...     600: 0.1360
    ... }
    >>> colour.plotting.plot_multi_illuminant_sds(
    ...     ['A', colour.SpectralDistribution(data)])
    ... # doctest: +SKIP

    Similarly, a typical call to :func:`colour.plotting.\
plot_planckian_locus_in_chromaticity_diagram_CIE1931` definition is as follows:

    >>> colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931(
    ...     ['A'])
    ... # doctest: +SKIP

    But it is also possible to pass a custom whitepoint as follows:

    >>> colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931(
    ...     ['A', {'Custom': np.array([1 / 3 + 0.05, 1 / 3 + 0.05])}])
    ... # doctest: +SKIP

    Parameters
    ----------
    mapping : dict_like
        Mapping to filter.
    filterers : unicode or object or array_like
        Filterer or object class instance (which is passed through directly if
        its type is one of the mapping element types) or list
        of filterers.
    anchors : bool, optional
        Whether to use Regex line anchors, i.e. *^* and *$* are added,
        surrounding the filterers patterns.
    allow_non_siblings : bool, optional
        Whether to allow non-siblings to be also passed through.
    flags : int, optional
        Regex flags.

    Returns
    -------
    dict_like
        Filtered mapping.
    """

    if is_string(filterers):
        filterers = [filterers]
    elif not isinstance(filterers, (list, tuple)):
        filterers = [filterers]

    string_filterers = [
        filterer for filterer in filterers if is_string(filterer)
    ]

    object_filterers = [
        filterer for filterer in filterers if is_sibling(filterer, mapping)
    ]

    if allow_non_siblings:
        non_siblings = [
            filterer for filterer in filterers
            if filterer not in string_filterers
            and filterer not in object_filterers
        ]

        if non_siblings:
            runtime_warning(
                'Non-sibling elements are passed-through: "{0}"'.format(
                    non_siblings))

            object_filterers.extend(non_siblings)

    filtered_mapping = filter_mapping(mapping, string_filterers, anchors,
                                      flags)

    for filterer in object_filterers:
        if isinstance(filterer, (dict, OrderedDict, CaseInsensitiveMapping)):
            for key, value in filterer.items():
                filtered_mapping[key] = value
        else:
            try:
                name = filterer.name
            except AttributeError:
                try:
                    name = filterer.__name__
                except AttributeError:
                    name = str(id(filterer))

            filtered_mapping[name] = filterer

    return filtered_mapping
Esempio n. 4
0
def filter_passthrough(mapping,
                       filterers,
                       anchors=True,
                       allow_non_siblings=True,
                       flags=re.IGNORECASE):
    """
    Returns mapping objects matching given filterers while passing through
    class instances whose type is one of the mapping element types.

    This definition allows passing custom but compatible objects to the various
    plotting definitions that by default expect the key from a dataset element.
    For example, a typical call to :func:`colour.plotting.\
plot_multi_illuminant_sds` definition is as follows:

    >>> import colour
    >>> import colour.plotting
    >>> colour.plotting.plot_multi_illuminant_sds(['A'])
    ... # doctest: +SKIP

    But it is also possible to pass a custom spectral distribution as follows:

    >>> data = {
    ...     500: 0.0651,
    ...     520: 0.0705,
    ...     540: 0.0772,
    ...     560: 0.0870,
    ...     580: 0.1128,
    ...     600: 0.1360
    ... }
    >>> colour.plotting.plot_multi_illuminant_sds(
    ...     ['A', colour.SpectralDistribution(data)])
    ... # doctest: +SKIP

    Similarly, a typical call to :func:`colour.plotting.\
plot_planckian_locus_in_chromaticity_diagram_CIE1931` definition is as follows:

    >>> colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931(
    ...     ['A'])
    ... # doctest: +SKIP

    But it is also possible to pass a custom whitepoint as follows:

    >>> colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931(
    ...     ['A', {'Custom': np.array([1 / 3 + 0.05, 1 / 3 + 0.05])}])
    ... # doctest: +SKIP

    Parameters
    ----------
    mapping : dict_like
        Mapping to filter.
    filterers : unicode or object or array_like
        Filterer or object class instance (which is passed through directly if
        its type is one of the mapping element types) or list
        of filterers.
    anchors : bool, optional
        Whether to use Regex line anchors, i.e. *^* and *$* are added,
        surrounding the filterers patterns.
    allow_non_siblings : bool, optional
        Whether to allow non-siblings to be also passed through.
    flags : int, optional
        Regex flags.

    Returns
    -------
    dict_like
        Filtered mapping.
    """

    if is_string(filterers):
        filterers = [filterers]
    elif not isinstance(filterers, (list, tuple)):
        filterers = [filterers]

    string_filterers = [
        filterer for filterer in filterers if is_string(filterer)
    ]

    object_filterers = [
        filterer for filterer in filterers if is_sibling(filterer, mapping)
    ]

    if allow_non_siblings:
        non_siblings = [
            filterer for filterer in filterers
            if filterer not in string_filterers and
            filterer not in object_filterers
        ]

        if non_siblings:
            runtime_warning(
                'Non-sibling elements are passed-through: "{0}"'.format(
                    non_siblings))

            object_filterers.extend(non_siblings)

    filtered_mapping = filter_mapping(mapping, string_filterers, anchors,
                                      flags)

    for filterer in object_filterers:
        if isinstance(filterer, (dict, OrderedDict, CaseInsensitiveMapping)):
            for key, value in filterer.items():
                filtered_mapping[key] = value
        else:
            try:
                name = filterer.name
            except AttributeError:
                try:
                    name = filterer.__name__
                except AttributeError:
                    name = str(id(filterer))

            filtered_mapping[name] = filterer

    return filtered_mapping
Esempio n. 5
0
def filter_passthrough(
    mapping: Mapping,
    filterers: Union[Any, str, Sequence[Union[Any, str]]],
    anchors: Boolean = True,
    allow_non_siblings: Boolean = True,
    flags: Union[Integer, RegexFlag] = re.IGNORECASE,
) -> Dict:
    """
    Return mapping objects matching given filterers while passing through
    class instances whose type is one of the mapping element types.

    This definition allows passing custom but compatible objects to the various
    plotting definitions that by default expect the key from a dataset element.

    For example, a typical call to :func:`colour.plotting.\
plot_multi_illuminant_sds` definition with a regex pattern automatically
    anchored at boundaries by default is as follows:

    >>> import colour
    >>> colour.plotting.plot_multi_illuminant_sds(['A'])
    ... # doctest: +SKIP

    Here, `'A'` is by default anchored at boundaries and transformed into
    `'^A$'`. Note that because it is a regex pattern, special characters such
    as parenthesis must be escaped: `'Adobe RGB (1998)'` must be written
    `'Adobe RGB \\(1998\\)'` instead.

    With the previous example, t is also possible to pass a custom spectral
    distribution as follows:

    >>> data = {
    ...     500: 0.0651,
    ...     520: 0.0705,
    ...     540: 0.0772,
    ...     560: 0.0870,
    ...     580: 0.1128,
    ...     600: 0.1360
    ... }
    >>> colour.plotting.plot_multi_illuminant_sds(
    ...     ['A', colour.SpectralDistribution(data)])
    ... # doctest: +SKIP

    Similarly, a typical call to :func:`colour.plotting.\
plot_planckian_locus_in_chromaticity_diagram_CIE1931` definition is as follows:

    >>> colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931(
    ...     ['A'])
    ... # doctest: +SKIP

    But it is also possible to pass a custom whitepoint as follows:

    >>> colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931(
    ...     ['A', {'Custom': np.array([1 / 3 + 0.05, 1 / 3 + 0.05])}])
    ... # doctest: +SKIP

    Parameters
    ----------
    mapping
        Mapping to filter.
    filterers
        Filterer or object class instance (which is passed through directly if
        its type is one of the mapping element types) or list
        of filterers.
    anchors
        Whether to use Regex line anchors, i.e. *^* and *$* are added,
        surrounding the filterers patterns.
    allow_non_siblings
        Whether to allow non-siblings to be also passed through.
    flags
        Regex flags.

    Returns
    -------
    :class:`dict`
        Filtered mapping.
    """

    if is_string(filterers):
        filterers = [filterers]
    elif not isinstance(filterers, (list, tuple)):
        filterers = [filterers]

    string_filterers: List[str] = [
        cast(str, filterer) for filterer in filterers if is_string(filterer)
    ]

    object_filterers: List[Any] = [
        filterer for filterer in filterers if is_sibling(filterer, mapping)
    ]

    if allow_non_siblings:
        non_siblings = [
            filterer for filterer in filterers
            if filterer not in string_filterers
            and filterer not in object_filterers
        ]

        if non_siblings:
            runtime_warning(
                f'Non-sibling elements are passed-through: "{non_siblings}"')

            object_filterers.extend(non_siblings)

    filtered_mapping = filter_mapping(mapping, string_filterers, anchors,
                                      flags)

    for filterer in object_filterers:
        # TODO: Consider using "MutableMapping" here.
        if isinstance(filterer, (dict, CaseInsensitiveMapping)):
            for key, value in filterer.items():
                filtered_mapping[key] = value
        else:
            try:
                name = filterer.name
            except AttributeError:
                try:
                    name = filterer.__name__
                except AttributeError:
                    name = str(id(filterer))

            filtered_mapping[name] = filterer

    return filtered_mapping
Esempio n. 6
0
def filter_passthrough(mapping,
                       filterers,
                       anchors=True,
                       allow_non_siblings=True,
                       flags=re.IGNORECASE):
    """
    Returns mapping objects matching given filterers while passing through
    class instances whose type is one of the mapping element types.

    Parameters
    ----------
    mapping : dict_like
        Mapping to filter.
    filterers : unicode or object or array_like
        Filterer or object class instance (which is passed through directly if
        its type is one of the mapping element types) or list
        of filterers.
    anchors : bool, optional
        Whether to use Regex line anchors, i.e. *^* and *$* are added,
        surrounding the filterers patterns.
    allow_non_siblings : bool, optional
        Whether to allow non-siblings to be also passed through.
    flags : int, optional
        Regex flags.

    Returns
    -------
    dict_like
        Filtered mapping.
    """

    if is_string(filterers):
        filterers = [filterers]
    elif not isinstance(filterers, (list, tuple)):
        filterers = [filterers]

    string_filterers = [
        filterer for filterer in filterers if is_string(filterer)
    ]

    object_filterers = [
        filterer for filterer in filterers if is_sibling(filterer, mapping)
    ]

    if allow_non_siblings:
        non_siblings = [
            filterer for filterer in filterers
            if filterer not in string_filterers
            and filterer not in object_filterers
        ]

        if non_siblings:
            runtime_warning(
                'Non-sibling elements are passed-through: "{0}"'.format(
                    non_siblings))

            object_filterers.extend(non_siblings)

    filtered_mapping = filter_mapping(mapping, string_filterers, anchors,
                                      flags)

    for filterer in object_filterers:
        try:
            name = filterer.name
        except AttributeError:
            try:
                name = filterer.__name__
            except AttributeError:
                name = str(id(filterer))

        filtered_mapping[name] = filterer

    return filtered_mapping