def _cast()

in api/bottle.py [0:0]


    def _cast(self, out, peek=None):
        """Try to convert the parameter into something WSGI compatible and set
        correct HTTP headers when possible.
        Support: False, str, unicode, dict, HTTPResponse, HTTPError, file-like,
        iterable of strings and iterable of unicodes
        """

        # Empty output is done here
        if not out:
            if "Content-Length" not in response:
                response["Content-Length"] = 0
            return []
        # Join lists of byte or unicode strings. Mixed lists are NOT supported
        if isinstance(out, (tuple, list)) and isinstance(out[0], (bytes, unicode)):
            out = out[0][0:0].join(out)  # b'abc'[0:0] -> b''
        # Encode unicode strings
        if isinstance(out, unicode):
            out = out.encode(response.charset)
        # Byte Strings are just returned
        if isinstance(out, bytes):
            if "Content-Length" not in response:
                response["Content-Length"] = len(out)
            return [out]
        # HTTPError or HTTPException (recursive, because they may wrap anything)
        # TODO: Handle these explicitly in handle() or make them iterable.
        if isinstance(out, HTTPError):
            out.apply(response)
            out = self.error_handler.get(out.status_code, self.default_error_handler)(
                out
            )
            return self._cast(out)
        if isinstance(out, HTTPResponse):
            out.apply(response)
            return self._cast(out.body)

        # File-like objects.
        if hasattr(out, "read"):
            if "wsgi.file_wrapper" in request.environ:
                return request.environ["wsgi.file_wrapper"](out)
            elif hasattr(out, "close") or not hasattr(out, "__iter__"):
                return WSGIFileWrapper(out)

        # Handle Iterables. We peek into them to detect their inner type.
        try:
            iout = iter(out)
            first = next(iout)
            while not first:
                first = next(iout)
        except StopIteration:
            return self._cast("")
        except HTTPResponse as E:
            first = E
        except (KeyboardInterrupt, SystemExit, MemoryError):
            raise
        except Exception as error:
            if not self.catchall:
                raise
            first = HTTPError(500, "Unhandled exception", error, format_exc())

        # These are the inner types allowed in iterator or generator objects.
        if isinstance(first, HTTPResponse):
            return self._cast(first)
        elif isinstance(first, bytes):
            new_iter = itertools.chain([first], iout)
        elif isinstance(first, unicode):

            def encoder(x):
                return x.encode(response.charset)

            new_iter = imap(encoder, itertools.chain([first], iout))
        else:
            msg = "Unsupported response type: %s" % type(first)
            return self._cast(HTTPError(500, msg))
        if hasattr(out, "close"):
            new_iter = _closeiter(new_iter, out.close)
        return new_iter