def _update_recurse(self, endpoint=None, max_depth=3, data=None):
     """
     Update data about remote system
     :param endpoint: Endpoint from which recursive update starts
     :param max_depth: Maximum depth for recursive update. This
     parameter is essential to prevent reference loop
     :param data: Common dictionary which stores collected data on all
     levels of recursion
     :return: Dictionary with endpoints as keys and fresh data stored
     beneath such endpoint as dictionary value
     """
     if not endpoint:
         endpoint = self.endpoint
     if endpoint[-1] == '/':
         endpoint = endpoint[:-1]
     if not data:
         data = {}
     # LOGGER.info(f"Updating data from {endpoint} with depth {max_depth}")
     if max_depth == 0 or endpoint in data.keys():
         return data
     #print(endpoint)
     resp = self.get_data(endpoint)
     data[endpoint] = resp
     if isinstance(resp, dict):
         for key, value in resp.items():
             if key == '@odata.id':
                 if value == endpoint:
                     continue
                 data = self._update_recurse(value, max_depth - 1, data)
             if utils.is_iterable(value):
                 endpoints = RedfishTools._endpoint_inception(value)
                 for endp in endpoints:
                     data = self._update_recurse(endp, max_depth - 1, data)
     return data
    def _search_recurse(self, name, structure=None, i=0):
        """
        Searches for `name` iterable object
        :param name: Name to search
        :param structure: Iterable structure to search in
        :param all_data: Common list with all collected pairs
        (key, value) passed through all levels of recursion
        :param i: just for debugging
        :return: List with all collected pairs
        (key, value) containing `name`
        """
        tuple_list = []

        if isinstance(structure, dict):
            for key, value in structure.items():
                if utils.is_iterable(value):
                    tuples = self._search_recurse(name, value, i + 1)
                    if tuples:
                        prefixed_tuples = utils.prefix_tuples(key, tuples)
                        tuple_list += prefixed_tuples
                if name in (key, value):
                    tuple_list.append((key, value))
        elif isinstance(structure, list):
            for elem in structure:
                tuple_list += self._search_recurse(name, elem, i + 1)
        return tuple_list
 def _get_basic_info(self, data=None):
     self._fetch()
     return_data = {}
     if not data:
         data = self.data
     for key, value in data.items():
         if not utils.is_iterable(value):
             return_data[key] = value
     return self.filter_data(return_data)
    def snake_case_dict(self, data):
        "Converts dictionary keys from CamelCase to snake_case"
        if not utils.is_iterable(data):
            return data

        # iterate over list and check them
        if isinstance(data, list):
            new_data = [
                self.snake_case_dict(elem)
                for elem in data]
            return new_data

        # such element is in this dictionary
        new_data = {}
        for key, value in data.items():
            new_key = underscore(key).replace(' ', '_')
            new_data[new_key] = self.snake_case_dict(value)
        return new_data
    def _get_dict_containing(self, name, data=None, misses=5):
        """
        finds a dictionary containing 'name' as key or value in data
        stored locally retrieved earlier from Redfish connector
        :param name: name to search in 'self.data'
        :return: dictionary containing name as key or value
        """

        # starting point - default argument
        if data is None:
            data = self.data

        # we went too deep or cannot iterate over data
        if not misses or not utils.is_iterable(data):
            return None

        found = None

        # iterate over list and check them
        if isinstance(data, list):
            for elem in data:
                found = self._get_dict_containing(name, elem, misses)
                if found:
                    return found
            return None

        # such element is in this dictionary
        for key, value in data.items():
            try:
                if name in key or name in value:
                    return data
            except TypeError:
                pass

        # if not found in current dictionary, we search through curent dict values
        for value in data.values():
            found = self._get_dict_containing(name, value, misses-1)
            if found:
                return found

        return None
    def filter_data(data, dot_replacement='-'):
        "Removes all odata entries and dots from data"
        if not utils.is_iterable(data):
            return data

        new_data = None
        if isinstance(data, list):
            new_data = []
            for elem in data:
                new_elem = RedfishTools.filter_data(elem)
                if new_elem:
                    new_data.append(new_elem)
        else:
            new_data = {}
            for key, value in data.items():
                if 'odata' not in key:
                    new_value = RedfishTools.filter_data(value)
                    if new_value:
                        key = key.replace('.', dot_replacement)
                        new_data[key] = new_value
        return new_data
 def _endpoint_inception(iterable, max_depth=3, endpoints=None):
     """
     We need to go deeper. Aka extract_endpoints().
     Search for every endpoint reference stored in iterable
     (list, dict) object.
     """
     if not endpoints:
         endpoints = []
     if isinstance(iterable, list):
         for elem in iterable:
             endpoints = RedfishTools._endpoint_inception(elem, max_depth - 1, endpoints)
     if isinstance(iterable, dict):
         for key, value in iterable.items():
             if utils.is_iterable(value):
                 endpoints = RedfishTools._endpoint_inception(
                     value,
                     max_depth - 1,
                     endpoints)
             elif key == '@odata.id':
                 endp = value.split('#')[0]
                 if endp not in endpoints:
                     endpoints.append(endp)
     return endpoints