Skip to content

Commit 5105303

Browse files
committed
2 parents a9a5af4 + 3b20be2 commit 5105303

34 files changed

+2781
-71
lines changed
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)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/python
2+
import cgi
3+
import cgitb
4+
cgitb.enable()
5+
import os
6+
import datetime
7+
8+
9+
print "Content-Type: text/html"
10+
print
11+
12+
body = """<html>
13+
<head>
14+
<title>Lab 1 - CGI experiments</title>
15+
</head>
16+
<body>
17+
The server name is %s. (if an IP address, then a DNS problem) <br>
18+
<br>
19+
The server address is %s:%s.<br>
20+
<br>
21+
Your hostname is %s. <br>
22+
<br>
23+
You are coming from %s:%s.<br>
24+
<br>
25+
The currenly executing script is %s<br>
26+
<br>
27+
The request arrived at %s<br>
28+
29+
</body>
30+
</html>""" % (
31+
os.environ.get('SERVER_NAME', 'Unset'), # Server Hostname
32+
os.environ.get('SERVER_ADDR', 'Unset'), # server IP
33+
os.environ.get('SERVER_PORT', 'Unset'), # server port
34+
os.environ.get('REMOTE_HOST', 'Unset'), # client hostname
35+
os.environ.get('REMOTE_ADDR', 'Unset'), # client IP
36+
os.environ.get('REMOTE_PORT', 'Unset'), # client port
37+
os.environ.get('SCRIPT_NAME', 'Unset'), # this script name
38+
datetime.datetime.now().isoformat(), # time
39+
)
40+
41+
print body,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/python
2+
import datetime
3+
4+
body = """<html>
5+
<head>
6+
<title>Lab A - CGI experiments</title>
7+
</head>
8+
<body>
9+
10+
The server name is %s. (if an IP address, then a DNS problem) <br>
11+
<br>
12+
The server address is %s:%s.<br>
13+
<br>
14+
You are coming from %s:%s.<br>
15+
<br>
16+
The URI we are serving is %s.<br>
17+
<br>
18+
The request arrived at %s<br>
19+
20+
</body>
21+
</html>"""
22+
23+
def application(environ, start_response):
24+
response_body = body % (
25+
environ.get('SERVER_NAME', 'Unset'), # server name
26+
environ.get('SERVER_ADDR', 'Unset'), # server IP
27+
environ.get('SERVER_PORT', 'Unset'), # server port
28+
environ.get('REMOTE_ADDR', 'Unset'), # client IP
29+
environ.get('REMOTE_PORT', 'Unset'), # client port
30+
environ.get('SCRIPT_NAME', 'Unset'), # this script name
31+
datetime.datetime.now().isoformat(), # time
32+
)
33+
status = '200 OK'
34+
35+
response_headers = [('Content-Type', 'text/html'),
36+
('Content-Length', str(len(response_body)))]
37+
start_response(status, response_headers)
38+
39+
return [response_body]
40+
41+
if __name__ == '__main__':
42+
from wsgiref.simple_server import make_server
43+
srv = make_server('localhost', 8080, application)
44+
srv.serve_forever()

assignments/week03/athome/assignment.txt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,13 @@ interests, the Web has tools. Put them together to make something.
77
Place the following in the ``assignments/week03/athome`` directory and make a
88
pull request:
99

10-
.. class:: small
11-
1210
A textual description of your mashup.
1311
What data sources did you scan, what tools did you use, what is the
1412
outcome you wanted to create?
1513

16-
.. class:: small
17-
1814
Your source code.
1915
Give me an executable python script that I can run to get output.
2016

21-
.. class:: small
22-
2317
Any instructions I need.
2418
If I need instructions beyond 'python myscript.py' to get the right
2519
output, let me know.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Using what you've learned this week, Attempt the following:
2+
3+
* Create a small, multi-page WSGI application
4+
* Use ``assignments/week04/athome/bookdb.py`` as a data source
5+
* Your app index page should list the books in the db
6+
* Each listing should supply a link to a detail page
7+
* Each detail page should list information about the book
8+
9+
HINT:
10+
11+
Use the Armin Ronacher reading from the class outline as a source for hints:
12+
http://lucumr.pocoo.org/2007/5/21/getting-started-with-wsgi/
13+
14+
Submitting Your Work:
15+
16+
This week we are going to do something a bit different. Get your application
17+
running on your VM. Then add the following to ``assignments/week04/athome``
18+
and submit a pull request:
19+
20+
* A README.txt file containing the URL I can visit to see your application.
21+
You can also put questions or comments in this file.
22+
23+
* Your source code, whatever is up on your VM.
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+
}

assignments/week04/lab/README.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Start a test CGI server by running:
2+
python -m CGIHTTPServer
3+
from the current directory and then navigating to:
4+
http://localhost:8000/
5+
in your web browser.
6+
7+
You can also set the port manually by passing it on the command line:
8+
python -m CGIHTTPServer 50000
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/python
2+
import cgi
3+
import cgitb
4+
import time
5+
import json
6+
7+
cgitb.enable()
8+
9+
data = {'time' : time.time()
10+
}
11+
12+
fs = cgi.FieldStorage()
13+
a = fs['a']
14+
b = fs['b']
15+
a = int(a.value)
16+
b = int(b.value)
17+
result = a + b
18+
data['result'] = result
19+
20+
print "Content-Type: application/json"
21+
print
22+
print json.dumps(data, indent=4)
23+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/python
2+
import time
3+
import datetime
4+
5+
now = time.time()
6+
7+
html = """<html>
8+
<head></head>
9+
<body>
10+
<p>Here is the time: %s</p>
11+
<p>and again: %s</p>
12+
<p>and in ISO format: %s</p>
13+
</body>
14+
</html>
15+
""" % (now,
16+
datetime.datetime.fromtimestamp(now),
17+
datetime.datetime.fromtimestamp(now).isoformat())
18+
19+
print "Content-Type: text/html"
20+
print "Content-length: %s" % len(html)
21+
print
22+
print html

0 commit comments

Comments
 (0)