Using aspen instead of homespun wsgi thingy

This commit is contained in:
Dan Buch 2012-05-18 01:33:35 -04:00
parent d6d4cd1ec0
commit b649e10ae8
5 changed files with 76 additions and 152 deletions

View File

@ -1,152 +0,0 @@
from __future__ import print_function
import json
import re
import sys
from pprint import pformat
from traceback import print_exc
from wsgiref.simple_server import make_server
class PersonModel(object):
__people__ = [
{
'name': {
'first': 'Hammy',
'last': 'Spammy',
},
'age': 42,
'id': 1,
},
{
'name': {
'first': 'Sampers',
'last': 'Dancer',
},
'age': 38,
'id': 2
},
]
def __init__(self):
self._index()
def _index(self):
self.__people_by_id__ = dict(((p['id'], p) for p in self.__people__))
def getall(self):
return self.__people__
def get(self, person_id):
return self.__people_by_id__[person_id]
def add(self, person):
person['id'] = len(self.__people__) + 1
self.__people__.append(person)
self._index()
return person['id']
class PersonApp(object):
__routes__ = [
(_m, _k, re.compile('^{}$'.format(_k)), _v) for _m, _k, _v in (
('GET', '/people.json', 'all'),
('POST', '/people.json', 'new'),
('GET', '/people/(.*)\.json', 'get'),
('GET', '/', 'echo')
)
]
def __init__(self):
self.people = PersonModel()
print('Routes = {}'.format(pformat(self.__routes__)))
def __call__(self, environ, start_response):
path = '/' + environ.get('PATH_INFO', '').lstrip('/')
request_method = environ.get('REQUEST_METHOD', 'GET')
environ.update({
'app.path': path,
'app.request_method': request_method,
})
method_name = 'not_found'
for route_req_method, route, route_re, route_method in self.__routes__:
if route_req_method == request_method:
match = route_re.match(path)
if match:
print('Found match: {!r}'.format(match.re.pattern))
environ['app.route_match'] = match
method_name = route_method
break
try:
return getattr(self, method_name)(environ, start_response)
except AttributeError, exc:
print_exc()
return self.not_found(environ, start_response)
def not_found(self, environ, start_response):
print('Nothing matched: {} {!r}'.format(
environ['app.request_method'], environ['app.path']
))
return self._return_json(
start_response, {'error': 'Not Found'},
status='404 Not Found'
)
def bad_request(self, environ, start_response):
return self._return_json(
start_response, {'error': 'Bad Request'},
status='400 Bad Request'
)
def get(self, environ, start_response):
person_id = environ['app.route_match'].group(1)
if not person_id.isdigit():
return self.bad_request(environ, start_response)
person = self.people.get(int(person_id))
return self._return_json(start_response, {'person': person})
def all(self, environ, start_response):
return self._return_json(start_response, self.people.getall())
def new(self, environ, start_response):
person = json.loads(
environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
)
person_id = self.people.add(person)
return self._return_json(
start_response, {}, status='201 Created',
extra_headers=[
('location', '/people/{}.json'.format(person_id))
]
)
def echo(self, environ, start_response):
return self._return_json(start_response, {'here?': 'yup'})
def _return_json(self, start_response, json_dict, status='200 OK',
extra_headers=()):
body = json.dumps(json_dict)
start_response(status, [
('content-type', 'application/x-json'),
('content-length', str(len(body)))
] + list(extra_headers))
return [body]
def main():
server = make_server('0.0.0.0', 9282, PersonApp())
try:
print('Serving on 0.0.0.0:9282')
server.serve_forever()
return 1
except KeyboardInterrupt:
return 0
if __name__ == '__main__':
sys.exit(main())

42
ares/person_model.py Normal file
View File

@ -0,0 +1,42 @@
class PersonModel(object):
_people = [
{
'name': {
'first': 'Hammy',
'last': 'Spammy',
},
'age': 42,
'id': 1,
},
{
'name': {
'first': 'Sampers',
'last': 'Dancer',
},
'age': 38,
'id': 2
},
]
def __init__(self):
self._index()
def _index(self):
self._people_by_id = dict(((p['id'], p) for p in self._people))
def getall(self):
return self._people
def get(self, person_id):
return self._people_by_id[person_id]
def add(self, person):
if None in (person.get('name'), person.get('age')):
raise ValueError('Missing required fields!: {}'.format(person))
person['id'] = len(self._people) + 1
self._people.append(person)
self._index()
return person['id']

8
ares/serve Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
which aspen >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "You need to 'pip install aspen'"
exit 1
fi
cd $(dirname $(readlink -f $0))
exec aspen -w ./www -a '0.0.0.0:9282'

20
ares/www/people.json Normal file
View File

@ -0,0 +1,20 @@
import json
from person_model import PersonModel
from aspen import Response
__people__ = PersonModel()
if GET:
response.body = __people__.getall()
elif POST:
person = json.loads(
request.body.s_iter.read(int(request.headers['Content-Length']))
)['person']
person_id = __people__.add(person)
response.headers['Location'] = '/people/{}.json'.format(person_id)
response.body = {}
raise Response(201)
# vim:filetype=python

6
ares/www/people/%id.json Normal file
View File

@ -0,0 +1,6 @@
from person_model import PersonModel
__people__ = PersonModel()
response.body = {'person': __people__.get(int(path['id']))}
# vim:filetype=python