MEMFILE_MAX = 4*1024*1024
class Request(object):
    def __init__(self, environ, populate_request=True):
    def __repr__(self):
    def url_charset(self):
    def close(self):
    def __enter__(self):
    def __exit__(self, exc_type, exc_value, tb):
    def stream(self):
    def input_stream(self):
    def args(self):
    def data(self):
    def get_data(self, cache=True, as_text=False):
    def chunked(self):
    def iter_body(self, read, bufsize):
    def iter_chunked(self, read, bufsize):
    def get_input_stream(self):
    def parse_form_data(self):
    def parsed_form_data(self):
    def form(self):
    def values(self):
    def files(self):
    def get_host(self):
    def get_content_length(self):
    def get_current_url(self, root_only=False, strip_querystring=False, host_only=False):
    def cookies(self):
    def get_cookie(self, key):
    def headers(self):
    def path(self):
    def script_name(self):
    def full_path(self):
    def script_root(self):
    def url(self):
    def base_url(self):
    def root_url(self):
    def host_url(self):
    def host(self):
    def query_string(self):
    def method(self):
    def access_route(self):
    def remote_addr(self):
    def if_modified_since(self):
    def if_unmodified_since(self):
    def range(self):
    def authorization(self):
    def content_type(self):
    def content_length(self):
    def parsed_content_type(self):
    def mimetype(self):
    def mimetype_params(self):
    def blueprint(self):
    def json(self):
    def get_json(self, force=False, silent=False, cache=True): def abort(code, *args, **kwargs):
    mapping = default_exceptions
    if not args and not kwargs and not isinstance(code, integer_types):
        raise HTTPException(response=code)
    if code not in mapping:
        raise LookupError('no exception for %r' % code)
    raise mapping[code](*args, **kwargs) class Cocopot(object):
    """The cocopot object implements a WSGI application and acts as the central
    object.  Once it is created it will act as a central registry for
    the view functions, the URL rules,  and more.

    Usually you create a `Cocopot` instance in your main module or
    in the `__init__.py` file of your package like this:

        from cocopot import Cocopot
        app = Cocopot()

    """

    debug = False

    log_format = '%(message)s'


    def __init__(self, import_name=''):
        self.config = {}

        self.import_name = import_name

        #: A dictionary of all view functions registered.  The keys will
        #: be function names which are also used to generate URLs and
        #: the values are the function objects themselves.
        self.view_functions = {}

        #: A dictionary of all registered error handlers.  The key is `None`
        #: for error handlers active on the application, otherwise the key is
        #: the name of the blueprint.  Each key points to another dictionary
        #: where they key is the status code of the http exception.  The
        #: special key `None` points to a list of tuples where the first item
        #: is the class for the instance check and the second the error handler
        #: function.
        #:
        self.error_handler_spec = {None: {}}

        #: A dictionary with lists of functions that should be called at the
        #: beginning of the request.  The key of the dictionary is the name of
        #: the blueprint this function is active for, `None` for all requests.
        #: This can for example be used to open database connections or
        #: getting hold of the currently logged in user.
        self.before_request_funcs = {}

        #: A dictionary with lists of functions that should be called after
        #: each request.  The key of the dictionary is the name of the blueprint
        #: this function is active for, `None` for all requests.  This can for
        #: example be used to open database connections or getting hold of the
        #: currently logged in user.
        self.after_request_funcs = {}
        self.teardown_request_funcs = {}

        #: all the attached blueprints in a dictionary by name.  Blueprints
        #: can be attached multiple times so this dictionary does not tell
        #: you how often they got attached.
        self.blueprints = {}

        self.router = Router()

        self.logger = self.create_logger()

    def create_logger(self):
        """Creates a logger for the given application.  This logger works
        similar to a regular Python logger but changes the effective logging
        level based on the application's debug flag.  Furthermore this
        function also removes all attached handlers in case there was a
        logger with the log name before.
        """
        class DebugHandler(StreamHandler):
            def emit(x, record):
                StreamHandler.emit(x, record) if self.debug else None

        handler = DebugHandler()
        handler.setLevel(DEBUG)
        handler.setFormatter(Formatter(self.log_format))
        logger = getLogger(self.name or 'cocopot')
        logger.addHandler(handler)
        if logger.level == NOTSET or logger.level > INFO:
            logger.setLevel(INFO)
        return logger

    @property
    def name(self):
        """The name of the application.  This is usually the import name
        with the difference that it's guessed from the run file if the
        import name is main.  This name is used as a display name when
        Cocopot needs the name of the application.  It can be set and overridden
        to change the value.
        """
        if self.import_name == '__main__':
            fn = getattr(sys.modules['__main__'], '__file__', None)
            return os.path.splitext(os.path.basename(fn))[0] if fn else '__main__'
        return self.import_name


    def run(self, host=None, port=None, debug=True, **options):
        """Runs the application on a local development server.
        Args:

          * host: the hostname to listen on. Set this to '0.0.0.0' to
                     have the server available externally as well. Defaults to
                     '127.0.0.1'.
          * port: the port of the webserver. Defaults to 5000 or the
                     port defined in the SERVER_NAME` config variable if
                     present.
        """
        from cocopot.run import run_simple
        if host is None:
            host = '127.0.0.1'
        if port is None:
            port = 3000
        if debug is not None:
            self.debug = bool(debug)
        run_simple(host, port, self, **options)

    def register_blueprint(self, blueprint, **options):
        """Registers a blueprint on the application.
        """
        if blueprint.name in self.blueprints:
            assert self.blueprints[blueprint.name] is blueprint, \
                'A blueprint\'s name collision occurred between %r and ' \
                '%r.  Both share the same name "%s".  Blueprints that ' \
                'are created on the fly need unique names.' % \
                (blueprint, self.blueprints[blueprint.name], blueprint.name)
        else:
            self.blueprints[blueprint.name] = blueprint
        blueprint.register(self, options)

    def add_url_rule(self, rule, endpoint=None, view_func=None, methods=None, **options):
        """Connects a URL rule.  Works exactly like the `route`
        decorator.  If a view_func is provided it will be registered with the
        endpoint.

        Basically this example:

            @app.route('/')
            def index():
                pass

        Is equivalent to the following:

            def index():
                pass
            app.add_url_rule('/', 'index', index)

        If the view_func is not provided you will need to connect the endpoint
        to a view function like so:

            app.view_functions['index'] = index

        Internally `route` invokes `add_url_rule` so if you want
        to customize the behavior via subclassing you only need to change
        this method.

        For more information refer to `url-route-registrations`.

        Args:

          * rule : the URL rule as string
          * endpoint : the endpoint for the registered URL rule.
                    Cocopot itself assumes the name of the view function as endpoint
          * view_func: the function to call when serving a request to the
                    provided endpoint
          * options: methods is a list of methods this rule should be limited
                    to (`GET`, `POST` etc.).
        """
        if endpoint is None:
            endpoint = view_func.__name__

        # if the methods are not given and the view_func object knows its
        # methods we can use that instead.  If neither exists, we go with
        # a tuple of only `GET` as default.
        if methods is None:
            methods = getattr(view_func, 'methods', None) or ('GET',)
        methods = set(methods)

        # Methods that should always be added
        required_methods = set(getattr(view_func, 'required_methods', ()))

        # Add the required methods now.
        methods |= required_methods

        defaults = options.get('defaults') or {}

        self.router.add(rule, endpoint, methods=methods, defaults=defaults)
        if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError('View function mapping is overwriting an '
                                     'existing endpoint function: %s' % endpoint)
            self.view_functions[endpoint] = view_func

    def route(self, rule, **options):
        """A decorator that is used to register a view function for a
        given URL rule.  This does the same thing as `add_url_rule`
        but is intended for decorator usage:

            @app.route('/')
            def index():
                return 'Hello World'

        For more information refer to `url-route-registrations`.

        Args:

          * rule: the URL rule as string
          * endpoint: the endpoint for the registered URL rule.  Cocopot
                         itself assumes the name of the view function as
                         endpoint
        """
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            methods = options.pop('methods', None)
            self.add_url_rule(rule, endpoint, f, methods, **options)
            return f
        return decorator

    def endpoint(self, endpoint):
        """A decorator to register a function as an endpoint.
        Example:

            @app.endpoint('example.endpoint')
            def example():
                return "example"
        Args:
            endpoint: the name of the endpoint
        """
        def decorator(f):
            self.view_functions[endpoint] = f
            return f
        return decorator

    def errorhandler(self, code_or_exception):
        """A decorator that is used to register a function give a given
        error code.  Example:

            @app.errorhandler(404)
            def page_not_found(error):
                return 'This page does not exist', 404

        You can also register handlers for arbitrary exceptions:

            @app.errorhandler(DatabaseError)
            def special_exception_handler(error):
                return 'Database connection failed', 500

        You can also register a function as error handler without using
        the `errorhandler` decorator.  The following example is
        equivalent to the one above:

            def page_not_found(error):
                return 'This page does not exist', 404
            app.error_handler_spec[None][404] = page_not_found

        Setting error handlers via assignments to `error_handler_spec`
        however is discouraged as it requires fiddling with nested dictionaries
        and the special case for arbitrary exception types.

        The first `None` refers to the active blueprint.  If the error
        handler should be application wide `None` shall be used.

        """
        def decorator(f):
            self._register_error_handler(None, code_or_exception, f)
            return f
        return decorator

    def register_error_handler(self, code_or_exception, f):
        """Alternative error attach function to the `errorhandler`
        decorator that is more straightforward to use for non decorator
        usage.
        """
        self._register_error_handler(None, code_or_exception, f)

    def _register_error_handler(self, key, code_or_exception, f):
        if isinstance(code_or_exception, HTTPException):
            code_or_exception = code_or_exception.code
        if isinstance(code_or_exception, integer_types):
            assert code_or_exception != 500 or key is None, \
                'It is currently not possible to register a 500 internal ' \
                'server error on a per-blueprint level.'
            self.error_handler_spec.setdefault(key, {})[code_or_exception] = f
        else:
            self.error_handler_spec.setdefault(key, {}).setdefault(None, []) \
                .append((code_or_exception, f))

    def before_request(self, f):
        """Registers a function to run before each request."""
        self.before_request_funcs.setdefault(None, []).append(f)
        return f


    def after_request(self, f):
        """Register a function to be run after each request.  Your function
        must take one parameter, a `Response` object and return
        a new response object.

        """
        self.after_request_funcs.setdefault(None, []).insert(0, f)
        return f

    def teardown_request(self, f):
        """Register a function to be run at the end of each request,
        regardless of whether there was an exception or not.  These functions
        are executed when the request context is popped, even if not an
        actual request was performed.

        Generally teardown functions must take every necessary step to avoid
        that they will fail.  If they do execute code that might fail they
        will have to surround the execution of these code by try/except
        statements and log occurring errors.

        When a teardown function was called because of a exception it will
        be passed an error object.
        """
        self.teardown_request_funcs.setdefault(None, []).insert(0, f)
        return f


    def handle_http_exception(self, e):
        """Handles an HTTP exception.  By default this will invoke the
        registered error handlers and fall back to returning the
        exception as response.
        """
        handlers = self.error_handler_spec.get(request.blueprint)
        # Proxy exceptions don't have error codes.  We want to always return
        # those unchanged as errors
        if e.code is None:
            return e
        if handlers and e.code in handlers:
            handler = handlers[e.code]
        else:
            handler = self.error_handler_spec[None].get(e.code)
        if handler is None:
            return e
        return handler(e)

    def handle_user_exception(self, e):
        """This method is called whenever an exception occurs that should be
        handled.  A special case are `~cocopot.exception.HTTPException`\s which are forwarded by
        this function to the `handle_http_exception` method.  This
        function will either return a response value or reraise the
        exception with the same traceback.

        """
        exc_type, exc_value, tb = sys.exc_info()
        assert exc_value is e

        # ensure not to trash sys.exc_info() at that point in case someone
        # wants the traceback preserved in handle_http_exception.  Of course
        # we cannot prevent users from trashing it themselves in a custom
        # trap_http_exception method so that's their fault then.
        if isinstance(e, HTTPException):
            return self.handle_http_exception(e)

        blueprint_handlers = ()
        handlers = self.error_handler_spec.get(request.blueprint)
        if handlers is not None:
            blueprint_handlers = handlers.get(None, ())
        app_handlers = self.error_handler_spec[None].get(None, ())
        for typecheck, handler in chain(blueprint_handlers, app_handlers):
            if isinstance(e, typecheck):
                return handler(e)

        reraise(exc_type, exc_value, tb)

    def handle_exception(self, e):
        """Default exception handling that kicks in when an exception
        occurs that is not caught.  In debug mode the exception will
        be re-raised immediately, otherwise it is logged and the handler
        for a 500 internal server error is used.  If no such handler
        exists, a default 500 internal server error message is displayed.
        """
        exc_type, exc_value, tb = sys.exc_info()

        handler = self.error_handler_spec[None].get(500)

        self.log_exception((exc_type, exc_value, tb))
        if handler is None:
            return InternalServerError()
        return handler(e)

    def log_exception(self, exc_info):
        """Logs an exception.  This is called by `handle_exception`
        if debugging is disabled and right before the handler is called.
        The default implementation logs the exception as error on the
        `logger`.
        """
        self.logger.error('Exception on %s [%s]' % (
            request.path,
            request.method
        ), exc_info=exc_info)

    def full_dispatch_request(self):
        """Dispatches the request and on top of that performs request
        pre and postprocessing as well as HTTP exception catching and
        error handling.
        """
        try:
            req = _request_ctx_stack.top.request
            endpoint, view_args = self.router.match(to_unicode(req.environ['PATH_INFO']))
            req.endpoint, req.view_args = endpoint, view_args
            rv = self.preprocess_request()
            if rv is None:
                rv = self.view_functions[req.endpoint](**req.view_args)
        except Exception as e:
            self.logger.info('%s'%(traceback.format_exc()))
            rv = self.handle_user_exception(e)
        response = make_response(rv)
        response = self.process_response(response)
        return response

    def preprocess_request(self):
        """Called before the actual request dispatching and will
        call every as `before_request` decorated function.
        If any of these function returns a value it's handled as
        if it was the return value from the view and further
        request handling is stopped.
        """
        bp = _request_ctx_stack.top.request.blueprint
        funcs = self.before_request_funcs.get(None, ())
        if bp is not None and bp in self.before_request_funcs:
            funcs = chain(funcs, self.before_request_funcs[bp])
        for func in funcs:
            rv = func()
            if rv is not None:
                return rv

    def process_response(self, response):
        """Can be overridden in order to modify the response object
        before it's sent to the WSGI server.  By default this will
        call all the `after_request` decorated functions.

        Args:

          * response: a `Response` object.

        Returns:

          * a new response object or the same, has to be an
                 instance of `Response`.
        """
        ctx = _request_ctx_stack.top
        bp = ctx.request.blueprint
        funcs = []
        if bp is not None and bp in self.after_request_funcs:
            funcs = chain(funcs, self.after_request_funcs[bp])
        if None in self.after_request_funcs:
            funcs = chain(funcs, self.after_request_funcs[None])
        for handler in funcs:
            response = handler(response)
        return response

    def do_teardown_request(self, exc=None):
        """Called after the actual request dispatching and will
        call every as `teardown_request` decorated function.  This is
        not actually called by the `Cocopot` object itself but is always
        triggered when the request context is popped.  That way we have a
        tighter control over certain resources under testing environments.
        """
        if exc is None:
            exc = sys.exc_info()[1]
        funcs = self.teardown_request_funcs.get(None, ())
        bp = _request_ctx_stack.top.request.blueprint
        if bp is not None and bp in self.teardown_request_funcs:
            funcs = chain(funcs, self.teardown_request_funcs[bp])
        for func in funcs:
            rv = func(exc)


    def wsgi_app(self, environ, start_response):
        """The actual WSGI application.  This is not implemented in
        `__call__` so that middlewares can be applied without losing a
        reference to the class.  So instead of doing this:

            app = MyMiddleware(app)

        It's a better idea to do this instead:

            app.wsgi_app = MyMiddleware(app.wsgi_app)

        Then you still have the original application object around and
        can continue to call methods on it.

        Args:

          * environ: a WSGI environment
          * start_response: a callable accepting a status code,
                               a list of headers and an optional
                               exception context to start the response
        """
        req = Request(environ)
        ctx = RequestContext(self, environ, req)
        ctx.push()
        error = None
        try:
            try:
                response = self.full_dispatch_request()
            except Exception as e:
                self.logger.info('%s'%(traceback.format_exc()))
                error = e
                response = make_response(self.handle_exception(e))
            return response(environ, start_response)
        finally:
            self.do_teardown_request(error)
            ctx.pop(error)

    def __call__(self, environ, start_response):
        """Shortcut for `wsgi_app`."""
        return self.wsgi_app(environ, start_response)

    def __repr__(self):
        return '<%s %r>' % (
            self.__class__.__name__,
            self.name,
        ) def _lookup_req_object(name): class Blueprint(object):
    """Represents a blueprint.
    """

    def __init__(self, name, url_prefix=None, url_defaults=None):
        self.app = None
        self.name = name
        self.url_prefix = url_prefix
        self.deferred_functions = []
        self.view_functions = {}
        self.url_defaults = url_defaults or {}
        self.register_options = {}

    def record(self, func):
        """Registers a function that is called when the blueprint is
        registered on the application.  This function is called with the
        state as argument as returned by the `make_setup_state`
        method.
        """
        if self.app:
            from warnings import warn
            warn('The blueprint was already registered once '
                         'but is getting modified now.  These changes '
                         'will not show up.')
        self.deferred_functions.append(func)


    def register(self, app, options):
        """Called by `Cocopot.register_blueprint` to register a blueprint
        on the application.  This can be overridden to customize the register
        behavior.  Keyword arguments from
        `~cocopot.Cocopot.register_blueprint` are directly forwarded to this
        method in the `options` dictionary.
        """
        self.app = app
        self.register_options = options or {}
        for deferred in self.deferred_functions:
            deferred(self)

    def route(self, rule, **options):
        """Like `Cocopot.route` but for a blueprint.
        """
        def decorator(f):
            endpoint = options.pop("endpoint", f.__name__)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        """Like `Cocopot.add_url_rule` but for a blueprint.
        """
        if endpoint:
            assert '.' not in endpoint, "Blueprint endpoint's should not contain dot's"
        self.record(lambda s:
            s.app_add_url_rule(rule, endpoint, view_func, **options))

    def app_add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        """A helper method to register a rule (and optionally a view function)
        to the application.  The endpoint is automatically prefixed with the
        blueprint's name.
        """
        url_prefix = self.register_options.get('url_prefix') or self.url_prefix
        if url_prefix:
            rule = url_prefix + rule
        if endpoint is None:
            endpoint = view_func.__name__
        defaults = self.url_defaults
        if 'defaults' in options:
            defaults = dict(defaults, **options.pop('defaults'))
        self.app.add_url_rule(rule, '%s.%s' % (self.name, endpoint),
                              view_func, defaults=defaults, **options)

    def endpoint(self, endpoint):
        """Like `Cocopot.endpoint` but for a blueprint.  This does not
        prefix the endpoint with the blueprint name, this has to be done
        explicitly by the user of this method.  If the endpoint is prefixed
        with a `.` it will be registered to the current blueprint, otherwise
        it's an application independent endpoint.
        """
        def decorator(f):
            def register_endpoint(self):
                self.app.view_functions['%s.%s' % (self.name, endpoint)] = f
            self.record(register_endpoint)
            return f
        return decorator


    def before_request(self, f):
        """Like `Cocopot.before_request` but for a blueprint.  This function
        is only executed before each request that is handled by a function of
        that blueprint.
        """
        self.record(lambda s: s.app.before_request_funcs
            .setdefault(self.name, []).append(f))
        return f

    def before_app_request(self, f):
        """Like `Cocopot.before_request`.  Such a function is executed
        before each request, even if outside of a blueprint.
        """
        self.record(lambda s: s.app.before_request_funcs
            .setdefault(None, []).append(f))
        return f

    def after_request(self, f):
        """Like `Cocopot.after_request` but for a blueprint.  This function
        is only executed after each request that is handled by a function of
        that blueprint.
        """
        self.record(lambda s: s.app.after_request_funcs
            .setdefault(self.name, []).append(f))
        return f

    def after_app_request(self, f):
        """Like `Cocopot.after_request` but for a blueprint.  Such a function
        is executed after each request, even if outside of the blueprint.
        """
        self.record(lambda s: s.app.after_request_funcs
            .setdefault(None, []).append(f))
        return f

    def teardown_request(self, f):
        """Like `Cocopot.teardown_request` but for a blueprint.  This
        function is only executed when tearing down requests handled by a
        function of that blueprint.  Teardown request functions are executed
        when the request context is popped, even when no actual request was
        performed.
        """
        self.record(lambda s: s.app.teardown_request_funcs
            .setdefault(self.name, []).append(f))
        return f

    def teardown_app_request(self, f):
        """Like `Cocopot.teardown_request` but for a blueprint.  Such a
        function is executed when tearing down each request, even if outside of
        the blueprint.
        """
        self.record(lambda s: s.app.teardown_request_funcs
            .setdefault(None, []).append(f))
        return f

    def app_errorhandler(self, code):
        """Like `Cocopot.errorhandler` but for a blueprint.  This
        handler is used for all requests, even if outside of the blueprint.
        """
        def decorator(f):
            self.record(lambda s: s.app.errorhandler(code)(f))
            return f
        return decorator


    def errorhandler(self, code_or_exception):
        """Registers an error handler that becomes active for this blueprint
        only.  Please be aware that routing does not happen local to a
        blueprint so an error handler for 404 usually is not handled by
        a blueprint unless it is caused inside a view function.  Another
        special case is the 500 internal server error which is always looked
        up from the application.

        Otherwise works as the `Cocopot.errorhandler` decorator
        of the `Cocopot` object.
        """
        def decorator(f):
            self.record(lambda s: s.app._register_error_handler(
                self.name, code_or_exception, f))
            return f
        return decorator def to_bytes(s, enc='utf8'):
    if s is None:
        return None
    return s.encode(enc) if isinstance(s, text_type) else bytes(s) class Request(object):
    """
    """

    #: the charset for the request, defaults to utf-8
    charset = 'utf-8'

    #: the error handling procedure for errors, defaults to 'replace'
    encoding_errors = 'replace'

    endpoint = ''

    #: a dict of view arguments that matched the request.  If an exception
    #: happened when matching, this will be `None`.
    view_args = None

    def __init__(self, environ, populate_request=True):
        self.environ = environ
        if populate_request:
            self.environ['cocopot.request'] = self

    def __repr__(self):
        # make sure the __repr__ even works if the request was created
        # from an invalid WSGI environment.  If we display the request
        # in a debug session we don't want the repr to blow up.
        args = []
        try:
            args.append("'%s'" % to_native(self.url, self.url_charset))
            args.append('[%s]' % self.method)
        except Exception:
            args.append('(invalid WSGI environ)')

        return '<%s %s>' % (
            self.__class__.__name__,
            ' '.join(args)
        )

    @property
    def url_charset(self):
        """The charset that is assumed for URLs.  Defaults to the value
        of `charset`.

        """
        return self.charset

    def close(self):
        """Closes associated resources of this request object.  This
        closes all file handles explicitly.  You can also use the request
        object in a with statement with will automatically close it.

        """
        if hasattr(self.stream, 'close'):
            self.stream.close()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, tb):
        self.close()

    @cached_property
    def stream(self):
        stream = self.get_input_stream()
        stream.seek(0)
        return stream

    @property
    def input_stream(self):
        return self.environ.get('wsgi.input')

    @cached_property
    def args(self):
        query_string = self.environ.get('QUERY_STRING', '')
        if query_string:
            return MultiDict(urldecode(query_string))
        else:
            return MultiDict()

    @property
    def data(self):
        return self.get_data()

    def get_data(self, cache=True, as_text=False):
        """This reads the buffered incoming data from the client into one
        bytestring.  By default this is cached but that behavior can be
        changed by setting `cache` to `False`.

        Usually it's a bad idea to call this method without checking the
        content length first as a client could send dozens of megabytes or more
        to cause memory problems on the server.

        If `as_text` is set to `True` the return value will be a decoded
        unicode string.

        """
        rv = getattr(self, '_cached_data', None)
        if rv is None:
            rv = self.stream.read()
            if cache:
                self._cached_data = rv
        if as_text:
            rv = rv.decode(self.charset, self.encoding_errors)
        return rv

    @cached_property
    def chunked(self):
        """ True if Chunked transfer encoding was. """
        return 'chunked' in self.environ.get('HTTP_TRANSFER_ENCODING', '').lower()

    def iter_body(self, read, bufsize):
        maxread = max(0, self.content_length)
        while maxread:
            part = read(min(maxread, bufsize))
            if not part: break
            yield part
            maxread -= len(part)

    def iter_chunked(self, read, bufsize):
        err = BadRequest('Error while parsing chunked transfer body.')
        rn, sem, bs = to_bytes('\r\n'), to_bytes(';'), to_bytes('')
        while True:
            header = read(1)
            while header[-2:] != rn:
                c = read(1)
                header += c
                if not c: raise err
                if len(header) > bufsize: raise err
            size, _, _ = header.partition(sem)
            try:
                maxread = int(to_native(size.strip()), 16)
            except ValueError:
                raise err
            if maxread == 0: break
            buff = bs
            while maxread > 0:
                if not buff:
                    buff = read(min(maxread, bufsize))
                part, buff = buff[:maxread], buff[maxread:]
                if not part: raise err
                yield part
                maxread -= len(part)
            if read(2) != rn:
                raise err

    def get_input_stream(self):
        try:
            read_func = self.environ['wsgi.input'].read
        except KeyError:
            self.environ['wsgi.input'] = BytesIO()
            return self.environ['wsgi.input']
        if self.chunked:
            body, body_size, is_temp_file = BytesIO(), 0, False
            for part in self.iter_chunked(read_func, MEMFILE_MAX):
                body.write(part)
                body_size += len(part)
                if not is_temp_file and body_size > MEMFILE_MAX:
                    body, tmp = TemporaryFile(mode='w+b'), body
                    body.write(tmp.getvalue())
                    del tmp
                    is_temp_file = True
        else:
            if self.content_length > MEMFILE_MAX:
                body = TemporaryFile(mode='w+b')
            else:
                body = BytesIO()
                for part in self.iter_body(read_func, MEMFILE_MAX):
                    body.write(part)
        self.environ['wsgi.input'] = body
        body.seek(0)
        return body

    def parse_form_data(self):
        post = FormsDict()
        # We default to application/x-www-form-urlencoded for everything that
        # is not multipart and take the fast path (also: 3.1 workaround)
        if not self.content_type.startswith('multipart/'):
            pairs = urldecode(to_unicode(self.get_data()))
            for key, value in pairs:
                post[key] = value
            return post

        safe_env = {'QUERY_STRING': ''}  # Build a safe environment for cgi
        for key in ('REQUEST_METHOD', 'CONTENT_TYPE', 'CONTENT_LENGTH'):
            if key in self.environ:
                safe_env[key] = self.environ[key]
        args = dict(fp=self.stream, environ=safe_env, keep_blank_values=True)
        if not PY2:
            args['encoding'] = 'utf8'
        data = cgi.FieldStorage(**args)
        self.environ['_cgi.FieldStorage'] = data  #http://bugs.python.org/issue18394
        data = data.list or []
        for item in data:
            if item.filename:
                post[item.name] = FileUpload(item.file, item.name,
                                             item.filename, item.headers)
            else:
                post[item.name] = item.value
        return post

    @cached_property
    def parsed_form_data(self):
        return self.parse_form_data()

    @cached_property
    def form(self):
        form = FormsDict()
        for name, item in self.parsed_form_data.allitems():
            if not isinstance(item, FileUpload):
                form[name] = item
        return form

    @cached_property
    def values(self):
        """Combined multi dict for `args` and `form`."""
        args = []
        for d in self.args, self.form:
            if not isinstance(d, MultiDict):
                for k, v in d.items():
                    args.append((k, v))
            else:
                for k, v in d.iterallitems():
                    args.append((k, v))
        return MultiDict(args)

    @cached_property
    def files(self):
        files = FormsDict()
        for name, item in self.parsed_form_data.allitems():
            if isinstance(item, FileUpload):
                files[name] = item
        return files

    def get_host(self):
        """Return the real host for the given WSGI environment.  This first checks
        the `X-Forwarded-Host` header, then the normal `Host` header, and finally
        the `SERVER_NAME` environment variable (using the first one it finds).
        """
        environ = self.environ
        if 'HTTP_X_FORWARDED_HOST' in environ:
            rv = environ['HTTP_X_FORWARDED_HOST'].split(',', 1)[0].strip()
        elif 'HTTP_HOST' in environ:
            rv = environ['HTTP_HOST']
        else:
            rv = environ['SERVER_NAME']
            if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \
               in (('https', '443'), ('http', '80')):
                rv += ':%s'%(environ['SERVER_PORT'])
        return rv


    def get_content_length(self):
        """Returns the content length from the WSGI environment as
        integer.  If it's not available `None` is returned.
        """
        content_length = self.environ.get('CONTENT_LENGTH')
        if content_length is not None:
            try:
                return max(0, int(content_length))
            except (ValueError, TypeError):
                pass
        return 0

    def get_current_url(self, root_only=False, strip_querystring=False, host_only=False):
        """A handy helper function that recreates the full URL as IRI for the
        current request or parts of it.  Here an example:

            >>> get_current_url()
            'http://localhost/script/?param=foo'
            >>> get_current_url(root_only=True)
            'http://localhost/script/'
            >>> get_current_url(host_only=True)
            'http://localhost/'
            >>> get_current_url(strip_querystring=True)
            'http://localhost/script/'

        """
        environ = self.environ
        tmp = [environ['wsgi.url_scheme'], '://', self.get_host()]
        cat = tmp.append
        if host_only:
            return ''.join(tmp) + '/'
        cat(urlquote(environ.get('SCRIPT_NAME', '')).rstrip('/'))
        cat('/')
        if not root_only:
            print(type(environ.get('PATH_INFO')))
            cat(urlquote(environ.get('PATH_INFO', '').lstrip('/')))
            if not strip_querystring:
                qs = self.query_string
                if qs:
                    cat('?' + qs)
        return ''.join(tmp)

    @cached_property
    def cookies(self):
        """Read only access to the retrieved cookie values as dictionary."""
        cookies = SimpleCookie(self.environ.get('HTTP_COOKIE', '')).values()
        return FormsDict((c.key, c.value) for c in cookies)

    def get_cookie(self, key):
        """ Return the content of a cookie. """
        value = self.cookies.get(key)
        return value

    @cached_property
    def headers(self):
        """The headers from the WSGI environ as immutable
        `~cocopot.datastructures.WSGIHeaders`.
        """
        return WSGIHeaders(self.environ)

    @cached_property
    def path(self):
        """Requested path as unicode.  This works a bit like the regular path
        info in the WSGI environment but will always include a leading slash,
        even if the URL root is accessed.
        """
        return '/' + to_unicode(self.environ.get('PATH_INFO', '')).lstrip('/')

    @property
    def script_name(self):
        """ The initial portion of the URL's `path` that was removed by a higher
            level (server or routing middleware) before the application was
            called. This script path is returned with leading and tailing
            slashes. """
        script_name = self.environ.get('SCRIPT_NAME', '').strip('/')
        return '/' + script_name + '/' if script_name else '/'

    @property
    def full_path(self):
        """Requested path as unicode, including the query string."""
        return urljoin(self.script_name, self.path.lstrip('/'))

    @cached_property
    def script_root(self):
        """The root path of the script without the trailing slash."""
        raw_path = to_unicode(self.environ.get('SCRIPT_NAME') or '',
                                       self.charset, self.encoding_errors)
        return raw_path.rstrip('/')

    @cached_property
    def url(self):
        """The reconstructed current URL as IRI.
        """
        return self.get_current_url()

    @cached_property
    def base_url(self):
        """Like `url` but without the querystring
        """
        return self.get_current_url(strip_querystring=True)

    @cached_property
    def root_url(self):
        """The full URL root (with hostname), this is the application
        root as IRI.
        """
        return self.get_current_url(root_only=True)

    @cached_property
    def host_url(self):
        """Just the host with scheme as IRI.
        """
        return self.get_current_url(host_only=True)

    @cached_property
    def host(self):
        """Just the host including the port if available.
        """
        return self.get_host()

    @property
    def query_string(self):
        return self.environ.get('QUERY_STRING', '')

    @property
    def method(self):
        return self.environ.get('REQUEST_METHOD', 'GET').upper()

    @cached_property
    def access_route(self):
        """If a forwarded header exists this is a list of all ip addresses
        from the client ip to the last proxy server.
        """
        if 'HTTP_X_FORWARDED_FOR' in self.environ:
            addr = self.environ['HTTP_X_FORWARDED_FOR'].split(',')
            return list([x.strip() for x in addr])
        elif 'REMOTE_ADDR' in self.environ:
            return list([self.environ['REMOTE_ADDR']])
        return list()

    remote_route = access_route

    @property
    def remote_addr(self):
        """The remote address of the client."""
        route = self.access_route
        return route[0] if route else None


    is_xhr = property(lambda x: x.environ.get('HTTP_X_REQUESTED_WITH', '')
                      .lower() == 'xmlhttprequest', doc='''
        True if the request was triggered via a JavaScript XMLHttpRequest.
        This only works with libraries that support the `X-Requested-With`
        header and set it to "XMLHttpRequest".  Libraries that do that are
        prototype, jQuery and Mochikit and probably some more.''')
    is_secure = property(lambda x: x.environ['wsgi.url_scheme'] == 'https',
                         doc='`True` if the request is secure.')


    @cached_property
    def if_modified_since(self):
        """The parsed `If-Modified-Since` header as datetime object."""
        return parse_date(self.environ.get('HTTP_IF_MODIFIED_SINCE'))

    @cached_property
    def if_unmodified_since(self):
        """The parsed `If-Unmodified-Since` header as datetime object."""
        return parse_date(self.environ.get('HTTP_IF_UNMODIFIED_SINCE'))


    @cached_property
    def range(self):
        """The parsed `Range` header.
        """
        return parse_range_header(self.environ.get('HTTP_RANGE'))


    @cached_property
    def authorization(self):
        header = self.environ.get('HTTP_AUTHORIZATION')
        if not header: return None
        return parse_auth(header)

    @property
    def content_type(self):
        return self.environ.get('CONTENT_TYPE', '')


    @cached_property
    def content_length(self):
        """The Content-Length entity-header field indicates the size of the
        entity-body in bytes or, in the case of the HEAD method, the size of
        the entity-body that would have been sent had the request been a
        GET.
        """
        return self.get_content_length()

    @cached_property
    def parsed_content_type(self):
        return parse_content_type(self.environ.get('CONTENT_TYPE', ''))

    @property
    def mimetype(self):
        """Like `content_type` but without parameters (eg, without
        charset, type etc.).  For example if the content
        type is ``text/html; charset=utf-8`` the mimetype would be
        ``'text/html'``.
        """
        return self.parsed_content_type[0]

    @property
    def mimetype_params(self):
        """The mimetype parameters as dict.  For example if the content
        type is ``text/html; charset=utf-8`` the params would be
        ``{'charset': 'utf-8'}``.
        """
        return self.parsed_content_type[1]

    @property
    def blueprint(self):
        """The name of the current blueprint"""
        if '.' in self.endpoint:
            return self.endpoint.rsplit('.', 1)[0]

    @property
    def json(self):
        """If the mimetype is `application/json` this will contain the
        parsed JSON data.  Otherwise this will be `None`.

        The `get_json` method should be used instead.
        """
        return self.get_json(silent=True)

    def get_json(self, force=False, silent=False, cache=True):
        """Parses the incoming JSON request data and returns it.  If
        parsing fails the `on_json_loading_failed` method on the
        request object will be invoked.  By default this function will
        only load the json data if the mimetype is ``application/json``
        but this can be overriden by the `force` parameter.

        Args:

          * force: if set to `True` the mimetype is ignored.
          * silent: if set to `False` this method will fail silently
                       and return `False`.
          * cache: if set to `True` the parsed JSON data is remembered
                      on the request.
        """
        _missing = object()
        rv = getattr(self, '_cached_json', _missing)
        if rv is not _missing:
            return rv

        if self.mimetype != 'application/json' and not force:
            return None

        # We accept a request charset against the specification as
        # certain clients have been using this in the past.  This
        # fits our general approach of being nice in what we accept
        # and strict in what we send out.
        request_charset = self.mimetype_params.get('charset', 'utf-8')
        try:
            data = to_unicode(self.get_data(cache=False))
            if request_charset is not None:
                rv = json.loads(data, encoding=request_charset)
            else:
                rv = json.loads(data)
        except ValueError as e:
            if silent:
                rv = None
            else:
                raise BadRequest()
        if cache:
            self._cached_json = rv
        return rv class RequestContextGlobals(object):
    """A plain object."""

    def get(self, name, default=None):
        return self.__dict__.get(name, default)

    def __contains__(self, item):
        return item in self.__dict__

    def __iter__(self):
        return iter(self.__dict__)

    def __repr__(self):
        return '<cocopot.g of %r>' % object.__repr__(self) class RequestContext(object):
    """The application context binds an application object implicitly
    to the current thread or greenlet, similar to how the
    `RequestContext` binds request information.  The application
    context is also implicitly created if a request context is created
    but the application is not on top of the individual application
    context.
    """

    def __init__(self, app, environ, request=None, **kwargs):
        self.app = app
        self.environ = environ
        self.request = request
        self.g = RequestContextGlobals()
        for k, v in kwargs.items():
            setattr(self.g, k, v)

    def push(self):
        if hasattr(sys, 'exc_clear'):
            sys.exc_clear()
        _request_ctx_stack.push(self)
        self.request.__enter__()

    def pop(self, exc=None):
        rv = _request_ctx_stack.pop()
        assert rv is self, 'Popped wrong request context.  (%r instead of %r)' \
            % (rv, self)
        rv.request.__exit__(None, None, None)

    def __enter__(self):
        self.push()
        return self

    def __exit__(self, exc_type, exc_value, tb):
        self.pop(exc_value) class CocopotClient(object):
    """
    """
    def __init__(self, application, use_cookies=True):
        self.application = application

    def open(self, *args, **kwargs):
        as_tuple = kwargs.pop('as_tuple', False)
        buffered = kwargs.pop('buffered', False)
        follow_redirects = kwargs.pop('follow_redirects', False)
        builder = EnvironBuilder(*args, **kwargs)
        try:
            environ = builder.get_environ()
        finally:
            builder.close()
        response = self.run_wsgi_app(self.application, environ)

        if as_tuple:
            return environ, response
        return response

    def run_wsgi_app(self, app, environ):
        response = []
        resp_buffer = []
        def start_response(status, headers, exc_info=None):
            if exc_info is not None:
                pass
                #reraise(*exc_info)
            response[:] = [status, headers]
            return resp_buffer.append

        app_rv = app(environ, start_response)
        return  app_rv[0], response[0], response[1]
import pytest
import copy
import traceback
from cocopot import Cocopot, Blueprint, request, g, abort
from cocopot._compat import to_bytes
from cocopot.request import Request
from cocopot.app import RequestContextGlobals, RequestContext
from cocopot.testing import CocopotClient
# -*- coding: utf-8 -*-


env1 = {
    'REQUEST_METHOD':       'GET',
    'SCRIPT_NAME':          '',
    'PATH_INFO':            '/foo/bar',
    'QUERY_STRING':         'a=1&b=2',
    'SERVER_NAME':          'test.cocopot.org',
    'SERVER_PORT':          80,
    'HTTP_HOST':            'test.cocopot.org',
    'SERVER_PROTOCOL':      'http',
    'CONTENT_TYPE':         '',
    'CONTENT_LENGTH':       '0',
    'wsgi.url_scheme':      'http'
}

def test_context_globals():
    contextg = RequestContextGlobals()
    contextg.foo = 'foo'
    assert contextg.get('foo') == 'foo'
    assert 'foo' in contextg
    attrs = [key for key in contextg]
    assert attrs == ['foo']
    s = repr(contextg)

def test_request_context():
    env = copy.deepcopy(env1)
    r = Request(env)
    context = RequestContext(Cocopot(), env, r, foo='foo', bar=123)
    with context:
        assert g.foo == 'foo'
        assert g.bar == 123


def start_response(x, y):
    print((x, y))

def test_basic_app():
    app = Cocopot(__name__)
    assert app.name == 'tests.test_app'

    app.add_url_rule('/hello', 'hello', lambda x: 'ok')

    with pytest.raises(AssertionError):
        app.add_url_rule('/hello', 'hello', lambda x: 'ok')

    @app.endpoint('foo')
    def foo():
        return 'foo'
    app.add_url_rule('/foo', 'foo')

    def error_handler(exception):
        return '500'

    app.register_error_handler(Exception, error_handler)


def test_more_app():
    app = Cocopot()
    assert 'Cocopot' in repr(app)

    @app.before_request
    def before_request1():
        print('before_request')

        g.a = 1