diff --git a/WebProgramming/Chat/README b/WebProgramming/Chat/README new file mode 100644 index 0000000..e69de29 diff --git a/WebProgramming/Chat/chat_client.py b/WebProgramming/Chat/chat_client.py new file mode 100644 index 0000000..628790e --- /dev/null +++ b/WebProgramming/Chat/chat_client.py @@ -0,0 +1,48 @@ +""" +echo client, usage: + + python echo_client.py + +Both host and port are optional, defaults: localhost 50000 +host must be present if you want to provide port +""" + +import socket +import sys +import select + +host = 'localhost' +port = 50003 +size = 1024 +text = '' +timeout = 10 # seconds + +nargs = len(sys.argv) +if nargs > 1: + host = sys.argv[1] +if nargs > 2: + port = int(sys.argv[2]) + +#open socket for sending to the server +s = socket.socket(socket.AF_INET, + socket.SOCK_STREAM) +s.connect((host,port)) + +input = [s, sys.stdin] + +print "Enter text to send : " +while True : + inputready,outputready,exceptready = select.select(input,[],[],timeout) + for selectInput in inputready: + if selectInput == sys.stdin: + text = str(raw_input('> ')) + if text : + s.send(text) + else : + s.close() + break + if selectInput == s: + text = s.recv(size) + print text + + diff --git a/WebProgramming/Chat/chat_server.py b/WebProgramming/Chat/chat_server.py new file mode 100644 index 0000000..166d70f --- /dev/null +++ b/WebProgramming/Chat/chat_server.py @@ -0,0 +1,78 @@ +""" +Based on Daniel Zappala's http://ilab.cs.byu.edu/python/code/echoserver-select.py +Add print statements to show what's going on. +Use SO_REUSEADDR to avoid 'Address already in use' errors +Add timeout +make style similar to our recho_clien + +An echo server that uses select to handle multiple clients at a time. +Entering any line of input at the terminal will exit the server. +""" + +import select +import socket +import sys +import time +import datetime + +host = '' +port = 50003 # different port than other samples, all can run on same server + +if len(sys.argv) > 1: + port = int(sys.argv[1]) + +backlog = 5 +size = 1024 + +server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# Release listener socket immediately when program exits, +# avoid socket.error: [Errno 48] Address already in use +server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + +server.bind((host,port)) + +print 'echo_server listening on port %s, to exit type return ' % port +server.listen(backlog) + +timeout = 10 # seconds +input = [server,sys.stdin] +clients = [] +running = True +while running: + inputready,outputready,exceptready = select.select(input,[],[],timeout) + + # timeout + if not inputready: + print 'Server running at %s' % datetime.datetime.now() + + for s in inputready: + + if s == server: + # handle the server socket + client, address = server.accept() + input.append(client) + clients.append(client) + print 'accepted connection from', address + + elif s == sys.stdin: + # handle standard input + junk = sys.stdin.readline() + running = False + print 'Input %s from stdin, exiting.' % junk.strip('\n') + + elif s: # client socket + data = s.recv(size) + print '%s: %s' % (s.getpeername(), data.strip('\n')) + if data: + for c in clients : + if c != s : + print 'sending : %s: %s' % (c.getpeername(), data.strip('\n')) + c.send('%s: %s' % (s.getpeername(), data)) + else: + s.close() + print 'closed connection' + input.remove(s) + clients.remove(s) + +s.close() diff --git a/WebProgramming/Chat/hello.py b/WebProgramming/Chat/hello.py new file mode 100755 index 0000000..da6849a --- /dev/null +++ b/WebProgramming/Chat/hello.py @@ -0,0 +1 @@ +print "hello world" diff --git a/WebProgramming/Echo/echo_client.py b/WebProgramming/Echo/echo_client.py new file mode 100644 index 0000000..7794598 --- /dev/null +++ b/WebProgramming/Echo/echo_client.py @@ -0,0 +1,30 @@ +""" +echo client, usage: + + python echo_client.py + +Both host and port are optional, defaults: localhost 50000 +host must be present if you want to provide port +""" + +import socket +import sys + +host = 'localhost' +port = 50000 +size = 1024 + +nargs = len(sys.argv) +if nargs > 1: + host = sys.argv[1] +if nargs > 2: + port = int(sys.argv[2]) + +s = socket.socket(socket.AF_INET, + socket.SOCK_STREAM) +s.connect((host,port)) +s.send('Hello, world') +data = s.recv(size) +s.close() +print 'from (%s,%s) %s' % (host, port, data) + diff --git a/WebProgramming/Echo/echo_server.py b/WebProgramming/Echo/echo_server.py new file mode 100644 index 0000000..c6a91c4 --- /dev/null +++ b/WebProgramming/Echo/echo_server.py @@ -0,0 +1,39 @@ +""" +echo server, usage: + + python echo_server.py + +Port is optional, default: 50000 +""" + +import socket +import sys + +host = '' +port = 50000 + +if len(sys.argv) > 1: + port = int(sys.argv[1]) + +backlog = 5 +size = 1024 + +# server's listener socket +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# Release listener socket immediately when program exits, +# avoid socket.error: [Errno 48] Address already in use +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + +s.bind((host,port)) + +print 'echo_server listening on port', port +s.listen(backlog) + +while True: + client, address = s.accept() + data = client.recv(size) + if data: + client.send('mark665: %s' % data) + print 'from %s: %s' % (address, data) + client.close() diff --git a/WebProgramming/FlaskLab/echo_flask.py b/WebProgramming/FlaskLab/echo_flask.py new file mode 100644 index 0000000..6c06125 --- /dev/null +++ b/WebProgramming/FlaskLab/echo_flask.py @@ -0,0 +1,39 @@ +""" +Minimal Flask + forms demo + +Send HTML page that echoes message from HTTP request +To get started, point browser at echo_flask.html +""" + +from flask import Flask, render_template, request +import copy + +# No need for message page +# Flask converts view function return string to HTML page + +app = Flask(__name__) + +app.debug = True # development only - remove on production machines + +messages = [] + +# View functions generate HTTP responses including HTML pages and headers + +@app.route('/echo_flask.html') +def form(): + return render_template('form.html') +# return form_page + +@app.route('/echo_flask.py') +def message_page(): + # Flask Quickstart suggests request.form should work, but here it is empty + # Flask converts return string to HTML page + messages.insert(0,request.args['message']) + return render_template('response.html', messages=copy.deepcopy(messages)) +# return 'Message: %s' % ("
Previous Message : ".join(messages)) + +# No function needed for other routes - Flask will send 404 page + +if __name__ == '__main__': + app.run() + diff --git a/WebProgramming/FlaskLab/echo_tests.py b/WebProgramming/FlaskLab/echo_tests.py new file mode 100644 index 0000000..71c4bf1 --- /dev/null +++ b/WebProgramming/FlaskLab/echo_tests.py @@ -0,0 +1,37 @@ +""" +Demonstrate Flask test support: test without server +""" + +import echo_flask as e + +# Flask test support +tc = e.app.test_client() +print tc +print +print + +# should respond with 404 +r = tc.get('/') +print r +print r.data +print +print + +# should respond with form +r = tc.get('/echo_flask.html') +print r +print r.data +print +print + +# should respond with message page +r = tc.get('/echo_flask.py?message=Hello') +print r +print r.headers +print r.data +print +print + +# This will fail if application isn't working +#assert 'Hello' in r.data # demonstrate success +assert 'Goodbye' in r.data # demonstrate failure diff --git a/WebProgramming/FlaskLab/flask_lab.txt b/WebProgramming/FlaskLab/flask_lab.txt new file mode 100644 index 0000000..7742c29 --- /dev/null +++ b/WebProgramming/FlaskLab/flask_lab.txt @@ -0,0 +1,15 @@ +flask_lab.txt ++-- + +Week 7 Lab: Flask + + Install Flask on your computer + + Revise echo_flask.py to show all the messages received since startup. + Suggestion: experiment with formatting the output page. What if + you return a big string? HTML? Does the templating system help? + + To install, consult http://flask.pocoo.org/docs/installation/ + -- but I didn't take their advice. I do not recommend virtualenv + I do not have pip installed so I tried sudo easy_install Flask + worked for me, installed Flask 0.8, Jinja2 2.6, Werkzeug 0.8.3 diff --git a/WebProgramming/FlaskLab/templates/form.html b/WebProgramming/FlaskLab/templates/form.html new file mode 100644 index 0000000..fa362f0 --- /dev/null +++ b/WebProgramming/FlaskLab/templates/form.html @@ -0,0 +1,10 @@ + +Echo request + + +
+Message: + +
+ + diff --git a/WebProgramming/FlaskLab/templates/response.html b/WebProgramming/FlaskLab/templates/response.html new file mode 100644 index 0000000..9061167 --- /dev/null +++ b/WebProgramming/FlaskLab/templates/response.html @@ -0,0 +1,16 @@ + +Echo request + + +
+

+Message: +{{ messages[0] }} +

+{% for message in messages[1:] %} +

Old Message : {{ message }}

+{% endfor %} +
+ + + diff --git a/WebProgramming/ReEcho/reecho_client.py b/WebProgramming/ReEcho/reecho_client.py new file mode 100644 index 0000000..28f1ee0 --- /dev/null +++ b/WebProgramming/ReEcho/reecho_client.py @@ -0,0 +1,38 @@ +""" +echo client, usage: + + python echo_client.py + +Both host and port are optional, defaults: localhost 50000 +host must be present if you want to provide port +""" + +import socket +import sys + +host = 'localhost' +port = 50001 +size = 1024 +text = '' + +nargs = len(sys.argv) +if nargs > 1: + host = sys.argv[1] +if nargs > 2: + port = int(sys.argv[2]) + +s = socket.socket(socket.AF_INET, + socket.SOCK_STREAM) +s.connect((host,port)) +print 'Connection accepted by (%s,%s)' % (host, port) +print "Enter test to send : " +while True : + text = str(raw_input('> ')) + if text : + s.send(text) + data = s.recv(size) + print data + else : + s.close() + print 'from (%s,%s) %s' % (host, port, data) + break diff --git a/WebProgramming/ReEcho/reecho_server.py b/WebProgramming/ReEcho/reecho_server.py new file mode 100644 index 0000000..75ab120 --- /dev/null +++ b/WebProgramming/ReEcho/reecho_server.py @@ -0,0 +1,43 @@ +""" +echo server, usage: + + python echo_server.py + +Port is optional, default: 50001 +""" + +import socket +import sys + +host = '' +port = 50001 + +if len(sys.argv) > 1: + port = int(sys.argv[1]) + +backlog = 5 +size = 1024 + +# server's listener socket +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# Release listener socket immediately when program exits, +# avoid socket.error: [Errno 48] Address already in use +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + +s.bind((host,port)) + +print 'echo_server listening on port', port +s.listen(backlog) + +while True: + client, address = s.accept() + while True : + data = client.recv(size) + if data: + client.send('mark665: %s' % data) + print 'from %s: %s' % (address, data) + else : # no data, client sent empty message + client.close() + print 'closed connection' + break diff --git a/WebProgramming/books/__init__.py b/WebProgramming/books/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/WebProgramming/books/manage.py b/WebProgramming/books/manage.py new file mode 100644 index 0000000..3e4eedc --- /dev/null +++ b/WebProgramming/books/manage.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +import imp +try: + imp.find_module('settings') # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) + sys.exit(1) + +import settings + +if __name__ == "__main__": + execute_manager(settings) diff --git a/WebProgramming/books/settings.py b/WebProgramming/books/settings.py new file mode 100644 index 0000000..b1179ee --- /dev/null +++ b/WebProgramming/books/settings.py @@ -0,0 +1,145 @@ +# Django settings for books project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': '/Users/mark/Documents/workspace/books/sqlite.db', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/media/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = '' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# URL prefix for admin static files -- CSS, JavaScript and images. +# Make sure to use a trailing slash. +# Examples: "http://foo.com/static/admin/", "/static/admin/". +ADMIN_MEDIA_PREFIX = '/static/admin/' + +# Additional locations of static files +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +# 'django.contrib.staticfiles.finders.DefaultStorageFinder', +) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '!s@20740-vblpbdyi-8!9&hj%=z&!#j@69*h^4un1sy=o*2ig%' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) + +ROOT_URLCONF = 'books.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Uncomment the next line to enable the admin: + # 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + # 'django.contrib.admindocs', +) + +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} diff --git a/WebProgramming/books/urls.py b/WebProgramming/books/urls.py new file mode 100644 index 0000000..9984d96 --- /dev/null +++ b/WebProgramming/books/urls.py @@ -0,0 +1,17 @@ +from django.conf.urls.defaults import patterns, include, url + +# Uncomment the next two lines to enable the admin: +# from django.contrib import admin +# admin.autodiscover() + +urlpatterns = patterns('', + # Examples: + # url(r'^$', 'books.views.home', name='home'), + # url(r'^books/', include('books.foo.urls')), + + # Uncomment the admin/doc line below to enable admin documentation: + # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + # url(r'^admin/', include(admin.site.urls)), +) diff --git a/WebProgramming/booksPage/__init__.py b/WebProgramming/booksPage/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/WebProgramming/booksPage/bookdb.py b/WebProgramming/booksPage/bookdb.py new file mode 100644 index 0000000..1f9a441 --- /dev/null +++ b/WebProgramming/booksPage/bookdb.py @@ -0,0 +1,42 @@ +""" +From Brian Dorsey's Internet Programming in Python, Winter 2011 +""" + +class BookDB(): + def titles(self): + titles = [dict(id=id, title=database[id]['title']) for id in database.keys()] + return titles + + def title_info(self, id): + return database[id] + + +# let's pretend we're getting this information from a database somewhere +database = { + 'id1' : {'title' : 'CherryPy Essentials: Rapid Python Web Application Development', + 'isbn' : '978-1904811848', + 'publisher' : 'Packt Publishing (March 31, 2007)', + 'author' : 'Sylvain Hellegouarch', + }, + 'id2' : {'title' : 'Python for Software Design: How to Think Like a Computer Scientist', + 'isbn' : '978-0521725965', + 'publisher' : 'Cambridge University Press; 1 edition (March 16, 2009)', + 'author' : 'Allen B. Downey', + }, + 'id3' : {'title' : 'Foundations of Python Network Programming', + 'isbn' : '978-1430230038', + 'publisher' : 'Apress; 2 edition (December 21, 2010)', + 'author' : 'John Goerzen', + }, + 'id4' : {'title' : 'Python Cookbook, Second Edition', + 'isbn' : '978-0-596-00797-3', + 'publisher' : 'O''Reilly Media', + 'author' : 'Alex Martelli, Anna Ravenscroft, David Ascher', + }, + 'id5' : {'title' : 'The Pragmatic Programmer: From Journeyman to Master', + 'isbn' : '978-0201616224', + 'publisher' : 'Addison-Wesley Professional (October 30, 1999)', + 'author' : 'Andrew Hunt, David Thomas', + }, +} + diff --git a/WebProgramming/booksPage/bookdb_test.py b/WebProgramming/booksPage/bookdb_test.py new file mode 100644 index 0000000..3d19756 --- /dev/null +++ b/WebProgramming/booksPage/bookdb_test.py @@ -0,0 +1,28 @@ +""" +From Brian Dorsey's Internet Programming in Python, Winter 2011 +""" + +import bookdb + +def test_list_books(): + books = bookdb.BookDB() + titles = books.titles() + assert len(titles) > 1 + print titles + for title in titles: + assert 'title' in title + assert 'id' in title + +def test_get_book_info(): + books = bookdb.BookDB() + titles = books.titles() + id = titles[0]['id'] + print id + info = books.title_info(id) + print info + assert 'title' in info + assert info['title'] == titles[0]['title'] + assert 'publisher' in info + assert 'isbn' in info + assert 'author' in info + diff --git a/WebProgramming/booksPage/books.py b/WebProgramming/booksPage/books.py new file mode 100644 index 0000000..2a1a790 --- /dev/null +++ b/WebProgramming/booksPage/books.py @@ -0,0 +1,37 @@ +""" +Minimal Flask + forms demo + +Send HTML page that echoes message from HTTP request +To get started, point browser at echo_flask.html +""" + +from flask import Flask, render_template, request +from bookdb import BookDB + +# No need for message page +# Flask converts view function return string to HTML page + +app = Flask(__name__) + +app.debug = True # development only - remove on production machines + +booksDB = BookDB () + +# View functions generate HTTP responses including HTML pages and headers + +@app.route('/books.html') +def bookList(): + return render_template('bookslist.html',titles = booksDB.titles()) +# return form_page + +@app.route('/abook/') +def bookInfo(book_id): + return render_template('book.html', thisBook = booksDB.title_info(book_id)) +# return from_page + + +# No function needed for other routes - Flask will send 404 page + +if __name__ == '__main__': + app.run() + diff --git a/WebProgramming/booksPage/books.txt b/WebProgramming/booksPage/books.txt new file mode 100644 index 0000000..1dda502 --- /dev/null +++ b/WebProgramming/booksPage/books.txt @@ -0,0 +1,11 @@ +books.txt ++-- + +Week 7 Assignment: Books web site + +- Write a multi page website, using bookdb.py +- Index page is a list of books, link to a detail page per book +- Each detail page displays info about one book +- Use any Python tech you’d like + +(from Brian Dorsey's Internet Programming in Python, Winter 2011) diff --git a/WebProgramming/booksPage/templates/book.html b/WebProgramming/booksPage/templates/book.html new file mode 100644 index 0000000..379b35c --- /dev/null +++ b/WebProgramming/booksPage/templates/book.html @@ -0,0 +1,15 @@ + +Book List + + +

{{ thisBook['title'] }} :

+
+ +
+ + + diff --git a/WebProgramming/booksPage/templates/booksList.html b/WebProgramming/booksPage/templates/booksList.html new file mode 100644 index 0000000..93b0d13 --- /dev/null +++ b/WebProgramming/booksPage/templates/booksList.html @@ -0,0 +1,15 @@ + +Book List + + +

Books Available in Library :

+
+ +
+ + + diff --git a/WebProgramming/cgiPrograming/cgi-bin/cgi_test.py b/WebProgramming/cgiPrograming/cgi-bin/cgi_test.py new file mode 100755 index 0000000..7805372 --- /dev/null +++ b/WebProgramming/cgiPrograming/cgi-bin/cgi_test.py @@ -0,0 +1,3 @@ +#!/usr/bin/python +import cgi +cgi.test() diff --git a/WebProgramming/cgiPrograming/cgi-bin/echo_cgi.py b/WebProgramming/cgiPrograming/cgi-bin/echo_cgi.py new file mode 100755 index 0000000..49d2249 --- /dev/null +++ b/WebProgramming/cgiPrograming/cgi-bin/echo_cgi.py @@ -0,0 +1,29 @@ +#!/usr/bin/python + +""" +Minimal CGI + forms demo + +Send HTML page that echoes message from HTTP request +Intended to be invoked via action attribute in form tag in echo_cgi.html +""" + +import cgi +import cgitb + +cgitb.enable() # so tracebacks in the web page, not the console + +form = cgi.FieldStorage() # invoke only once +message = form.getfirst('message') + +print """Content-type: text/html + + + +Echo response + + +Message: %s + + + +""" % message diff --git a/WebProgramming/cgiPrograming/echo_cgi.html b/WebProgramming/cgiPrograming/echo_cgi.html new file mode 100644 index 0000000..236943e --- /dev/null +++ b/WebProgramming/cgiPrograming/echo_cgi.html @@ -0,0 +1,18 @@ + + + + +Echo request + + +
+Message: + +
+ + diff --git a/WebProgramming/thirtyMinuteWebServer/hello_www.py b/WebProgramming/thirtyMinuteWebServer/hello_www.py new file mode 100644 index 0000000..6fcc7af --- /dev/null +++ b/WebProgramming/thirtyMinuteWebServer/hello_www.py @@ -0,0 +1,58 @@ +""" +hello_www.py - minimal web server + web application +""" + +import socket +import sys +import time +import datetime + + +page = """ +HTTP/1.0 200 OK +Content-Type text/html + + + +%s + + +""" + + +def parseRecieved (text): + url = text.split() + if url[1] == "/time" : + return page % time.time() + else : + return page % "Hello World!" + pass + +host = '' +port = 8082 # different default port than thirty_minute_webserver + +# optional command line argument: port +if len(sys.argv) > 1: + port = int(sys.argv[1]) + +backlog = 5 +size = 1024 + +# server's listener socket +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# Release listener socket immediately when program exits, +# avoid socket.error: [Errno 48] Address already in use +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + +s.bind((host,port)) + +print 'hello_www listening on port', port +s.listen(backlog) + +while True: # just keep serving page to any client that connects + client, address = s.accept() # create client socket + recieved = client.recv(size) # HTTP request - not too big! Just ignore contents + send = parseRecieved (recieved) + client.send(send) # HTTP response - same for any request + client.close() diff --git a/WebProgramming/thirtyMinuteWebServer/print_time.py b/WebProgramming/thirtyMinuteWebServer/print_time.py new file mode 100755 index 0000000..88e1e1d --- /dev/null +++ b/WebProgramming/thirtyMinuteWebServer/print_time.py @@ -0,0 +1,6 @@ +#! /Library/Frameworks/Python.framework/Versions/2.7/bin/python +import time +import datetime + +print "Here is the time: %s" % time.time() +print "and again: %s" % datetime.datetime.now() diff --git a/WebProgramming/thirtyMinuteWebServer/text.txt b/WebProgramming/thirtyMinuteWebServer/text.txt new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/WebProgramming/thirtyMinuteWebServer/text.txt @@ -0,0 +1 @@ +test diff --git a/WebProgramming/thirtyMinuteWebServer/thirty_minute_webserver.py b/WebProgramming/thirtyMinuteWebServer/thirty_minute_webserver.py new file mode 100644 index 0000000..8f1e4d0 --- /dev/null +++ b/WebProgramming/thirtyMinuteWebServer/thirty_minute_webserver.py @@ -0,0 +1,140 @@ +# +# ws30 -- the thirty minute web server +# author: Wilhelm Fitzpatrick (rafial@well.com) +# date: August 3rd, 2002 +# version: 1.0 +# +# Written after attending a Dave Thomas talk at PNSS and hearing about +# his "write a web server in Ruby in one hour" challenge. +# +# Actual time spent: +# 30 minutes reading socket man page +# 30 minutes coding to first page fetched +# 3 hours making it prettier & more pythonic +# +# updated for UW Internet Programming in Python, by Brian Dorsey +# + +import os, socket, sys, datetime + +defaults = ['127.0.0.1', '8088'] +mime_types = {'.jpg' : 'image/jpg', + '.gif' : 'image/gif', + '.png' : 'image/png', + '.html' : 'text/html', + '.pdf' : 'application/pdf'} +response = {} + +response[200] =\ +"""HTTP/1.0 200 Okay +Server: ws30 +Content-type: %s + +%s +""" + +response[301] =\ +"""HTTP/1.0 301 Moved +Server: ws30 +Content-type: text/plain +Location: %s + +moved +""" + +response[404] =\ +"""HTTP/1.0 404 Not Found +Server: ws30 +Content-type: text/plain + +%s not found +""" + +DIRECTORY_LISTING =\ +""" +%s + +
..
+%s + + +""" + +DIRECTORY_LINE = '%s
' + +def server_socket(host, port): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((host, port)) + s.listen(1) + return s + +def listen(s): + connection, client = s.accept() + return connection.makefile('r+') + +def get_request(stream): + method = None + while True: + line = stream.readline() + print line + if not line.strip(): + break + elif not method: + method, uri, protocol = line.split() + return uri + +def list_directory(uri): + entries = os.listdir('.' + uri) + entries.sort() + return DIRECTORY_LISTING % (uri, uri, '\n'.join( + [DIRECTORY_LINE % (e, e) for e in entries])) + +def get_file(path): + f = open(path) + try: + return f.read() + finally: + f.close() + +def get_content(uri): + print 'fetching:', uri + try: + path = '.' + uri + if os.path.isfile(path): + if path.endswith ('.py'): + output = os.popen('python ' + path).read() + return (200,'text/plain', output) + return (200, get_mime(uri), get_file(path)) + if os.path.isdir(path): + if(uri.endswith('/')): + return (200, 'text/html', list_directory(uri)) + else: + return (301, uri + '/') + if uri.endswith ("date.html") : + return (200, "text/html", datetime.datetime.now()) + + + else: return (404, uri) + except IOError, e: + return (404, e) + +def get_mime(uri): + return mime_types.get(os.path.splitext(uri)[1], 'text/plain') + +def send_response(stream, content): + stream.write(response[content[0]] % content[1:]) + +if __name__ == '__main__': + args, nargs = sys.argv[1:], len(sys.argv) - 1 + host, port = (args + defaults[-2 + nargs:])[0:2] + server = server_socket(host, int(port)) + print 'starting %s on %s...' % (host, port) + try: + while True: + stream = listen (server) + send_response(stream, get_content(get_request(stream))) + stream.close() + except KeyboardInterrupt: + print 'shutting down...' + server.close() + diff --git a/WebProgramming/webAPIProject/displayLocation.py b/WebProgramming/webAPIProject/displayLocation.py new file mode 100644 index 0000000..11c1284 --- /dev/null +++ b/WebProgramming/webAPIProject/displayLocation.py @@ -0,0 +1,44 @@ +''' +Created on Feb 12, 2012 + +@author: mark +Given an address, this prints the lat/long cordinates of the address, as well as the address of the house across the street. s +''' + +from pprint import pprint +import urllib2, json + +requestLatLogAddress = "http://maps.googleapis.com/maps/api/geocode/json?%s%s" +sensor = "&sensor=false" + +print "Enter street address (less city and state) :" +address = raw_input().split() +homeAddress = "address=" + "+".join(address) +print address +address[0] = str(int(address[0]) + 1) +neighborAddress = "address=" + "+".join(address) +print "Enter City : " +city = ",+" + raw_input () +print "Enter State : " +state = ",+" + raw_input () + +print address +print city +print state + +address_request = requestLatLogAddress % (homeAddress+city+state,sensor) +neighbor_request = requestLatLogAddress % (neighborAddress+city+state,sensor) + +addressResult = urllib2.urlopen(address_request) +neighborResult = urllib2.urlopen(neighbor_request) + +jsonDataAddress = json.load(addressResult) +jsonDataNeighbor = json.load(neighborResult) + +print "Cordinates of your house: " +pprint("lat: " + str(jsonDataAddress['results'][0]['geometry']['location']['lat'])) +pprint("lng: " + str(jsonDataAddress['results'][0]['geometry']['location']['lng'])) + +print "Cordinates of your Neighbor's house: " +pprint("lat: " + str(jsonDataNeighbor['results'][0]['geometry']['location']['lat'])) +pprint("lng: " + str(jsonDataNeighbor['results'][0]['geometry']['location']['lng'])) diff --git a/WebProgramming/week4/Class.py b/WebProgramming/week4/Class.py new file mode 100644 index 0000000..6b1a821 --- /dev/null +++ b/WebProgramming/week4/Class.py @@ -0,0 +1,20 @@ +''' +Created on Feb 7, 2012 + +@author: mark +''' + +""" +NOTES: + +freebase.com - database intended for exclusive use as an api +""" + +import urllib2 + +result = urllib2.urlopen('http://google.com').read () +print result + + +if __name__ == '__main__': + pass \ No newline at end of file diff --git a/WebProgramming/week4/scrape.py b/WebProgramming/week4/scrape.py new file mode 100644 index 0000000..db1a5b4 --- /dev/null +++ b/WebProgramming/week4/scrape.py @@ -0,0 +1,11 @@ +''' +Created on Feb 7, 2012 + +@author: mark +''' +from pprint import pprint +import re, urllib2, sys + +url = sys.argv[1] +result = urllib2.urlopen("http://jon-jacky.github.com/uw_python/winter_2012/index.html").read () +pprint (re.findall('http://.*html',result)) \ No newline at end of file diff --git a/WebProgramming/week5/class.py b/WebProgramming/week5/class.py new file mode 100644 index 0000000..b797b13 --- /dev/null +++ b/WebProgramming/week5/class.py @@ -0,0 +1,7 @@ +''' +Created on Feb 14, 2012 + +@author: mark + +python -m +''' diff --git a/WebProgramming/wsgiAssignment/echo_wsgi.py b/WebProgramming/wsgiAssignment/echo_wsgi.py new file mode 100644 index 0000000..91f5516 --- /dev/null +++ b/WebProgramming/wsgiAssignment/echo_wsgi.py @@ -0,0 +1,68 @@ +""" +Minimal WSGI + forms demo, with persistence + +Send HTML page that echoes message from HTTP request +To get started, point browser at echo_wsgi.html + +Based on example in PEP 333, then add path and query processing +""" + +import urlparse + +# send one of these pages, depending on URL path + +form_page = """ +Echo request + + +
+Message: + +
+ + +""" + +message_template = """ + + +Echo response + + +Message: %s + + + +""" + +notfound_template = """ + + +404 Not Found + + +404 %s not found + + + +""" +messages = [] + +# must be named 'application' to work with our wsgi simple server +def application(environ, start_response): + status = '200 OK' + response_headers = [('Content_type', 'text/HTML')] + start_response(status, response_headers) + + # send different page depending on URL path + path = environ['PATH_INFO'] + if path == '/echo_wsgi.html': + page = form_page + elif path == '/echo_wsgi.py': + # get message from URL query string, parse_qs returns a list for each key + messages.append(urlparse.parse_qs(environ['QUERY_STRING'])['message'][0]) + page = message_template % ( + "
Previous Message : ".join(messages)) + else: + page = notfound_template % path + return [ page ] # list of strings - must return iterable, not just a string diff --git a/WebProgramming/wsgiAssignment/wsgi_simple_server.py b/WebProgramming/wsgiAssignment/wsgi_simple_server.py new file mode 100644 index 0000000..eed3d5c --- /dev/null +++ b/WebProgramming/wsgiAssignment/wsgi_simple_server.py @@ -0,0 +1,32 @@ +""" +Simple WSGI application runner, including its own WSGI server + +Usage: python simple_wsgi_server.py + +Example: python simple_wsgi_server.py test.wsgi 8080 + +Default application is wsgi_test, default port is 8000 + +The application module can be named anything, but the +application callable it provides MUST be named 'application' +""" + +import sys +from wsgiref.simple_server import make_server + +appname = 'wsgi_test' +port = 8000 + + +nargs = len(sys.argv) +if nargs > 1: + appname = sys.argv[1] +if nargs > 2: + port = int(sys.argv[2]) + +app = __import__(appname) +httpd = make_server('', port, app.application) +print "Running %s on port %s ..." % (appname, port) + +# Respond to requests until process is killed +httpd.serve_forever()