The PEAK Developers' Center   Diff for "AsyncWSGISketch" UserPreferences
 
HelpContents Search Diffs Info Edit Subscribe XML Print View
Ignore changes in the amount of whitespace

Differences between version dated 2011-01-08 15:53:16 and 2011-01-10 09:58:13 (spanning 3 versions)

Deletions are marked like this.
Additions are marked like this.

#!python
"""Some sketches of implementing a WSGI 2 async API, in both sync and async servers"""
 
def example_app(environ):
    yield '200 OK', [('Content-type','text/plain')], [b'hello world!']
 
 
def example_middleware(app):
 
    def wrapped(environ):
        # middleware can modify environ here
        status, headers, body = yield app(environ)
 
        # and modify or replace s, h, body here
        body = process(body) # ...only if you need to alter it
 
        yield status, headers, body
 
    def process(body_iter):
        # This function is only needed if the middleware wants to read
        # or modify the body in some way...
        while True:
            chunk = yield body_iter # fetch the next chunk from the body
            if chunk is None:
                break
            # process/modify chunk here, then yield it to the server
            yield chunk
 
    return wrapped
 
 
def WSGI2(app):
    """Decorator that synchronously emulates WSGI2 futures under WSGI 1"""
    def wsgi1_app(environ, start_response):
 
        def process_response(shb):
            s, h, body = shb
            write = start_response(s, h)

                         return routine.RETURN(yielded)
                else:
                    return base_trampoline(routine, yielded)
 
            Coroutine(b, body_trampoline)
            if not [body has send/throw methods]:
                body = (item for item in body)
            Coroutine(body, body_trampoline)()
 
        def app_trampoline(routine, yielded):
            if type(yielded) is tuple:

                raise TypeError("Not a future, result, or generator:", yielded)
 
        # [add an executor to environ here]
        Coroutine(app(environ), app_trampoline, process_response)
        Coroutine(app(environ), app_trampoline, process_response)()
        return []
 
    return wsgi1_app

    def process_response(shb):
        s, h, body = shb
        [do an asynchronous start_response analog here]
 
        def body_trampoline(routine, yielded):
            if type(yielded) is bytes:
                # only accept from outermost middleware

            else:
                return base_trampoline(routine, yielded)
 
        Coroutine(body, body_trampoline, [optional termination callback])
 
        if not [body has send/throw methods]:
            body = (item for item in body)
        Coroutine(body, body_trampoline, [optional termination callback])()
            
    def app_trampoline(routine, yielded):
        if type(yielded) is tuple:
            return routine.RETURN(yielded)

            raise TypeError("Not a future, result, or generator:", yielded)
 
    # [add an executor to environ here]
    Coroutine(app(environ), app_trampoline, process_response)
    Coroutine(app(environ), app_trampoline, process_response)()
 
 
class Coroutine:

        self.stack = [iterator]
        self.trampoline = trampoline
        self.callback = callback
        self()
 
    PAUSE = ()
 

            return self.RESUME(func(*args, **kw))
        except BaseException:
            return self.RAISE(sys.exc_info())
        
    def close():
        while self.stack:
            self.stack.pop().close()
 
    def __call__(self, value=None, exc_info=()):
        stack = self.stack

                    return rv
 
        # Coroutine is entirely finished when the stack is empty
        if exc_info:
            try:
                raise exc_info[1]
            finally:
                exc_info = ()
        return self.callback(value)
}}}

PythonPowered
ShowText of this page
EditText of this page
FindPage by browsing, title search , text search or an index
Or try one of these actions: AttachFile, DeletePage, LikePages, LocalSiteMap, SpellCheck