Refactory in contexts.

This commit is contained in:
Rafael Caricio 2011-08-19 11:57:24 -03:00
parent 588c84f64f
commit 728dee527d
2 changed files with 149 additions and 129 deletions

View file

@ -9,142 +9,14 @@
# Copyright (c) 2011 Rafael Caricio rafael@caricio.com
import os
import sys
import urllib2
from threading import Thread
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from pyvows import Vows
from django.http import HttpRequest
from django.core.handlers.wsgi import WSGIHandler
from django_pyvows.assertions import Url, Model, Template
from django_pyvows.server import DjangoServer
class WSGIRequestHandler(BaseHTTPRequestHandler):
"""A request handler that implements WSGI dispatching."""
@property
def server_version(self):
return 'pyVowsServer'
def make_environ(self):
if '?' in self.path:
path_info, query = self.path.split('?', 1)
else:
path_info = self.path
query = ''
environ = {
'wsgi.version': (1, 0),
'wsgi.url_scheme': 'http',
'wsgi.input': self.rfile,
'wsgi.errors': sys.stderr,
'wsgi.multithread': False,
'wsgi.multiprocess': False,
'wsgi.run_once': False,
'SERVER_SOFTWARE': self.server_version,
'REQUEST_METHOD': self.command,
'SCRIPT_NAME': '',
'PATH_INFO': urllib2.unquote(path_info),
'QUERY_STRING': query,
'CONTENT_TYPE': self.headers.get('Content-Type', ''),
'CONTENT_LENGTH': self.headers.get('Content-Length', ''),
'REMOTE_ADDR': self.client_address[0],
'REMOTE_PORT': self.client_address[1],
'SERVER_NAME': self.server.server_address[0],
'SERVER_PORT': str(self.server.server_address[1]),
'SERVER_PROTOCOL': self.request_version
}
for key, value in self.headers.items():
key = 'HTTP_' + key.upper().replace('-', '_')
if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
environ[key] = value
return environ
def run_wsgi(self):
app = self.server.app
environ = self.make_environ()
headers_set = []
headers_sent = []
def write(data):
assert headers_set, 'write() before start_response'
if not headers_sent:
status, response_headers = headers_sent[:] = headers_set
code, msg = status.split(None, 1)
self.send_response(int(code), msg)
header_keys = set()
for key, value in response_headers:
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if 'content-length' not in header_keys:
self.close_connection = True
self.send_header('Connection', 'close')
if 'server' not in header_keys:
self.send_header('Server', self.version_string())
if 'date' not in header_keys:
self.send_header('Date', self.date_time_string())
self.end_headers()
assert type(data) is str, 'applications must write bytes'
self.wfile.write(data)
self.wfile.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
raise exc_info[0], exc_info[1], exc_info[2]
finally:
exc_info = None
elif headers_set:
raise AssertionError('Headers already set')
headers_set[:] = [status, response_headers]
return write
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
# make sure the headers are sent
if not headers_sent:
write('')
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None
def handle_one_request(self):
self.raw_requestline = self.rfile.readline()
if self.parse_request():
return self.run_wsgi()
def log_request(self, *args, **kwargs):
pass
def log_error(self, *args):
pass
def log_message(self, *args):
pass
class DjangoServer(HTTPServer, object):
def __init__(self, host, port):
HTTPServer.__init__(self, (host, int(port)), WSGIRequestHandler)
self.app = WSGIHandler()
def start(self):
self.server_activate()
def make_response():
while True:
self.handle_request()
self.thr = Thread(target=make_response)
self.thr.daemon = True
self.thr.start()
class DjangoContext(Vows.Context):

148
django_pyvows/server.py Normal file
View file

@ -0,0 +1,148 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# django-pyvows extensions
# https://github.com/rafaelcaricio/django-pyvows
# Licensed under the MIT license:
# http://www.opensource.org/licenses/mit-license
# Copyright (c) 2011 Rafael Caricio rafael@caricio.com
import sys
import urllib2
from threading import Thread
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from pyvows import Vows
from django.http import HttpRequest
from django.core.handlers.wsgi import WSGIHandler
from django_pyvows.assertions import Url, Model, Template
class WSGIRequestHandler(BaseHTTPRequestHandler):
"""A request handler that implements WSGI dispatching."""
@property
def server_version(self):
return 'pyVowsServer'
def make_environ(self):
if '?' in self.path:
path_info, query = self.path.split('?', 1)
else:
path_info = self.path
query = ''
environ = {
'wsgi.version': (1, 0),
'wsgi.url_scheme': 'http',
'wsgi.input': self.rfile,
'wsgi.errors': sys.stderr,
'wsgi.multithread': False,
'wsgi.multiprocess': False,
'wsgi.run_once': False,
'SERVER_SOFTWARE': self.server_version,
'REQUEST_METHOD': self.command,
'SCRIPT_NAME': '',
'PATH_INFO': urllib2.unquote(path_info),
'QUERY_STRING': query,
'CONTENT_TYPE': self.headers.get('Content-Type', ''),
'CONTENT_LENGTH': self.headers.get('Content-Length', ''),
'REMOTE_ADDR': self.client_address[0],
'REMOTE_PORT': self.client_address[1],
'SERVER_NAME': self.server.server_address[0],
'SERVER_PORT': str(self.server.server_address[1]),
'SERVER_PROTOCOL': self.request_version
}
for key, value in self.headers.items():
key = 'HTTP_' + key.upper().replace('-', '_')
if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
environ[key] = value
return environ
def run_wsgi(self):
app = self.server.app
environ = self.make_environ()
headers_set = []
headers_sent = []
def write(data):
assert headers_set, 'write() before start_response'
if not headers_sent:
status, response_headers = headers_sent[:] = headers_set
code, msg = status.split(None, 1)
self.send_response(int(code), msg)
header_keys = set()
for key, value in response_headers:
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if 'content-length' not in header_keys:
self.close_connection = True
self.send_header('Connection', 'close')
if 'server' not in header_keys:
self.send_header('Server', self.version_string())
if 'date' not in header_keys:
self.send_header('Date', self.date_time_string())
self.end_headers()
assert type(data) is str, 'applications must write bytes'
self.wfile.write(data)
self.wfile.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
raise exc_info[0], exc_info[1], exc_info[2]
finally:
exc_info = None
elif headers_set:
raise AssertionError('Headers already set')
headers_set[:] = [status, response_headers]
return write
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
# make sure the headers are sent
if not headers_sent:
write('')
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None
def handle_one_request(self):
self.raw_requestline = self.rfile.readline()
if self.parse_request():
return self.run_wsgi()
def log_request(self, *args, **kwargs):
pass
def log_error(self, *args):
pass
def log_message(self, *args):
pass
class DjangoServer(HTTPServer, object):
def __init__(self, host, port):
HTTPServer.__init__(self, (host, int(port)), WSGIRequestHandler)
self.app = WSGIHandler()
def start(self):
self.server_activate()
def make_response():
while True:
self.handle_request()
self.thr = Thread(target=make_response)
self.thr.daemon = True
self.thr.start()