├── requirements.txt ├── .gitignore ├── README.rst ├── messager.py ├── simple.py ├── simple_longpoll.py ├── better_responses.py ├── pusher.py └── LICENSE /requirements.txt: -------------------------------------------------------------------------------- 1 | gevent 2 | redis 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | .DS_Store 3 | *.pyc 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Supporting materials for my blog post on WSGI long-polling apps with gevent at http://toastdriven.com/blog/2011/jul/31/gevent-long-polling-you/. 2 | -------------------------------------------------------------------------------- /messager.py: -------------------------------------------------------------------------------- 1 | import redis 2 | 3 | server = redis.Redis(host='localhost', port=6379, db=0) 4 | 5 | while True: 6 | message = raw_input("What to say: ") 7 | server.publish('messages', message) 8 | 9 | if message == 'quit': 10 | break 11 | -------------------------------------------------------------------------------- /simple.py: -------------------------------------------------------------------------------- 1 | from gevent import pywsgi 2 | 3 | 4 | def handle(environ, start_response): 5 | start_response('200 OK', [('Content-Type', 'text/html')]) 6 | yield '

Hi There

' 7 | 8 | 9 | server = pywsgi.WSGIServer(('127.0.0.1', 1234), handle) 10 | print "Serving on http://127.0.0.1:1234..." 11 | server.serve_forever() 12 | -------------------------------------------------------------------------------- /simple_longpoll.py: -------------------------------------------------------------------------------- 1 | import gevent 2 | from gevent import pywsgi 3 | 4 | 5 | def handle(environ, start_response): 6 | start_response('200 OK', [('Content-Type', 'text/html')]) 7 | yield ' ' * 1200 8 | yield '

Hi ' 9 | gevent.sleep(10) 10 | yield 'There

' 11 | 12 | 13 | server = pywsgi.WSGIServer(('127.0.0.1', 1234), handle) 14 | print "Serving on http://127.0.0.1:1234..." 15 | server.serve_forever() 16 | -------------------------------------------------------------------------------- /better_responses.py: -------------------------------------------------------------------------------- 1 | from gevent import monkey 2 | monkey.patch_all() 3 | 4 | import datetime 5 | import time 6 | from gevent import Greenlet 7 | from gevent import pywsgi 8 | from gevent import queue 9 | 10 | 11 | def current_time(body): 12 | current = start = datetime.datetime.now() 13 | end = start + datetime.timedelta(seconds=60) 14 | 15 | while current < end: 16 | current = datetime.datetime.now() 17 | body.put('
%s
' % current.strftime("%Y-%m-%d %I:%M:%S")) 18 | time.sleep(1) 19 | 20 | body.put('') 21 | body.put(StopIteration) 22 | 23 | 24 | def handle(environ, start_response): 25 | start_response('200 OK', [('Content-Type', 'text/html')]) 26 | body = queue.Queue() 27 | body.put(' ' * 1000) 28 | body.put("

Current Time:

") 29 | g = Greenlet.spawn(current_time, body) 30 | return body 31 | 32 | 33 | server = pywsgi.WSGIServer(('127.0.0.1', 1234), handle) 34 | print "Serving on http://127.0.0.1:1234..." 35 | server.serve_forever() 36 | -------------------------------------------------------------------------------- /pusher.py: -------------------------------------------------------------------------------- 1 | from gevent import monkey 2 | monkey.patch_all() 3 | 4 | import gevent 5 | from gevent import pywsgi 6 | from gevent import queue 7 | import redis 8 | 9 | 10 | def process_messages(body): 11 | server = redis.Redis(host='localhost', port=6379, db=0) 12 | client = server.pubsub() 13 | client.subscribe('messages') 14 | messages = client.listen() 15 | 16 | while True: 17 | message = messages.next() 18 | print "Saw: %s" % message['data'] 19 | 20 | if message['data'] == 'quit': 21 | body.put("Server closed.") 22 | body.put(StopIteration) 23 | break 24 | 25 | body.put("
%s
\n" % message['data']) 26 | 27 | 28 | def handle(environ, start_response): 29 | start_response('200 OK', [('Content-Type', 'text/html')]) 30 | body = queue.Queue() 31 | body.put(' ' * 1000) 32 | body.put("

Messages:

") 33 | gevent.spawn(process_messages, body) 34 | return body 35 | 36 | 37 | server = pywsgi.WSGIServer(('127.0.0.1', 1234), handle) 38 | print "Serving on http://127.0.0.1:1234..." 39 | server.serve_forever() 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Daniel Lindsley. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of wsgi_longpolling nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | --------------------------------------------------------------------------------