Skip to content

Commit 334eba1

Browse files
committed
* add answer for week 4 homework
1 parent 7be7d8c commit 334eba1

2 files changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
3+
class BookDB():
4+
def titles(self):
5+
titles = [dict(id=id, title=database[id]['title']) for id in database.keys()]
6+
return titles
7+
8+
def title_info(self, id):
9+
return database[id]
10+
11+
12+
# let's pretend we're getting this information from a database somewhere
13+
database = {
14+
'id1' : {'title' : 'CherryPy Essentials: Rapid Python Web Application Development',
15+
'isbn' : '978-1904811848',
16+
'publisher' : 'Packt Publishing (March 31, 2007)',
17+
'author' : 'Sylvain Hellegouarch',
18+
},
19+
'id2' : {'title' : 'Python for Software Design: How to Think Like a Computer Scientist',
20+
'isbn' : '978-0521725965',
21+
'publisher' : 'Cambridge University Press; 1 edition (March 16, 2009)',
22+
'author' : 'Allen B. Downey',
23+
},
24+
'id3' : {'title' : 'Foundations of Python Network Programming',
25+
'isbn' : '978-1430230038',
26+
'publisher' : 'Apress; 2 edition (December 21, 2010)',
27+
'author' : 'John Goerzen',
28+
},
29+
'id4' : {'title' : 'Python Cookbook, Second Edition',
30+
'isbn' : '978-0-596-00797-3',
31+
'publisher' : 'O''Reilly Media',
32+
'author' : 'Alex Martelli, Anna Ravenscroft, David Ascher',
33+
},
34+
'id5' : {'title' : 'The Pragmatic Programmer: From Journeyman to Master',
35+
'isbn' : '978-0201616224',
36+
'publisher' : 'Addison-Wesley Professional (October 30, 1999)',
37+
'author' : 'Andrew Hunt, David Thomas',
38+
},
39+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/python
2+
import re
3+
4+
5+
class MyApplication(object):
6+
page_template = """
7+
<!DOCTYPE html>
8+
<html>
9+
<head><title>%(page_title)s</title></head>
10+
<body>
11+
%(page_body)s
12+
</body>
13+
</html>
14+
"""
15+
16+
def __init__(self, db, urls):
17+
self.db = db
18+
self.urls = urls
19+
20+
def __call__(self, environ, start_response):
21+
headers = [('Content-type', 'text/html')]
22+
try:
23+
path = environ.get('PATH_INFO', None)
24+
if path is None:
25+
raise NameError
26+
func, args = self._get_callable(path.lstrip('/'))
27+
body = func(*args)
28+
status = "200 OK"
29+
headers.append(('Content-length', str(len(body))))
30+
except NameError:
31+
status = "404 Not Found"
32+
body = self.page_template % {'page_title': 'Not Found',
33+
'page_body': '404 Not Found'}
34+
except ValueError:
35+
status = "501 Not Implemented"
36+
body = 'That URI is not implemented'
37+
except:
38+
status = "500 Internal Server Error"
39+
body = 'There has been an error, try again later'
40+
finally:
41+
start_response(status, headers)
42+
return [body]
43+
44+
def books(self):
45+
core = ['<h1>Book Database</h1>',
46+
'<ul>']
47+
tmpl = '<li><a href="book/%s">%s</a></li>'
48+
for book_id, book_data in self.db.items():
49+
core.append(tmpl % (book_id, book_data['title']))
50+
core.append('</ul>')
51+
body = "\n".join(core)
52+
context = {'page_title': "Book Database",
53+
'page_body': body}
54+
return self.page_template % context
55+
56+
def book(self, id):
57+
tmpl = """
58+
<h1>%(title)s</h1>
59+
<dl>
60+
<dt>ISBN</dt>
61+
<dd>%(isbn)s</dd>
62+
<dt>Author(s)</dt>
63+
<dd>%(author)s</dd>
64+
<dt>Publisher</dt>
65+
<dd>%(publisher)s</dd>
66+
</dl>
67+
<p><a href="../">More Books</a></p>
68+
"""
69+
book = self.db.get(id, None)
70+
if book is None:
71+
raise NameError
72+
title = "Book Database: %s" % book['isbn']
73+
context = {'page_title': title,
74+
'page_body': tmpl % book}
75+
return self.page_template % context
76+
77+
def _get_callable(self, path):
78+
for regexp, funcname in self.urls:
79+
match = re.match(regexp, path)
80+
# if there is no match for the path, it's a 404 error
81+
if match is None:
82+
continue
83+
# if the match names a method that does not exist, its a 501
84+
func = getattr(self, funcname, None)
85+
if func is None:
86+
raise ValueError
87+
# get all subgroup matches from the regexp as args
88+
args = match.groups([])
89+
return func, args
90+
raise NameError
91+
92+
93+
94+
URLS = [(r'^$', 'books'),
95+
(r'^book/(id[\d]{1,2})$', 'book'), ]
96+
97+
98+
if __name__ == '__main__':
99+
# this block will be called when the script is run directly
100+
from wsgiref.simple_server import make_server
101+
import bookdb
102+
application = MyApplication(bookdb.database, URLS)
103+
srv = make_server('localhost', 8080, application)
104+
srv.serve_forever()
105+
else:
106+
# this block will be called when the script is run on a VM via mod_wsgi
107+
#
108+
# we need to place bookdb.py in some location on the server, and then
109+
# add that location to the sys.path variable in order to allow mod_wsgi
110+
# to import bookdb
111+
#
112+
# in addition, apache must be configured with the following:
113+
# WSGIScriptAlias /books /path/on/server/to/homework.py
114+
import sys
115+
sys.path.append('/path/to/directory/containing/bookdb/on/server')
116+
import bookdb
117+
application = MyApplication(bookdb.database, URLS)

0 commit comments

Comments
 (0)