Returns ``True`` if the given `node` is an ancestor of the given
            `subject` node, ``False`` otherwise. This method uses the
            :attr:`path` virtual field, and so does not perform any query.

            :param node: the :class:`CTENode' for which to determine whether it
                is an ancestor of the `subject`.

            :param subject: the :class:`CTENode` for which to determine whether
                one of its ancestors is the `node`.

            :returns: ``True`` if `node` is an ancestor of `subject`, ``False``
                otherwise.

def is_ancestor_of(self, node, subject):
        """ Returns ``True`` if the given `node` is an ancestor of the given
            `subject` node, ``False`` otherwise. This method uses the
            :attr:`path` virtual field, and so does not perform any query.

            :param node: the :class:`CTENode' for which to determine whether it
                is an ancestor of the `subject`.

            :param subject: the :class:`CTENode` for which to determine whether
                one of its ancestors is the `node`.

            :returns: ``True`` if `node` is an ancestor of `subject`, ``False``
                otherwise.
        """
        # We will need to use the path virtual field, so ensure it exists.
        self._ensure_virtual_fields(node)

        # Convenience check so is_ancestor_of can be combined with methods
        # returning nodes without the caller having to worry about a None
        # subject.
        if subject is None:
            return False

        # Optimization: a node will never be an ancestor of a root node.
        if getattr(subject, subject._cte_node_depth) == 1:
            return False

        # The path will either be an index of primitives, or an encoding of an
        # array.
        if type(getattr(node, node._cte_node_path)) == list:
            # We can slice with -1 because we know that depth > 1 from above.
            return node.id in getattr(subject, subject._cte_node_path)[0:-1]
        else:
            # Search for node id up to the penultimate entry in the path of the
            # subject, meaning we ignore the end of the path consisting of:
            # a) the ending closing curly brace,
            # b) the length of the subject id, and
            # c) the separator character,
            # therefore we look for a match ending at the length of the
            # subject's id string plus two (so negative index length minus two).
            _path = getattr(subject, subject._cte_node_path)
            return _path[: -len(str(subject.id)) - 2].index(str(node.id)) > 0