<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def lookup_data(self, lookup, data):
 """ Given a lookup string, attempts to descend through nested data looking for the value. Can work with either dictionary-alikes or objects (or any combination of those). Lookups should be a string. If it is a dotted path, it will be split on ``.`` & it will traverse through to find the final value. If not, it will simply attempt to find either a key or attribute of that name & return it. Example:: 'message' 'hello' 'daniel' """

        value = data
        parts = lookup.split('.')

        if not parts or not parts[0]:
            return value

        part = parts[0]
        remaining_lookup = '.'.join(parts[1:])

        if callable(getattr(data, 'keys', None)) and hasattr(data, '__getitem__'):
            # Dictionary enough for us.
            value = data[part]
        elif data is not None:
            # Assume it's an object.
            value = getattr(data, part)

        # Call if it's callable except if it's a Django DB manager instance
        #   We check if is a manager by checking the db_manager (duck typing)
        if callable(value) and not hasattr(value, 'db_manager'):
            value = value()

        if not remaining_lookup:
            return value

        # There's more to lookup, so dive in recursively.
        return self.lookup_data(remaining_lookup, value)