# Path: bustard/http.py
# class Headers(MultiDict):
# 
#     def add(self, key, value):
#         key = to_text(to_header_key(key))
#         if isinstance(value, (tuple, list)):
#             self.data.setdefault(key, []).extend(map(to_text, value))
#         else:
#             self.data.setdefault(key, []).append(to_text(value))
# 
#     def set(self, key, value):
#         self.__setitem__(key, value)
# 
#     def get_all(self, key):
#         key = to_header_key(key)
#         return self.data[key]
# 
#     @classmethod
#     def from_list(cls, headers_list):
#         headers = cls()
#         for (k, v) in headers_list:
#             headers.add(k, v)
#         return headers
# 
#     def to_list(self):
#         return [
#             (k, v)
#             for k, values in self.to_dict().items()
#             for v in values
#         ]
# 
#     def __getitem__(self, key):
#         key = to_header_key(key)
#         return super(Headers, self).__getitem__(key)
# 
#     def __setitem__(self, key, value):
#         key = to_text(to_header_key(key))
#         if isinstance(value, (list, tuple)):
#             value = list(map(to_text, value))
#         else:
#             value = to_text(value)
#         super(Headers, self).__setitem__(key, value)
# 
# class Response:
# 
#     def __init__(self, content=b'', status_code=200,
#                  content_type='text/html; charset=utf-8',
#                  headers=None):
#         self._content = content
#         self._status_code = status_code
#         _headers = headers or {}
#         _headers.setdefault('Content-Type', content_type)
#         if isinstance(_headers, Headers):
#             self._headers = _headers
#         else:
#             self._headers = Headers(_headers)
#         self._cookies = SimpleCookie()
#         self._load_cookies_from_headers()
# 
#     def _load_cookies_from_headers(self):
#         cookies = self._headers.to_dict().pop('Set-Cookie', [])
#         for cookie in cookies:
#             self._cookies.load(cookie)
# 
#     @property
#     def content(self):
#         return self._content
# 
#     @content.setter
#     def content(self, value):
#         if isinstance(value, str):
#             value = value.encode('utf-8')
#         self._content = value
#     body = data = content
# 
#     def get_data(self):
#         return self._content
# 
#     @property
#     def content_type(self, value):
#         return self.headers.get('Content-Type', '')
# 
#     @content_type.setter
#     def content_type(self, value):
#         self.headers['Content-Type'] = value
# 
#     @property
#     def content_length(self):
#         return int(self.headers.get('Content-Length', '0'))
# 
#     @property
#     def status_code(self):
#         return self._status_code
# 
#     @status_code.setter
#     def status_code(self, value):
#         self._status_code = value
# 
#     @property
#     def status(self):
#         code = self._status_code
#         return response_status_string(code)
# 
#     @property
#     def headers(self):
#         return self._headers
# 
#     @headers.setter
#     def headers(self, value):
#         self._headers = Headers(value)
# 
#     @property
#     def content_type(self):
#         return self._headers.get('Content-Type', '')
# 
#     @content_type.setter
#     def content_type(self, value):
#         self._headers['Content-Type'] = value
# 
#     @property
#     def cookies(self):
#         return self._cookies
# 
#     def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
#                    domain=None, secure=False, httponly=False):
#         cookie = cookie_dump(
#             key, value=value, max_age=max_age, expires=expires, path=path,
#             domain=domain, secure=secure, httponly=httponly
#         )
#         self._cookies.load(cookie)
# 
#     def delete_cookie(self, key, max_age=0,
#                       expires='Thu, 01-Jan-1970 00:00:00 GMT'):
#         self.set_cookie(key, value='', max_age=max_age, expires=expires)
# 
#     @property
#     def headers_list(self):
#         # normal headers
#         headers_list = list(self.headers.to_list())
# 
#         # set-cookies
#         headers_list.extend(
#             ('Set-Cookie', value.OutputString())
#             for value in self.cookies.values()
#         )
#         return headers_list
# 
#     def json(self):
#         return json.loads(to_text(self.data))
# 
#     def __repr__(self):
#         return '<{} [{}]>'.format(self.__class__.__name__, self.status_code)
# 
# Path: bustard/utils.py
# def to_text(st, encoding='utf-8'):
#     if isinstance(st, str):
#         return st
#     elif isinstance(st, collections.ByteString):
#         return st.decode(encoding)
#     else:
#         return str(st)
# 
# def to_bytes(bt, encoding='utf-8'):
#     if isinstance(bt, collections.ByteString):
#         return bt
#     elif isinstance(bt, str):
#         return bt.encode(encoding)
#     else:
#         return bytes(bt)


import collections
import mimetypes
import itertools
import io
import random
import sys
import time
import urllib
from .http import Headers, Response
from .utils import to_text, to_bytes
# -*- coding: utf-8 -*-



def run_wsgi_app(app, environ):

    response = []
    buffer = []

    def start_response(status, headers, exc_info=None):
        if exc_info is not None:
            raise (exc_info[0], exc_info[1], exc_info[2])
        response[:] = [status, headers]
        return buffer.append

    app_rv = app(environ, start_response)
    app_iter = itertools.chain(buffer, app_rv)


# Path: bustard/http.py
# class Headers(MultiDict):
# 
#     def add(self, key, value):
#         key = to_text(to_header_key(key))
#         if isinstance(value, (tuple, list)):
#             self.data.setdefault(key, []).extend(map(to_text, value))
#         else:
#             self.data.setdefault(key, []).append(to_text(value))
# 
#     def set(self, key, value):
#         self.__setitem__(key, value)
# 
#     def get_all(self, key):
#         key = to_header_key(key)
#         return self.data[key]
# 
#     @classmethod
#     def from_list(cls, headers_list):
#         headers = cls()
#         for (k, v) in headers_list:
#             headers.add(k, v)
#         return headers
# 
#     def to_list(self):
#         return [
#             (k, v)
#             for k, values in self.to_dict().items()
#             for v in values
#         ]
# 
#     def __getitem__(self, key):
#         key = to_header_key(key)
#         return super(Headers, self).__getitem__(key)
# 
#     def __setitem__(self, key, value):
#         key = to_text(to_header_key(key))
#         if isinstance(value, (list, tuple)):
#             value = list(map(to_text, value))
#         else:
#             value = to_text(value)
#         super(Headers, self).__setitem__(key, value)
# 
# class Response:
# 
#     def __init__(self, content=b'', status_code=200,
#                  content_type='text/html; charset=utf-8',
#                  headers=None):
#         self._content = content
#         self._status_code = status_code
#         _headers = headers or {}
#         _headers.setdefault('Content-Type', content_type)
#         if isinstance(_headers, Headers):
#             self._headers = _headers
#         else:
#             self._headers = Headers(_headers)
#         self._cookies = SimpleCookie()
#         self._load_cookies_from_headers()
# 
#     def _load_cookies_from_headers(self):
#         cookies = self._headers.to_dict().pop('Set-Cookie', [])
#         for cookie in cookies:
#             self._cookies.load(cookie)
# 
#     @property
#     def content(self):
#         return self._content
# 
#     @content.setter
#     def content(self, value):
#         if isinstance(value, str):
#             value = value.encode('utf-8')
#         self._content = value
#     body = data = content
# 
#     def get_data(self):
#         return self._content
# 
#     @property
#     def content_type(self, value):
#         return self.headers.get('Content-Type', '')
# 
#     @content_type.setter
#     def content_type(self, value):
#         self.headers['Content-Type'] = value
# 
#     @property
#     def content_length(self):
#         return int(self.headers.get('Content-Length', '0'))
# 
#     @property
#     def status_code(self):
#         return self._status_code
# 
#     @status_code.setter
#     def status_code(self, value):
#         self._status_code = value
# 
#     @property
#     def status(self):
#         code = self._status_code
#         return response_status_string(code)
# 
#     @property
#     def headers(self):
#         return self._headers
# 
#     @headers.setter
#     def headers(self, value):
#         self._headers = Headers(value)
# 
#     @property
#     def content_type(self):
#         return self._headers.get('Content-Type', '')
# 
#     @content_type.setter
#     def content_type(self, value):
#         self._headers['Content-Type'] = value
# 
#     @property
#     def cookies(self):
#         return self._cookies
# 
#     def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
#                    domain=None, secure=False, httponly=False):
#         cookie = cookie_dump(
#             key, value=value, max_age=max_age, expires=expires, path=path,
#             domain=domain, secure=secure, httponly=httponly
#         )
#         self._cookies.load(cookie)
# 
#     def delete_cookie(self, key, max_age=0,
#                       expires='Thu, 01-Jan-1970 00:00:00 GMT'):
#         self.set_cookie(key, value='', max_age=max_age, expires=expires)
# 
#     @property
#     def headers_list(self):
#         # normal headers
#         headers_list = list(self.headers.to_list())
# 
#         # set-cookies
#         headers_list.extend(
#             ('Set-Cookie', value.OutputString())
#             for value in self.cookies.values()
#         )
#         return headers_list
# 
#     def json(self):
#         return json.loads(to_text(self.data))
# 
#     def __repr__(self):
#         return '<{} [{}]>'.format(self.__class__.__name__, self.status_code)
# 
# Path: bustard/utils.py
# def to_text(st, encoding='utf-8'):
#     if isinstance(st, str):
#         return st
#     elif isinstance(st, collections.ByteString):
#         return st.decode(encoding)
#     else:
#         return str(st)
# 
# def to_bytes(bt, encoding='utf-8'):
#     if isinstance(bt, collections.ByteString):
#         return bt
#     elif isinstance(bt, str):
#         return bt.encode(encoding)
#     else:
#         return bytes(bt)


# Path: bustard/testing.py
import collections
import mimetypes
import itertools
import io
import random
import sys
import time
import urllib
from .http import Headers, Response
from .utils import to_text, to_bytes

# -*- coding: utf-8 -*-



def run_wsgi_app(app, environ):

    response = []
    buffer = []

    def start_response(status, headers, exc_info=None):
        if exc_info is not None:
            raise (exc_info[0], exc_info[1], exc_info[2])
        response[:] = [status, headers]
        return buffer.append

    app_rv = app(environ, start_response)
    app_iter = itertools.chain(buffer, app_rv)


    return app_iter, response[0], Headers.from_list(response[1])