#
#  Copyright (C) 2018 Codethink Limited
#  Copyright (C) 2019 Bloomberg LLP
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
#        Daniel Silverstone <daniel.silverstone@codethink.co.uk>
#        James Ennis <james.ennis@codethink.co.uk>
#        Benjamin Schubert <bschubert@bloomberg.net>

"""
Node - Parsed YAML configuration
================================

This module contains the building blocks for handling YAML configuration.

Everything that is loaded from YAML is encapsulated in such nodes, which
provide helper methods to validate configuration on access.

Using node methods when reading configuration will ensure that errors
are always coherently notified to the user.


Node types
----------

The most important classes defined here are:

* :class:`.MappingNode`: represents a YAML Mapping (dictionary)
* :class:`.ScalarNode`: represents a YAML Scalar (string, boolean, integer)
* :class:`.SequenceNode`: represents a YAML Sequence (list)


Class Reference
---------------
"""

import string

from ._exceptions import LoadError, LoadErrorReason


# A sentinel to be used as a default argument for functions that need
# to distinguish between a kwarg set to None and an unset kwarg.
_sentinel = object()


cdef class Node:
    """This is the base class for YAML document nodes.

    YAML Nodes contain information to describe the provenance of the YAML
    which resulted in the Node, allowing mapping back from a Node to the place
    in the file it came from.

    .. note:: You should never need to create a :class:`.Node` manually.
              If you do, you can create :class:`.Node` from dictionaries with
              :func:`Node.from_dict() <buildstream.node.Node.from_dict>`.
              If something else is needed, please open an issue.
    """

    def __init__(self):
        raise NotImplementedError("Please do not construct nodes like this. Use Node.from_dict(dict) instead.")

    def __cinit__(self, int file_index, int line, int column, *args):
        self.file_index = file_index
        self.line = line
        self.column = column

    # This is in order to ensure we never add a `Node` to a cache key
    # as ujson will try to convert objects if they have a `__json__`
    # attribute.
    def __json__(self):
        raise ValueError("Nodes should not be allowed when jsonify-ing data", self)

    #############################################################
    #                  Abstract Public Methods                  #
    #############################################################

    cpdef Node clone(self):
        """Clone the node and return the copy.

        Returns:
            :class:`.Node`: a clone of the current node
        """
        raise NotImplementedError()

    cpdef object strip_node_info(self):
        """ Remove all the node information (provenance) and return the underlying data as plain python objects 

        Returns:
            (list, dict, str, None): the underlying data that was held in the node structure.
        """
        raise NotImplementedError()

    #############################################################
    #                       Public Methods                      #
    #############################################################

    @classmethod
    def from_dict(cls, dict value):
        """from_dict(value)

        Create a new node from the given dictionary.

        This is a recursive operation, and will transform every value in the
        dictionary to a :class:`.Node` instance

        Valid values for keys are `str`
        Valid values for values are `list`, `dict`, `str`, `int`, `bool` or None.
        `list` and `dict` can also only contain such types.

        Args:
            value (dict): dictionary from which to create a node.

        Raises:
            :class:`TypeError`: when the value cannot be converted to a :class:`Node`

        Returns:
            :class:`.MappingNode`: a new mapping containing the value
        """
        if value:
            return __new_node_from_dict(value, MappingNode.__new__(
                MappingNode, _SYNTHETIC_FILE_INDEX, 0, __next_synthetic_counter(), {}))
        else:
            # We got an empty dict, we can shortcut
            return MappingNode.__new__(MappingNode, _SYNTHETIC_FILE_INDEX, 0, __next_synthetic_counter(), {})

    cpdef ProvenanceInformation get_provenance(self):
        """A convenience accessor to obtain the node's :class:`.ProvenanceInformation`

        The provenance information allows you to inform the user of where
        a node came. Transforming the information to a string will show the file, line and column
        in the file where the node is.

        An example usage would be:

        .. code-block:: python

            # With `config` being your node
            max_jobs_node = config.get_node('max-jobs')
            max_jobs = max_jobs_node.as_int()

            if max_jobs < 1:  # We can't get a negative number of jobs
                raise LoadError("Error at {}: Max jobs needs to be >= 1".format(
                    max_jobs_node.get_provenance()
                )

            # Will print something like:
            # element.bst [line 4, col 7]: Max jobs needs to be >= 1

        Returns:
            :class:`.ProvenanceInformation`: the provenance information for the node.
        """
        return ProvenanceInformation(self)

    #############################################################
    #        Abstract Private Methods used in BuildStream       #
    #############################################################

    # _assert_fully_composited()
    #
    # This must be called on a fully loaded and composited node,
    # after all composition has completed.
    #
    # This checks that no more composition directives are present
    # in the data.
    #
    # Raises:
    #    (LoadError): If any assertions fail
    #
    cpdef void _assert_fully_composited(self) except *:
        raise NotImplementedError()

    #############################################################
    #                Abstract Protected Methods                 #
    #############################################################

    # _compose_on(key, target, path)
    #
    # Compose the current node on the given target.
    #
    # Args:
    #   key (str): key on the target on which to compose the current value
    #   target (.Node): target node on which to compose
    #   path (list): path from the root of the target when composing recursively
    #         in order to give accurate error reporting.
    #
    # Raises:
    #   (_CompositeError): if an error is encountered during composition
    #
    cdef void _compose_on(self, str key, MappingNode target, list path) except *:
        raise NotImplementedError()

    # _is_composite_list
    #
    # Checks if the node is a Mapping with array composition
    # directives.
    #
    # Returns:
    #    (bool): True if node was a Mapping containing only
    #            list composition directives
    #
    # Raises:
    #    (LoadError): If node was a mapping and contained a mix of
    #                 list composition directives and other keys
    #
    cdef bint _is_composite_list(self) except *:
        raise NotImplementedError()

    # _walk_find(target, path)
    #
    # Walk the node to search for `target`.
    #
    # When this returns `True`, the `path` argument will contain the full path
    # to the target from the root node.
    #
    # Args:
    #   target (.Node): target to find in the node tree
    #   path (list): current path from the root
    #
    # Returns:
    #   (bool): whether the target was found in the tree or not
    #
    cdef bint _walk_find(self, Node target, list path) except *:
        raise NotImplementedError()

    #############################################################
    #                     Protected Methods                     #
    #############################################################

    # _shares_position_with(target)
    #
    # Check whether the current node is at the same position in its tree as the target.
    #
    # This is useful when we want to know if two nodes are 'identical', that is they
    # are at the exact same position in each respective tree, but do not necessarily
    # have the same content.
    #
    # Args:
    #   target (.Node): the target to compare with the current node.
    #
    # Returns:
    #   (bool): whether the two nodes share the same position
    #
    cdef bint _shares_position_with(self, Node target):
        return (self.file_index == target.file_index and
                self.line == target.line and
                self.column == target.column)


cdef class ScalarNode(Node):
    """This class represents a Scalar (int, str, bool, None) in a YAML document.

    .. note:: If you need to store another type of scalars, please open an issue
              on the project.

    .. note:: You should never have to create a :class:`.ScalarNode` directly
    """

    def __cinit__(self, int file_index, int line, int column, object value):
        cdef value_type = type(value)

        if value_type is str:
            value = value.strip()
        elif value_type is bool:
            if value:
                value = "True"
            else:
                value = "False"
        elif value_type is int:
            value = str(value)
        elif value is None:
            pass
        else:
            raise ValueError("ScalarNode can only hold str, int, bool or None objects")

        self.value = value

    def __reduce__(self):
        return (
            ScalarNode.__new__,
            (ScalarNode, self.file_index, self.line, self.column, self.value),
        )

    #############################################################
    #                       Public Methods                      #
    #############################################################

    cpdef bint as_bool(self) except *:
        """Get the value of the node as a boolean.

        .. note:: BuildStream treats the values 'True' and 'true' as True,
                  and the values 'False' and 'false' as False.  Any other
                  string values (such as the valid YAML 'TRUE' or 'FALSE'
                  will be considered as an error)

        Raises:
            :class:`buildstream._exceptions.LoadError`: if the value cannot be coerced to
                                                        a bool correctly.

        Returns:
            :class:`bool`: the value contained in the node, as a boolean
        """
        if type(self.value) is bool:
            return self.value

        # Don't coerce strings to booleans, this makes "False" strings evaluate to True
        if self.value in ('True', 'true'):
            return True
        elif self.value in ('False', 'false'):
            return False
        else:
            provenance = self.get_provenance()
            path = provenance._toplevel._find(self)[-1]
            raise LoadError("{}: Value of '{}' is not of the expected type '{}'"
                            .format(provenance, path, bool.__name__, self.value),
                            LoadErrorReason.INVALID_DATA)

    cpdef object as_enum(self, object constraint):
        """Get the value of the node as an enum member from `constraint`

        The constraint must be a :class:`buildstream.types.FastEnum` or a plain python Enum.

        For example you could do:

        .. code-block:: python

            from buildstream.types import FastEnum

            class SupportedCompressions(FastEnum):
              NONE = "none"
              GZIP = "gzip"
              XZ = "xz"


            x = config.get_scalar('compress').as_enum(SupportedCompressions)

            if x == SupportedCompressions.GZIP:
                print("Using GZIP")

        Args:
            constraint (:class:`buildstream.types.FastEnum` or :class:`Enum`): an enum from which to extract the value
                                                                               for the current node.

        Returns:
            :class:`FastEnum` or :class:`Enum`: the value contained in the node, as a member of `constraint`
        """
        try:
            return constraint(self.value)
        except ValueError:
            provenance = self.get_provenance()
            path = provenance._toplevel._find(self)[-1]
            valid_values = [str(v.value) for v in constraint]
            raise LoadError("{}: Value of '{}' should be one of '{}'".format(
                                provenance, path, ", ".join(valid_values)),
                            LoadErrorReason.INVALID_DATA)

    cpdef int as_int(self) except *:
        """Get the value of the node as an integer.

        Raises:
            :class:`buildstream._exceptions.LoadError`: if the value cannot be coerced to
                                                        an integer correctly.

        Returns:
            :class:`int`: the value contained in the node, as a integer
        """
        try:
            return int(self.value)
        except ValueError:
            provenance = self.get_provenance()
            path = provenance._toplevel._find(self)[-1]
            raise LoadError("{}: Value of '{}' is not of the expected type '{}'"
                            .format(provenance, path, int.__name__),
                            LoadErrorReason.INVALID_DATA)

    cpdef str as_str(self):
        """Get the value of the node as a string.

        Returns:
            :class:`str`: the value contained in the node, as a string, or `None` if the content
                          is `None`.
        """
        # We keep 'None' as 'None' to simplify the API's usage and allow chaining for users
        if self.value is None:
            return None
        return str(self.value)

    cpdef bint is_none(self):
        """Determine whether the current scalar is `None`.

        Returns:
            :class:`bool`: `True` if the value of the scalar is `None`, else `False`
        """
        return self.value is None

    #############################################################
    #               Public Methods implementations              #
    #############################################################

    cpdef ScalarNode clone(self):
        return self

    cpdef object strip_node_info(self):
        return self.value

    #############################################################
    #              Private Methods implementations              #
    #############################################################

    cpdef void _assert_fully_composited(self) except *:
        pass

    #############################################################
    #                     Protected Methods                     #
    #############################################################

    cdef void _compose_on(self, str key, MappingNode target, list path) except *:
        cdef Node target_value = target.value.get(key)

        if target_value is not None and type(target_value) is not ScalarNode:
            raise __CompositeError(path,
                                   "{}: Cannot compose scalar on non-scalar at {}".format(
                                       self.get_provenance(),
                                       target_value.get_provenance()))

        target.value[key] = self

    cdef bint _is_composite_list(self) except *:
        return False

    cdef bint _walk_find(self, Node target, list path) except *:
        return self._shares_position_with(target)


cdef class MappingNode(Node):
    """This class represents a Mapping (dict) in a YAML document.

    It behaves mostly like a :class:`dict`, but doesn't allow untyped value access
    (Nothing of the form :code:`my_dict[my_value]`.

    It also doesn't allow anything else than :class:`str` as keys, to align with YAML.

    You can however use common dict operations in it:

    .. code-block:: python

        # Assign a new value to a key
        my_mapping[key] = my_value

        # Delete an entry
        del my_mapping[key]

    When assigning a key/value pair, the key must be a string,
    and the value can be any of:

    * a :class:`Node`, in which case the node is just assigned like normally
    * a :class:`list`, :class:`dict`, :class:`int`, :class:`str`, :class:`bool` or :class:`None`.
      In which case, the value will be converted to a :class:`Node` for you.

    Therefore, all values in a :class:`.MappingNode` will be :class:`Node`.

    .. note:: You should never create an instance directly. Use :func:`Node.from_dict() <buildstream.node.Node.from_dict>`
              instead, which will ensure your node is correctly formatted.
    """

    def __cinit__(self, int file_index, int line, int column, dict value):
        self.value = value

    def __reduce__(self):
        return (
            MappingNode.__new__,
            (MappingNode, self.file_index, self.line, self.column, self.value),
        )

    def __contains__(self, what):
        return what in self.value

    def __delitem__(self, str key):
        del self.value[key]

    def __setitem__(self, str key, object value):
        cdef Node old_value

        if type(value) in [MappingNode, ScalarNode, SequenceNode]:
            self.value[key] = value
        else:
            node = __create_node_recursive(value, self)

            # FIXME: Do we really want to override provenance?
            #
            # Related to https://gitlab.com/BuildStream/buildstream/issues/1058
            #
            # There are only two cases were nodes are set in the code (hence without provenance):
            #   - When automatic variables are set by the core (e-g: max-jobs)
            #   - when plugins call Element.set_public_data
            #
            # The first case should never throw errors, so it is of limited interests.
            #
            # The second is more important. What should probably be done here is to have 'set_public_data'
            # able of creating a fake provenance with the name of the plugin, the project and probably the
            # element name.
            #
            # We would therefore have much better error messages, and would be able to get rid of most synthetic
            # nodes.
            old_value = self.value.get(key)
            if old_value:
                node.file_index = old_value.file_index
                node.line = old_value.line
                node.column = old_value.column

            self.value[key] = node

    #############################################################
    #                       Public Methods                      #
    #############################################################

    cpdef bint get_bool(self, str key, object default=_sentinel) except *:
        """get_bool(key, default=sentinel)

        Get the value of the node for `key` as a boolean.

        This is equivalent to: :code:`mapping.get_scalar(my_key, my_default).as_bool()`.

        Args:
            key (str): key for which to get the value
            default (bool): default value to return if `key` is not in the mapping

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.ScalarNode` or isn't a
                                                       valid `boolean`

        Returns:
            :class:`bool`: the value at `key` or the default
        """
        cdef ScalarNode scalar = self.get_scalar(key, default)
        return scalar.as_bool()

    cpdef object get_enum(self, str key, object constraint, object default=_sentinel):
        """Get the value of the node as an enum member from `constraint`

        Args:
            key (str): key for which to get the value
            constraint (:class:`buildstream.types.FastEnum` or :class:`Enum`): an enum from which to extract the value
                                                                               for the current node.
            default (object): default value to return if `key` is not in the mapping

        Raises:
            :class:`buildstream._exceptions.LoadError`: if the value is not is not found or not part of the
                                                        provided enum.

        Returns:
            :class:`buildstream.types.Enum` or :class:`Enum`: the value contained in the node, as a member of
                                                              `constraint`
        """
        cdef object value = self.value.get(key, _sentinel)

        if value is _sentinel:
            if default is _sentinel:
                provenance = self.get_provenance()
                raise LoadError("{}: Dictionary did not contain expected key '{}'".format(provenance, key),
                                LoadErrorReason.INVALID_DATA)

            if default is None:
                return None
            else:
                return constraint(default)

        if type(value) is not ScalarNode:
            provenance = value.get_provenance()
            raise LoadError("{}: Value of '{}' is not of the expected type 'scalar'"
                                .format(provenance, key),
                            LoadErrorReason.INVALID_DATA)

        return (<ScalarNode> value).as_enum(constraint)

    cpdef int get_int(self, str key, object default=_sentinel) except *:
        """get_int(key, default=sentinel)

        Get the value of the node for `key` as an integer.

        This is equivalent to: :code:`mapping.get_scalar(my_key, my_default).as_int()`.

        Args:
            key (str): key for which to get the value
            default (int): default value to return if `key` is not in the mapping

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.ScalarNode` or isn't a
                                                       valid `integer`

        Returns:
            :class:`int`: the value at `key` or the default
        """
        cdef ScalarNode scalar = self.get_scalar(key, default)
        return scalar.as_int()

    cpdef MappingNode get_mapping(self, str key, object default=_sentinel):
        """get_mapping(key, default=sentinel)

        Get the value of the node for `key` as a :class:`.MappingNode`.

        Args:
            key (str): key for which to get the value
            default (dict): default value to return if `key` is not in the mapping. It will be converted
                            to a :class:`.MappingNode` before being returned

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.MappingNode`

        Returns:
            :class:`.MappingNode`: the value at `key` or the default
        """
        value = self._get(key, default, MappingNode)

        if type(value) is not MappingNode and value is not None:
            provenance = value.get_provenance()
            raise LoadError("{}: Value of '{}' is not of the expected type 'dict'"
                            .format(provenance, key), LoadErrorReason.INVALID_DATA)

        return value

    cpdef Node get_node(self, str key, list allowed_types = None, bint allow_none = False):
        """get_node(key, allowed_types=None, allow_none=False)

        Get the value of the node for `key` as a :class:`.Node`.

        This is useful if you have configuration that can be either a :class:`.ScalarNode` or
        a :class:`.MappingNode` for example.

        This method will validate that the value is indeed exactly one of those types (not a subclass)
        and raise an exception accordingly.

        Args:
            key (str): key for which to get the value
            allowed_types (list): list of valid subtypes of :class:`.Node` that are valid return values.
                                  If this is `None`, no checks are done on the return value.
            allow_none (bool): whether to allow the return value to be `None` or not

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not one
                                                       of the expected types or if it doesn't
                                                       exist.

        Returns:
            :class:`.Node`: the value at `key` or `None`
        """
        cdef value = self.value.get(key, _sentinel)

        if value is _sentinel:
            if allow_none:
                return None

            provenance = self.get_provenance()
            raise LoadError("{}: Dictionary did not contain expected key '{}'".format(provenance, key),
                            LoadErrorReason.INVALID_DATA)

        if allowed_types and type(value) not in allowed_types:
            provenance = self.get_provenance()
            human_types = []
            if MappingNode in allowed_types:
                human_types.append("dict")
            if SequenceNode in allowed_types:
                human_types.append('list')
            if ScalarNode in allowed_types:
                human_types.append('scalar')

            raise LoadError("{}: Value of '{}' is not one of the following: {}.".format(
                            provenance, key, ", ".join(human_types)), LoadErrorReason.INVALID_DATA)

        return value

    cpdef ScalarNode get_scalar(self, str key, object default=_sentinel):
        """get_scalar(key, default=sentinel)

        Get the value of the node for `key` as a :class:`.ScalarNode`.

        Args:
            key (str): key for which to get the value
            default (str, int, bool, None): default value to return if `key` is not in the mapping.
                                            It will be converted to a :class:`.ScalarNode` before being
                                            returned.

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.MappingNode`

        Returns:
            :class:`.ScalarNode`: the value at `key` or the default
        """
        value = self._get(key, default, ScalarNode)

        if type(value) is not ScalarNode:
            if value is None:
                value = ScalarNode.__new__(ScalarNode, self.file_index, 0, __next_synthetic_counter(), None)
            else:
                provenance = value.get_provenance()
                raise LoadError("{}: Value of '{}' is not of the expected type 'scalar'"
                                .format(provenance, key), LoadErrorReason.INVALID_DATA)

        return value

    cpdef SequenceNode get_sequence(self, str key, object default=_sentinel):
        """get_sequence(key, default=sentinel)

        Get the value of the node for `key` as a :class:`.SequenceNode`.

        Args:
            key (str): key for which to get the value
            default (list): default value to return if `key` is not in the mapping. It will be converted
                            to a :class:`.SequenceNode` before being returned

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.SequenceNode`

        Returns:
            :class:`.SequenceNode`: the value at `key` or the default
        """
        value = self._get(key, default, SequenceNode)

        if type(value) is not SequenceNode and value is not None:
            provenance = value.get_provenance()
            raise LoadError("{}: Value of '{}' is not of the expected type 'list'"
                            .format(provenance, key), LoadErrorReason.INVALID_DATA)

        return value

    cpdef str get_str(self, str key, object default=_sentinel):
        """get_str(key, default=sentinel)

        Get the value of the node for `key` as an string.

        This is equivalent to: :code:`mapping.get_scalar(my_key, my_default).as_str()`.

        Args:
            key (str): key for which to get the value
            default (str): default value to return if `key` is not in the mapping

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.ScalarNode` or isn't a
                                                       valid `str`

        Returns:
            :class:`str`: the value at `key` or the default
        """
        cdef ScalarNode scalar = self.get_scalar(key, default)
        return scalar.as_str()

    cpdef list get_str_list(self, str key, object default=_sentinel):
        """get_str_list(key, default=sentinel)

        Get the value of the node for `key` as a list of strings.

        This is equivalent to: :code:`mapping.get_sequence(my_key, my_default).as_str_list()`.

        Args:
            key (str): key for which to get the value
            default (str): default value to return if `key` is not in the mapping

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.SequenceNode` or if any
                                                       of its internal values is not a ScalarNode.

        Returns:
            :class:`list`: the value at `key` or the default
        """
        cdef SequenceNode sequence = self.get_sequence(key, default)
        return sequence.as_str_list()

    cpdef object items(self):
        """Get a new view of the mapping items ((key, value) pairs).

        This is equivalent to running :code:`my_dict.item()` on a `dict`.

        Returns:
             :class:`dict_items`: a view on the underlying dictionary
        """
        return self.value.items()

    cpdef list keys(self):
        """Get the list of all keys in the mapping.

        This is equivalent to running :code:`my_dict.keys()` on a `dict`.

        Returns:
             :class:`list`: a list of all keys in the mapping
        """
        return list(self.value.keys())

    cpdef void safe_del(self, str key):
        """safe_del(key)

        Remove the entry at `key` in the dictionary if it exists.

        This method is a safe equivalent to :code:`del mapping[key]`, that doesn't
        throw anything if the key doesn't exist.

        Args:
            key (str): key to remove from the mapping
        """
        self.value.pop(key, None)

    cpdef void validate_keys(self, list valid_keys) except *:
        """validate_keys(valid_keys)

        Validate that the node doesn't contain extra keys

        This validates the node so as to ensure the user has not specified
        any keys which are unrecognized by BuildStream (usually this
        means a typo which would otherwise not trigger an error).

        Args:
           valid_keys (list): A list of valid keys for the specified node

        Raises:
            :class:`buildstream._exceptions.LoadError`: In the case that the specified node contained
                                                        one or more invalid keys
        """

        # Probably the fastest way to do this: https://stackoverflow.com/a/23062482
        cdef set valid_keys_set = set(valid_keys)
        cdef str key

        for key in self.value:
            if key not in valid_keys_set:
                provenance = self.get_node(key).get_provenance()
                raise LoadError("{}: Unexpected key: {}".format(provenance, key),
                                LoadErrorReason.INVALID_DATA)

    cpdef object values(self):
        """Get the values in the mapping.

        This is equivalent to running :code:`my_dict.values()` on a `dict`.

        Returns:
             :class:`dict_values`: a list of all values in the mapping
        """
        return self.value.values()

    #############################################################
    #               Public Methods implementations              #
    #############################################################

    cpdef MappingNode clone(self):
        cdef dict copy = {}
        cdef str key
        cdef Node value

        for key, value in self.value.items():
            copy[key] = value.clone()

        return MappingNode.__new__(MappingNode, self.file_index, self.line, self.column, copy)

    cpdef object strip_node_info(self):
        cdef str key
        cdef Node value

        return {key: value.strip_node_info() for key, value in self.value.items()}

    #############################################################
    #            Private Methods used in BuildStream            #
    #############################################################

    # _composite()
    #
    # Compose one mapping node onto another
    #
    # Args:
    #    target (Node): The target to compose into
    #
    # Raises: LoadError
    #
    cpdef void _composite(self, MappingNode target) except *:
        try:
            self.__composite(target, [])
        except __CompositeError as e:
            source_provenance = self.get_provenance()
            error_prefix = ""
            if source_provenance:
                error_prefix = "{}: ".format(source_provenance)
            raise LoadError("{}Failure composing {}: {}"
                            .format(error_prefix,
                                    e.path,
                                    e.message),
                            LoadErrorReason.ILLEGAL_COMPOSITE) from e

    # Like self._composite(target), but where values in the target don't get overridden by values in self.
    #
    cpdef void _composite_under(self, MappingNode target) except *:
        target._composite(self)

        cdef str key
        cdef Node value
        cdef list to_delete = [key for key in target.value.keys() if key not in self.value]

        for key, value in self.value.items():
            target.value[key] = value
        for key in to_delete:
            del target.value[key]

    # _find()
    #
    # Searches the given node tree for the given target node.
    #
    # This is typically used when trying to walk a path to a given node
    # for the purpose of then modifying a similar tree of objects elsewhere
    #
    # Args:
    #    target (Node): The node you are looking for in that tree
    #
    # Returns:
    #    (list): A path from `node` to `target` or None if `target` is not in the subtree
    cpdef list _find(self, Node target):
        cdef list path = []
        if self._walk_find(target, path):
            return path
        return None

    #############################################################
    #              Private Methods implementations              #
    #############################################################

    cpdef void _assert_fully_composited(self) except *:
        cdef str key
        cdef Node value

        for key, value in self.value.items():
            # Assert that list composition directives dont remain, this
            # indicates that the user intended to override a list which
            # never existed in the underlying data
            #
            if key in ('(>)', '(<)', '(=)'):
                provenance = value.get_provenance()
                raise LoadError("{}: Attempt to override non-existing list".format(provenance),
                                LoadErrorReason.TRAILING_LIST_DIRECTIVE)

            value._assert_fully_composited()

    #############################################################
    #                     Protected Methods                     #
    #############################################################

    cdef void _compose_on(self, str key, MappingNode target, list path) except *:
        cdef Node target_value

        if self._is_composite_list():
            if key not in target.value:
                # Composite list clobbers empty space
                target.value[key] = self
            else:
                target_value = target.value[key]

                if type(target_value) is SequenceNode:
                    # Composite list composes into a list
                    self._compose_on_list(target_value)
                elif target_value._is_composite_list():
                    # Composite list merges into composite list
                    self._compose_on_composite_dict(target_value)
                else:
                    # Else composing on top of normal dict or a scalar, so raise...
                    raise __CompositeError(path,
                                           "{}: Cannot compose lists onto {}".format(
                                                self.get_provenance(),
                                                target_value.get_provenance()))
        else:
            # We're composing a dict into target now
            if key not in target.value:
                # Target lacks a dict at that point, make a fresh one with
                # the same provenance as the incoming dict
                target.value[key] = MappingNode.__new__(MappingNode, self.file_index, self.line, self.column, {})

            self.__composite(target.value[key], path)

    # _compose_on_list(target)
    #
    # Compose the current node on the given sequence.
    #
    # Args:
    #   target (.SequenceNode): sequence on which to compose the current composite dict
    #
    cdef void _compose_on_list(self, SequenceNode target):
        cdef SequenceNode clobber = self.value.get("(=)")
        cdef SequenceNode prefix = self.value.get("(<)")
        cdef SequenceNode suffix = self.value.get("(>)")

        if clobber is not None:
            target.value.clear()
            target.value.extend(clobber.value)
        if prefix is not None:
            for v in reversed(prefix.value):
                target.value.insert(0, v)
        if suffix is not None:
            target.value.extend(suffix.value)

    # _compose_on_composite_dict(target)
    #
    # Compose the current node on the given composite dict.
    #
    # A composite dict is a dict that contains composition directives.
    #
    # Args:
    #   target (.MappingNode): sequence on which to compose the current composite dict
    #
    cdef void _compose_on_composite_dict(self, MappingNode target):
        cdef SequenceNode clobber = self.value.get("(=)")
        cdef SequenceNode prefix = self.value.get("(<)")
        cdef SequenceNode suffix = self.value.get("(>)")

        if clobber is not None:
            # We want to clobber the target list
            # which basically means replacing the target list
            # with ourselves
            target.value["(=)"] = clobber
            if prefix is not None:
                target.value["(<)"] = prefix
            elif "(<)" in target.value:
                (<SequenceNode> target.value["(<)"]).value.clear()
            if suffix is not None:
                target.value["(>)"] = suffix
            elif "(>)" in target.value:
                (<SequenceNode> target.value["(>)"]).value.clear()
        else:
            # Not clobbering, so prefix the prefix and suffix the suffix
            if prefix is not None:
                if "(<)" in target.value:
                    for v in reversed(prefix.value):
                        (<SequenceNode> target.value["(<)"]).value.insert(0, v)
                else:
                    target.value["(<)"] = prefix
            if suffix is not None:
                if "(>)" in target.value:
                    (<SequenceNode> target.value["(>)"]).value.extend(suffix.value)
                else:
                    target.value["(>)"] = suffix

    cdef bint _is_composite_list(self) except *:
        cdef bint has_directives = False
        cdef bint has_keys = False
        cdef str key

        for key in self.value.keys():
            if key in ['(>)', '(<)', '(=)']:
                has_directives = True
            else:
                has_keys = True

        if has_keys and has_directives:
            provenance = self.get_provenance()
            raise LoadError("{}: Dictionary contains array composition directives and arbitrary keys"
                            .format(provenance), LoadErrorReason.INVALID_DATA)

        return has_directives

    cdef bint _walk_find(self, Node target, list path) except *:
        cdef str k
        cdef Node v

        if self._shares_position_with(target):
            return True

        for k, v in self.value.items():
            path.append(k)
            if v._walk_find(target, path):
                return True
            del path[-1]

        return False

    #############################################################
    #                      Private Methods                      #
    #############################################################

    # __composite(target, path)
    #
    # Helper method to compose the current node on another.
    #
    # Args:
    #   target (.MappingNode): target on which to compose the current node
    #   path (list): path from the root of the target when composing recursively
    #                in order to give accurate error reporting.
    #
    cdef void __composite(self, MappingNode target, list path) except *:
        cdef str key
        cdef Node value

        for key, value in self.value.items():
            path.append(key)
            value._compose_on(key, target, path)
            path.pop()

        # Clobber the provenance of the target mapping node if we're not
        # synthetic.
        if self.file_index != _SYNTHETIC_FILE_INDEX:
            target.file_index = self.file_index
            target.line = self.line
            target.column = self.column

    # _get(key, default, default_constructor)
    #
    # Internal helper method to get an entry from the underlying dictionary.
    #
    # Args:
    #   key (str): the key for which to retrieve the entry
    #   default (object): default value if the entry is not present
    #   default_constructor (object): method to transform the `default` into a Node
    #                                 if the entry is not present
    #
    # Raises:
    #   (LoadError): if the key is not present and no default has been given.
    #
    cdef Node _get(self, str key, object default, object default_constructor):
        value = self.value.get(key, _sentinel)

        if value is _sentinel:
            if default is _sentinel:
                provenance = self.get_provenance()
                raise LoadError("{}: Dictionary did not contain expected key '{}'".format(provenance, key),
                                LoadErrorReason.INVALID_DATA)

            if default is None:
                value = None
            else:
                value = default_constructor.__new__(
                    default_constructor, _SYNTHETIC_FILE_INDEX, 0, __next_synthetic_counter(), default)

        return value


cdef class SequenceNode(Node):
    """This class represents a Sequence (list) in a YAML document.

    It behaves mostly like a :class:`list`, but doesn't allow untyped value access
    (Nothing of the form :code:`my_list[my_value]`).

    You can however perform common list operations on it:

    .. code-block:: python

        # Assign a value
        my_sequence[key] = value

        # Get the length
        len(my_sequence)

        # Reverse it
        reversed(my_sequence)

        # And iter over it
        for value in my_sequence:
            print(value)

    All values in a :class:`SequenceNode` will be :class:`Node`.
    """

    def __cinit__(self, int file_index, int line, int column, list value):
        self.value = value

    def __reduce__(self):
        return (
            SequenceNode.__new__,
            (SequenceNode, self.file_index, self.line, self.column, self.value),
        )

    def __iter__(self):
        return iter(self.value)

    def __len__(self):
        return len(self.value)

    def __reversed__(self):
        return reversed(self.value)

    def __setitem__(self, int key, object value):
        cdef Node old_value

        if type(value) in [MappingNode, ScalarNode, SequenceNode]:
            self.value[key] = value
        else:
            node = __create_node_recursive(value, self)

            # FIXME: Do we really want to override provenance?
            # See __setitem__ on 'MappingNode' for more context
            old_value = self.value[key]
            if old_value:
                node.file_index = old_value.file_index
                node.line = old_value.line
                node.column = old_value.column

            self.value[key] = node

    #############################################################
    #                       Public Methods                      #
    #############################################################

    cpdef void append(self, object value):
        """append(value)

        Append the given object to the sequence.

        Args:
            value (object): the value to append to the list. This can either be:

                                - a :class:`Node`
                                - a :class:`int`, :class:`bool`, :class:`str`, :class:`None`,
                                  :class:`dict` or :class:`list`. In which case, this will be
                                  converted into a :class:`Node` beforehand

        Raises:
            :class:`TypeError`: when the value cannot be converted to a :class:`Node`
        """
        if type(value) in [MappingNode, ScalarNode, SequenceNode]:
            self.value.append(value)
        else:
            node = __create_node_recursive(value, self)
            self.value.append(node)

    cpdef list as_str_list(self):
        """Get the values of the sequence as a list of strings.

        Raises:
            :class:`buildstream._exceptions.LoadError`: if the sequence contains more than
                                                        :class:`ScalarNode`

        Returns:
            :class:`list`: the content of the sequence as a list of strings
        """
        return [node.as_str() for node in self.value]

    cpdef MappingNode mapping_at(self, int index):
        """mapping_at(index)

        Retrieve the entry at `index` as a :class:`.MappingNode`.

        Args:
            index (int): index for which to get the value

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.MappingNode`
           :class:`IndexError`: if no value exists at this index

        Returns:
            :class:`.MappingNode`: the value at `index`
        """
        value = self.value[index]

        if type(value) is not MappingNode:
            provenance = self.get_provenance()
            path = ["[{}]".format(p) for p in provenance._toplevel._find(self)] + ["[{}]".format(index)]
            raise LoadError("{}: Value of '{}' is not of the expected type '{}'"
                            .format(provenance, path, MappingNode.__name__),
                            LoadErrorReason.INVALID_DATA)
        return value

    cpdef Node node_at(self, int index, list allowed_types = None):
        """node_at(index, allowed_types=None)

        Retrieve the entry at `index` as a :class:`.Node`.

        This is useful if you have configuration that can be either a :class:`.ScalarNode` or
        a :class:`.MappingNode` for example.

        This method will validate that the value is indeed exactly one of those types (not a subclass)
        and raise an exception accordingly.

        Args:
            index (int): index for which to get the value
            allowed_types (list): list of valid subtypes of :class:`.Node` that are valid return values.
                                  If this is `None`, no checks are done on the return value.

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `index` is not of one of the
                                                       expected types
           :class:`IndexError`: if no value exists at this index

        Returns:
            :class:`.Node`: the value at `index`
        """
        cdef value = self.value[index]

        if allowed_types and type(value) not in allowed_types:
            provenance = self.get_provenance()
            raise LoadError("{}: Value of '{}' is not one of the following: {}.".format(
                            provenance, index, ", ".join(allowed_types)),
                            LoadErrorReason.INVALID_DATA)

        return value

    cpdef ScalarNode scalar_at(self, int index):
        """scalar_at(index)

        Retrieve the entry at `index` as a :class:`.ScalarNode`.

        Args:
            index (int): index for which to get the value

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.ScalarNode`
           :class:`IndexError`: if no value exists at this index

        Returns:
            :class:`.ScalarNode`: the value at `index`
        """
        value = self.value[index]

        if type(value) is not ScalarNode:
            provenance = self.get_provenance()
            path = ["[{}]".format(p) for p in provenance._toplevel._find(self)] + ["[{}]".format(index)]
            raise LoadError("{}: Value of '{}' is not of the expected type '{}'"
                            .format(provenance, path, ScalarNode.__name__),
                            LoadErrorReason.INVALID_DATA)
        return value

    cpdef SequenceNode sequence_at(self, int index):
        """sequence_at(index)

        Retrieve the entry at `index` as a :class:`.SequenceNode`.

        Args:
            index (int): index for which to get the value

        Raises:
           :class:`buildstream._exceptions.LoadError`: if the value at `key` is not a
                                                       :class:`.SequenceNode`
           :class:`IndexError`: if no value exists at this index

        Returns:
            :class:`.SequenceNode`: the value at `index`
        """
        value = self.value[index]

        if type(value) is not SequenceNode:
            provenance = self.get_provenance()
            path = ["[{}]".format(p) for p in provenance.toplevel._find(self)] + ["[{}]".format(index)]
            raise LoadError("{}: Value of '{}' is not of the expected type '{}'"
                            .format(provenance, path, SequenceNode.__name__),
                            LoadErrorReason.INVALID_DATA)

        return value

    #############################################################
    #               Public Methods implementations              #
    #############################################################

    cpdef SequenceNode clone(self):
        cdef list copy = []
        cdef Node entry

        for entry in self.value:
            copy.append(entry.clone())

        return SequenceNode.__new__(SequenceNode, self.file_index, self.line, self.column, copy)

    cpdef object strip_node_info(self):
        cdef Node value
        return [value.strip_node_info() for value in self.value]

    #############################################################
    #              Private Methods implementations              #
    #############################################################

    cpdef void _assert_fully_composited(self) except *:
        cdef Node value
        for value in self.value:
            value._assert_fully_composited()

    #############################################################
    #                     Protected Methods                     #
    #############################################################

    cdef void _compose_on(self, str key, MappingNode target, list path) except *:
        # List clobbers anything list-like
        cdef Node target_value = target.value.get(key)

        if not (target_value is None or
                type(target_value) is SequenceNode or
                target_value._is_composite_list()):
            raise __CompositeError(path,
                                  "{}: List cannot overwrite {} at: {}"
                                  .format(self.get_provenance(),
                                          key,
                                          target_value.get_provenance()))
        # Looks good, clobber it
        target.value[key] = self

    cdef bint _is_composite_list(self) except *:
        return False

    cdef bint _walk_find(self, Node target, list path) except *:
        cdef int i
        cdef Node v

        if self._shares_position_with(target):
            return True

        for i, v in enumerate(self.value):
            path.append(i)
            if v._walk_find(target, path):
                return True
            del path[-1]

        return False


# Returned from Node.get_provenance
cdef class ProvenanceInformation:
    """Represents the location of a YAML node in a file.

    This can effectively be used as a pretty print to display those information in
    errors consistently.

    You can retrieve this information for a :class:`Node` with
    :func:`Node.get_provenance() <buildstream.node.Node.get_provenance()>`
    """

    def __init__(self, Node nodeish):
        cdef __FileInfo fileinfo

        self._node = nodeish
        if (nodeish is None) or (nodeish.file_index == _SYNTHETIC_FILE_INDEX):
            self._filename = ""
            self._shortname = ""
            self._displayname = ""
            self._line = 1
            self._col = 0
            self._toplevel = None
            self._project = None
        else:
            fileinfo = <__FileInfo> __FILE_LIST[nodeish.file_index]
            self._filename = fileinfo.filename
            self._shortname = fileinfo.shortname
            self._displayname = fileinfo.displayname
            # We add 1 here to convert from computerish to humanish
            self._line = nodeish.line + 1
            self._col = nodeish.column
            self._toplevel = fileinfo.toplevel
            self._project = fileinfo.project
        self._is_synthetic = (self._filename == '') or (self._col < 0)

    # Convert a Provenance to a string for error reporting
    def __str__(self):
        if self._is_synthetic:
            return "{} [synthetic node]".format(self._displayname)
        else:
            return "{} [line {:d} column {:d}]".format(self._displayname, self._line, self._col)


#############################################################
#                BuildStream Private methods                #
#############################################################

# Purely synthetic nodes will have _SYNTHETIC_FILE_INDEX for the file number, have line number
# zero, and a negative column number which comes from inverting the next value
# out of this counter.  Synthetic nodes created with a reference node will
# have a file number from the reference node, some unknown line number, and
# a negative column number from this counter.
cdef int _SYNTHETIC_FILE_INDEX = -1

# _assert_symbol_name()
#
# A helper function to check if a loaded string is a valid symbol
# name and to raise a consistent LoadError if not. For strings which
# are required to be symbols.
#
# Args:
#    symbol_name (str): The loaded symbol name
#    purpose (str): The purpose of the string, for an error message
#    ref_node (Node): The node of the loaded symbol, or None
#    allow_dashes (bool): Whether dashes are allowed for this symbol
#
# Raises:
#    LoadError: If the symbol_name is invalid
#
# Note that dashes are generally preferred for variable names and
# usage in YAML, but things such as option names which will be
# evaluated with jinja2 cannot use dashes.
def _assert_symbol_name(str symbol_name, str purpose, *, Node ref_node=None, bint allow_dashes=True):
    cdef str valid_chars = string.digits + string.ascii_letters + '_'
    if allow_dashes:
        valid_chars += '-'

    cdef bint valid = True
    if not symbol_name:
        valid = False
    elif any(x not in valid_chars for x in symbol_name):
        valid = False
    elif symbol_name[0] in string.digits:
        valid = False

    if not valid:
        detail = "Symbol names must contain only alphanumeric characters, " + \
                 "may not start with a digit, and may contain underscores"
        if allow_dashes:
            detail += " or dashes"

        message = "Invalid symbol name for {}: '{}'".format(purpose, symbol_name)
        if ref_node:
            provenance = ref_node.get_provenance()
            if provenance is not None:
                message = "{}: {}".format(provenance, message)

        raise LoadError(message, LoadErrorReason.INVALID_SYMBOL_NAME, detail=detail)


# _create_new_file(filename, shortname, displayname, toplevel, project)
#
# Create a new synthetic file and return it's index in the `._FILE_LIST`.
#
# Args:
#   filename (str): the name to give to the file
#   shortname (str): a shorter name used when showing information on the screen
#   displayname (str): the name to give when reporting errors
#   project (object): project with which to associate the current file (when dealing with junctions)
#
# Returns:
#   (int): the index in the `._FILE_LIST` that identifies the new file
#
cdef Py_ssize_t _create_new_file(str filename, str shortname, str displayname, object project):
    cdef Py_ssize_t file_number = len(__FILE_LIST)
    __FILE_LIST.append(__FileInfo(filename, shortname, displayname, None, project))

    return file_number


# _set_root_node_for_file(file_index, contents)
#
# Set the root node for the given file
#
# Args:
#   file_index (int): the index in the `._FILE_LIST` for the file for which to set the root
#   contents (.MappingNode): node that should be the root for the file
#
cdef void _set_root_node_for_file(Py_ssize_t file_index, MappingNode contents) except *:
    cdef __FileInfo f_info

    if file_index != _SYNTHETIC_FILE_INDEX:
        f_info = <__FileInfo> __FILE_LIST[file_index]
        f_info.toplevel = contents


# _new_synthetic_file()
#
# Create a new synthetic mapping node, with an associated file entry
# (in _FILE_LIST) such that later tracking can correctly determine which
# file needs writing to in order to persist the changes.
#
# Args:
#    filename (str): The name of the synthetic file to create
#    project (Project): The optional project to associate this synthetic file with
#
# Returns:
#    (Node): An empty YAML mapping node, whose provenance is to this new
#            synthetic file
#
def _new_synthetic_file(str filename, object project=None):
    cdef Py_ssize_t file_index = len(__FILE_LIST)
    cdef Node node = MappingNode.__new__(MappingNode, file_index, 0, 0, {})

    __FILE_LIST.append(__FileInfo(filename,
                                  filename,
                                  "<synthetic {}>".format(filename),
                                  node,
                                  project))
    return node


# _reset_global_state()
#
# This resets the global variables __FILE_LIST and __counter to their initial
# state. This is used by the test suite to improve isolation between tests
# running in the same process.
#
def _reset_global_state():
    global __FILE_LIST, __counter
    __FILE_LIST = []
    __counter = 0


# _get_state_for_pickling()
#
# This gets the global variables necessary to preserve in a child process when
# e.g. running a ChildJob. Things that are pickled from the parent process to
# the child process will expect this module to be in the same state as in the
# parent.
#
# Returns:
#    (object): The state to supply to a call of _get_state_for_pickling().
#
def _get_state_for_pickling():
    return __FILE_LIST, __counter


# _set_state_from_pickling()
#
# This restores the global variables saved from _get_state_for_pickling(). See
# that function for more details.
#
# Args:
#    state (object): The result of calling _get_state_for_pickling().
#
def _set_state_from_pickling(state):
    global __FILE_LIST, __counter
    __FILE_LIST, __counter = state


#############################################################
#                 Module local helper Methods               #
#############################################################

# File name handling
cdef list __FILE_LIST = []

# synthetic counter for synthetic nodes
cdef int __counter = 0


class __CompositeError(Exception):
    def __init__(self, path, message):
        super().__init__(message)
        self.path = path
        self.message = message


# Metadata container for a yaml toplevel node.
#
# This class contains metadata around a yaml node in order to be able
# to trace back the provenance of a node to the file.
#
cdef class __FileInfo:

    cdef str filename, shortname, displayname
    cdef MappingNode toplevel,
    cdef object project

    def __init__(self, str filename, str shortname, str displayname, MappingNode toplevel, object project):
        self.filename = filename
        self.shortname = shortname
        self.displayname = displayname
        self.toplevel = toplevel
        self.project = project


cdef int __next_synthetic_counter():
    global __counter
    __counter -= 1
    return __counter


cdef Node __create_node_recursive(object value, Node ref_node):
    cdef value_type = type(value)

    if value_type is list:
        node = __new_node_from_list(value, ref_node)
    elif value_type in [int, str, bool]:
        node = ScalarNode.__new__(ScalarNode, ref_node.file_index, ref_node.line, __next_synthetic_counter(), value)
    elif value_type is dict:
        node = __new_node_from_dict(value, ref_node)
    else:
        raise TypeError(
            "Unable to assign a value of type {} to a Node.".format(value_type))

    return node


# _new_node_from_dict()
#
# Args:
#   indict (dict): The input dictionary
#   ref_node (Node): The dictionary to take as reference for position
#
# Returns:
#   (Node): A new synthetic YAML tree which represents this dictionary
#
cdef Node __new_node_from_dict(dict indict, Node ref_node):
    cdef MappingNode ret = MappingNode.__new__(
        MappingNode, ref_node.file_index, ref_node.line, __next_synthetic_counter(), {})
    cdef str k

    for k, v in indict.items():
        ret.value[k] = __create_node_recursive(v, ref_node)

    return ret


# Internal function to help new_node_from_dict() to handle lists
cdef Node __new_node_from_list(list inlist, Node ref_node):
    cdef SequenceNode ret = SequenceNode.__new__(
        SequenceNode, ref_node.file_index, ref_node.line, __next_synthetic_counter(), [])

    for v in inlist:
        ret.value.append(__create_node_recursive(v, ref_node))

    return ret
