/usr/share/pyshared/quixote/demo/altdemo.py is in python-quixote 2.7~b2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | """An alternative Quixote demo. This version is contained in a single module
and does not use PTL. The easiest way to run this demo is to use the
simple HTTP server included with Quixote. For example:
$ server/simple_server.py --factory quixote.demo.altdemo.create_publisher
The server listens on localhost:8080 by default. Debug and error output
will be sent to the terminal.
If you have installed durus, you can run the same demo, except with
persistent sessions stored in a durus database, by running:
$ server/simple_server.py --factory quixote.demo.altdemo.create_durus_publisher
"""
from quixote import get_user, get_session, get_session_manager, get_field
from quixote.directory import Directory
from quixote.html import href, htmltext
from quixote.publish import Publisher
from quixote.session import Session, SessionManager
from quixote.util import dump_request
def format_page(title, content):
request = htmltext(
'<div style="font-size: smaller;background:#eee">'
'<h1>Request:</h1>%s</div>') % dump_request()
return htmltext(
'<html><head><title>%(title)s</title>'
'<style type="text/css">\n'
'body { border: thick solid green; padding: 2em; }\n'
'h1 { font-size: larger; }\n'
'th { background: #aaa; text-align:left; font-size: smaller; }\n'
'td { background: #ccc; font-size: smaller; }\n'
'</style>'
'</head><body>%(content)s%(request)s</body></html>') % locals()
def format_request():
return format_page('Request', dump_request())
def format_link_list(targets):
return htmltext('<ul>%s</ul>') % htmltext('').join([
htmltext('<li>%s</li>') % href(target, target) for target in targets])
class RootDirectory(Directory):
_q_exports = ['', 'login', 'logout']
def _q_index(self):
content = htmltext('')
if not get_user():
content += htmltext('<p>%s</p>' % href('login', 'login'))
else:
content += htmltext(
'<p>Hello, %s.</p>') % get_user()
content += htmltext('<p>%s</p>' % href('logout', 'logout'))
sessions = get_session_manager().items()
if sessions:
sessions.sort()
content += htmltext('<table><tr>'
'<th></th>'
'<th>Session</th>'
'<th>User</th>'
'<th>Number of Requests</th>'
'</tr>')
this_session = get_session()
for index, (id, session) in enumerate(sessions):
if session is this_session:
formatted_id = htmltext(
'<span style="font-weight:bold">%s</span>' % id)
else:
formatted_id = id
content += htmltext(
'<tr><td>%s</td><td>%s</td><td>%s</td><td>%d</td>' % (
index,
formatted_id,
session.user or htmltext("<em>None</em>"),
session.num_requests))
content += htmltext('</table>')
return format_page("Quixote Session Management Demo", content)
def login(self):
content = htmltext('')
if get_field("name"):
session = get_session()
session.set_user(get_field("name")) # This is the important part.
content += htmltext(
'<p>Welcome, %s! Thank you for logging in.</p>') % get_user()
content += href("..", "go back")
else:
content += htmltext(
'<p>Please enter your name here:</p>\n'
'<form method="POST" action="login">'
'<input name="name" />'
'<input type="submit" />'
'</form>')
return format_page("Quixote Session Demo: Login", content)
def logout(self):
if get_user():
content = htmltext('<p>Goodbye, %s.</p>') % get_user()
else:
content = htmltext('<p>That would be redundant.</p>')
content += href("..", "start over")
get_session_manager().expire_session() # This is the important part.
return format_page("Quixote Session Demo: Logout", content)
class DemoSession(Session):
def __init__(self, id):
Session.__init__(self, id)
self.num_requests = 0
def start_request(self):
"""
This is called from the main object publishing loop whenever
we start processing a new request. Obviously, this is a good
place to track the number of requests made. (If we were
interested in the number of *successful* requests made, then
we could override finish_request(), which is called by
the publisher at the end of each successful request.)
"""
Session.start_request(self)
self.num_requests += 1
def has_info(self):
"""
Overriding has_info() is essential but non-obvious. The
session manager uses has_info() to know if it should hang on
to a session object or not: if a session is "dirty", then it
must be saved. This prevents saving sessions that don't need
to be saved, which is especially important as a defensive
measure against clients that don't handle cookies: without it,
we might create and store a new session object for every
request made by such clients. With has_info(), we create the
new session object every time, but throw it away unsaved as
soon as the request is complete.
(Of course, if you write your session class such that
has_info() always returns true after a request has been
processed, you're back to the original problem -- and in fact,
this class *has* been written that way, because num_requests
is incremented on every request, which makes has_info() return
true, which makes SessionManager always store the session
object. In a real application, think carefully before putting
data in a session object that causes has_info() to return
true.)
"""
return (self.num_requests > 0) or Session.has_info(self)
is_dirty = has_info
def create_publisher():
return Publisher(RootDirectory(),
session_manager=SessionManager(session_class=DemoSession),
display_exceptions='plain')
try:
# If durus is installed, define a create_durus_publisher() that
# uses a durus database to store persistent sessions.
import os, tempfile
from durus.persistent import Persistent
from durus.persistent_dict import PersistentDict
from durus.file_storage import FileStorage
from durus.connection import Connection
connection = None # set in create_durus_publisher()
class PersistentSession(DemoSession, Persistent):
pass
class PersistentSessionManager(SessionManager, Persistent):
def __init__(self):
sessions = PersistentDict()
SessionManager.__init__(self,
session_class=PersistentSession,
session_mapping=sessions)
def forget_changes(self, session):
print 'abort changes', get_session()
connection.abort()
def commit_changes(self, session):
print 'commit changes', get_session()
connection.commit()
def create_durus_publisher():
global connection
filename = os.path.join(tempfile.gettempdir(), 'quixote-demo.durus')
print 'Opening %r as a Durus database.' % filename
connection = Connection(FileStorage(filename))
root = connection.get_root()
session_manager = root.get('session_manager', None)
if session_manager is None:
session_manager = PersistentSessionManager()
connection.get_root()['session_manager'] = session_manager
connection.commit()
return Publisher(RootDirectory(),
session_manager=session_manager,
display_exceptions='plain')
except ImportError:
pass # durus not installed.
|