This function takes configuration data and a validation scheme
        then walk the configuration tree validating the configuraton data agenst
        the scheme provided. Will raise error on failure otherwise return None.

        Usage::
            >>> self._walk_tree(
            >>>    OrderedDict([('root', config_data)]),
            >>>    registries,
            >>>    REGISTRIES_SCHEME
            >>> )


        :param ancestors: A :OrderedDict:, The first element of the dict must be 'root'.
        :param data: The data that needs to be validated agents the scheme.
        :param scheme: A :dict:, The scheme defining the validations.
        :param property_name: A :string:, This is the name of the data getting validated.
        :param prefix:
        :rtype: :None: will raise error if a validation fails.

def _walk_tree(self, data, scheme, ancestors=None, property_name=None, prefix=None):
        """ This function takes configuration data and a validation scheme
        then walk the configuration tree validating the configuraton data agenst
        the scheme provided. Will raise error on failure otherwise return None.

        Usage::
            >>> self._walk_tree(
            >>>    OrderedDict([('root', config_data)]),
            >>>    registries,
            >>>    REGISTRIES_SCHEME
            >>> )


        :param ancestors: A :OrderedDict:, The first element of the dict must be 'root'.
        :param data: The data that needs to be validated agents the scheme.
        :param scheme: A :dict:, The scheme defining the validations.
        :param property_name: A :string:, This is the name of the data getting validated.
        :param prefix:
        :rtype: :None: will raise error if a validation fails.
        """
        if property_name is None:
            property_name = 'root'
            # hack until i add this to references
            # reorder validates putting required first.  If the data doesn't exist there is no need to continue.
            order = ['registries'] + [key for key in scheme.keys() if key not in ('registries',)]
            scheme = OrderedDict(sorted(scheme.items(), key=lambda x: order.index(x[0])))

        if data is None:
            return

        elif not isinstance(property_name, six.string_types):
            raise TypeError('property_name must be a string.')

        ancestors = self._update_ancestors(data, property_name, ancestors)
        if isinstance(ancestors, OrderedDict):
            if list(ancestors)[0] != 'root':
                raise LookupError('root must be the first item in ancestors.')
        else:
            raise TypeError('ancestors must be an OrderedDict. {0} was passed'.format(type(ancestors)))

        if not isinstance(scheme, dict):
            raise TypeError('scheme must be a dict. {0} was passed.'.format(type(scheme)))
        scheme = self._update_scheme(scheme, ancestors)

        if property_name is not None and data:
            data = self._get_cascading_attr(
                property_name, *list(ancestors)[1:]
            ) if scheme.get('cascading', False) else data

        for err in self.__execute_validations(scheme.get('is', {}), data, property_name, ancestors, prefix=prefix):
            if err:
                raise err
            else:
                self._create_attr(property_name, data, ancestors)

        self.__validate_unrecognized_values(scheme, data, ancestors, prefix)

        self.__populate_scheme_references(scheme, property_name)

        self.__validate_config_properties(scheme, data, ancestors, prefix)