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