# Buggy code
def display(self, ret, indent, prefix, out):
    """
    Recursively iterate down through data structures to determine output
    """
    if isinstance(ret, bytes):
        try:
            ret = salt.utils.stringutils.to_unicode(ret)
        except UnicodeDecodeError:
            # ret contains binary data that can't be decoded
            pass

    if ret is None or ret is True or ret is False:
        out.append(self.ustring(indent, self.LIGHT_YELLOW, ret, prefix=prefix))
    # Number includes all python numbers types
    #  (float, int, long, complex, ...)
    # use repr() to get the full precision also for older python versions
    # as until about python32 it was limited to 12 digits only by default
    elif isinstance(ret, Number):
        out.append(self.ustring(indent, self.LIGHT_YELLOW, repr(ret), prefix=prefix))
    elif isinstance(ret, six.string_types):
        first_line = True
        for line in ret.splitlines():
            if self.strip_colors:
                line = salt.output.strip_esc_sequence(line)
            line_prefix = " " * len(prefix) if not first_line else prefix
            out.append(self.ustring(indent, self.GREEN, line, prefix=line_prefix))
            first_line = False
    elif isinstance(ret, (list, tuple)):
        color = self.GREEN
        if self.retcode != 0:
            color = self.RED
        for ind in ret:
            if isinstance(ind, (list, tuple, dict)):
                out.append(self.ustring(indent, color, "|_"))
                prefix = "" if isinstance(ind, dict) else "- "
                self.display(ind, indent + 2, prefix, out)
            else:
                self.display(ind, indent, "- ", out)
    elif isinstance(ret, dict):
        if indent:
            color = self.CYAN
            if self.retcode != 0:
                color = self.RED
            out.append(self.ustring(indent, color, "----------"))

        # respect key ordering of ordered dicts
        if isinstance(ret, salt.utils.odict.OrderedDict):
            keys = ret.keys()
        else:
            keys = sorted(ret)
        color = self.CYAN
        if self.retcode != 0:
            color = self.RED
        for key in keys:
            val = ret[key]
            out.append(self.ustring(indent, color, key, suffix=":", prefix=prefix))
            self.display(val, indent + 4, "", out)
    return out


# Traceback (AttributeError)
ID: pip-deps
Function: pip.installed
Name: python
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/state.py", line 1913, in call
**cdata['kwargs'])
File "/usr/lib/python2.7/site-packages/salt/loader.py", line 1898, in wrapper
return f(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/states/pip_state.py", line 910, in installed
if pkg_name.lower() in already_installed_packages:
AttributeError: 'NoneType' object has no attribute 'lower'
Started: 13:14:27.731677
Duration: 1944.946 ms
Changes:

# Fixed code
def display(self, ret, indent, prefix, out):
    """
    Recursively iterate down through data structures to determine output
    """
    if isinstance(ret, bytes):
        try:
            ret = salt.utils.stringutils.to_unicode(ret)
        except UnicodeDecodeError:
            # ret contains binary data that can't be decoded
            pass

    if ret is None or ret is True or ret is False:
        out.append(self.ustring(indent, self.LIGHT_YELLOW, ret, prefix=prefix))
    # Number includes all python numbers types
    #  (float, int, long, complex, ...)
    # use repr() to get the full precision also for older python versions
    # as until about python32 it was limited to 12 digits only by default
    elif isinstance(ret, Number):
        out.append(self.ustring(indent, self.LIGHT_YELLOW, repr(ret), prefix=prefix))
    elif isinstance(ret, six.string_types):
        first_line = True
        for line in ret.splitlines():
            if self.strip_colors:
                line = salt.output.strip_esc_sequence(line)
            line_prefix = " " * len(prefix) if not first_line else prefix
            out.append(self.ustring(indent, self.GREEN, line, prefix=line_prefix))
            first_line = False
    elif isinstance(ret, (list, tuple)):
        color = self.GREEN
        if self.retcode != 0:
            color = self.RED
        for ind in ret:
            if isinstance(ind, (list, tuple, Mapping)):
                out.append(self.ustring(indent, color, "|_"))
                prefix = "" if isinstance(ind, Mapping) else "- "
                self.display(ind, indent + 2, prefix, out)
            else:
                self.display(ind, indent, "- ", out)
    elif isinstance(ret, Mapping):
        if indent:
            color = self.CYAN
            if self.retcode != 0:
                color = self.RED
            out.append(self.ustring(indent, color, "----------"))

        # respect key ordering of ordered dicts
        if isinstance(ret, salt.utils.odict.OrderedDict):
            keys = ret.keys()
        else:
            keys = sorted(ret)
        color = self.CYAN
        if self.retcode != 0:
            color = self.RED
        for key in keys:
            val = ret[key]
            out.append(self.ustring(indent, color, key, suffix=":", prefix=prefix))
            self.display(val, indent + 4, "", out)
    return out