root/software/session2/trunk/README.txt

Revision 12, 10.2 kB (checked in by t, 12 years ago)

Moved VolatileSessionStore? over to MemorySessionStore? (MO)

Line 
1 =======================================================
2 session2: Persistent Session Management for Quixote 2.x
3 =======================================================
4
5 :Authors: C Titus Brown, Mike Orr
6 :Email: titus@caltech.edu, mso@oz.net
7 :License: MIT  (http://www.opensource.org/licenses/mit-license.php)
8 :Version: 0.6.1  released on 2006-2-05
9 :Status: beta.  All stores pass basic tests and several are used in production code.
10
11 .. contents::
12
13 Introduction
14 ============
15
16 Quixote_ is a Python Web application framework.  It comes with an
17 in-memory session manager, which works but is incompatible with
18 multi-process servers (SCGI, CGI, etc).  It also forgets the sessions
19 when the Publisher quits.  `session2` solves these problems by
20 providing a new session manager class and a simple back end storage
21 API.
22
23 `session2` also provides several (fully functional) persistent storage back
24 ends:
25
26 DirectorySessionStore_
27   Store each pickled session in a file in the designated directory.  The
28   filename is the session ID.  Uses ``fcntl`` file locking.  ::
29
30       DirectorySessionStore(directory)
31  
32 DurusSessionStore_
33   Store sessions in a Durus_ database.  ::
34
35       DurusSessionStore(durus_connection)
36
37 MySQLSessionStore_
38   Store sessions in a MySQL_ database.  ::
39      
40       MySQLSessionStore(mysql_connection, table='sessions')
41
42 PostgresSessionStore_
43   Store sessions in a PostgreSQL_ database.  ::
44
45       PostgresSessionStore(psycopg_connection)
46  
47 ShelveSessionStore_
48   Store sessions in a DBM database using ``shelve``.  ::
49
50       ShelveSessionStore(filename)
51  
52 This package includes a refactored SessionManager that makes it easy to develop
53 additional back ends, and a simplified Session class (no .is_dirty method).
54 It supports the usual ``.user``, ``.set_user()`` and ``.has_info()``
55 attributes, and you can also set your own attributes which will be saved.
56 There's also a DictSession subclass for those who prefer setting keys rather
57 than attributes [1]_.
58
59 It's quite likely that the session stores can be adapted for use with other
60 Web frameworks; let us know if you do this so we can link to you and/or
61 include helpful code in our package.
62
63 .. _DirectorySessionStore: epydoc-html/session2.store.DirectorySessionStore.DirectorySessionStore-class.html
64 .. _DurusSessionStore: epydoc-html/session2.store.DurusSessionStore.DurusSessionStore-class.html
65 .. _MySQLSessionStore: epydoc-html/session2.store.MySQLSessionStore.MySQLSessionStore-class.html
66 .. _PostgresSessionStore: epydoc-html/session2.store.PostgresSessionStore.PostgresSessionStore-class.html
67 .. _ShelveSessionStore: epydoc-html/session2.store.ShelveSessionStore.ShelveSessionStore-class.html
68
69 .. [1] DictSession is especially useful for applications that may want
70    to use `Paste`_'s session middleware in the future, because it is dict-based.
71    However, the migration for ``.user`` and ``.set_user()`` is not yet clear.
72
73 Getting session2
74 ================
75
76 Download the latest version here:
77 http://quixote.idyll.org/session2/session2-0.6.tar.gz
78
79 Source code browser: http://cafepy.com/quixote_extras/titus/session2/
80
81 You can also `grab it directly via subversion`_.
82
83 .. _grab it directly via subversion: http://cafepy.com/quixote_extras/README
84
85 Installation
86 ------------
87
88 Unpack the tar.gz file, and install the normal Python way ("python
89 setup.py install").  You can also just put the 'session2' subdirectory
90 in your Python path.
91
92 Upgrading
93 ---------
94
95 The MySQL database format changed in 0.4.  Users should convert the 'pickle'
96 column to type BLOB, or delete the table and recreate it.
97
98 Using session2
99 ==============
100
101 In your `create_publisher` function, place the following code::
102
103     # create the session store.
104     from session2.store.MemorySessionStore import MemorySessionStore
105     store = MemorySessionStore()
106
107     # create the session manager.
108     from session2.SessionManager import SessionManager
109     session_manager = SessionManager(store)
110
111     # create the publisher.
112     from quixote.publish import Publisher
113     publisher = Publisher(..., session_manager=session_manager)
114
115 Each session store has different initialization requirements; see
116 the `source documentation`_ for more information.   
117
118 To use an alternate session class::
119
120     from session2.DictSession import DictSession
121     session_manager = SessionManager(store, DictSession)
122
123 Using MySQL
124 -----------
125 ::
126
127     import MySQLdb
128     from session2.store.MySQLSessionStore import MySQLSessionStore
129     from session2.SessionManager import SessionManager
130     from quixote.publish import Publisher
131     conn = MySQLdb.connect(user='USER', passwd='PASSWORD', db='DB')
132     store = MySQLSessionStore(conn, table='sessions')
133     session_manager = SessionManager(store)
134     publisher = Publisher(MyDirectory(), session_manager=session_manager)
135
136 Customizing the 'user' member
137 -----------------------------
138
139 The session2 code is fairly flexible.  You can assign anything pickle-able
140 to the 'Session.user' variable, and it will work with any of the session
141 stores.  This lets you use almost any Python class for user information.
142
143 However, you might want your session store to be independent from your
144 primary database.  If your user information is stored in this
145 database, but your session information is not, then you probably don't
146 want to store pickled user objects in your session store.
147
148 All of this is the long way to say that there's no reason for you to
149 store your entire user object within the session store.  You can easily
150 write an application-specific wrapper around the 'user' member of Session::
151
152    class MySessionWrapper(Session):
153       """Store only your user's database ID in the user variable."""
154       def set_user(self, user):
155          self.user = user.db_id
156
157       def get_user(self):
158          if self.user is None:   # user not set
159             return None
160
161          return database.load_user(self.user)
162
163 (Remember to pass the new session class in as the second argument to your
164 SessionManager_ instance!)
165
166 .. _SessionManager: epydoc-html/session2.SessionManager.SessionManager-class.html#__init__
167
168 Features
169 ========
170
171 All session stores have the following methods, which are called by the session
172 manager: ``.load_session``, ``.save_session``, ``.delete_session``,
173 ``.has_session``.
174
175 They also have these convenience methods:
176
177 ``.setup()``: initializes the store.  For MySQL and PostgreSQL, this
178 creates the table.  This is meant to be called in your application
179 setup code when you deploy it on a new server.
180
181 ``.delete_old_sessions(minutes)``: deletes sessions that haven't been modified
182 for N minutes.  This is meant for your application maintenance program; e.g.,
183 a daily cron job.  Only MySQLSessionStore actually deletes the sessions at
184 this point; it's a no-op for the others.
185
186 ``.iter_sessions()``: Return an iterable of (id, session) for all sessions
187 in the store.  This is for admin applications that want to browse the sessions.
188 Only MySQLSessionStore currently implements this; the others raise
189 NotImplementedError.
190
191 All stores have ``.is_multiprocess_safe`` and ``.is_thread_safe`` attributes.
192 An application can check these flags and abort if configured inappropriately.
193 The flags are defined as follows:
194
195 - DirectorySessionStore is multiprocess safe because it uses ``fcntl`` file
196   locking.  This limits its use to POSIX.  See the fcntl caution below.  It may
197   be thread safe because it always locks-unlocks within the same method, but we
198   don't know for sure so the attribute is false.
199
200 - DurusSessionStore is multiprocess safe.  It's not thread safe because Durus
201   isn't.  With synchronization (see ``thread.allocate_lock``) a subclass could
202   be made safe, maybe.
203
204 - The two SQL session stores (MySQLSessionStore and
205   PostgresSessionStore) are multiprocess safe.  They are not thread
206   safe because each connection is per-process.  A subclass could use
207   thread-specific connections or a connection pool.
208
209 - ShelveSessionStore is *not* multiprocess safe because it doesn't do file
210   locking.  See the "Restrictions" section for the ``shelve`` module in the
211   Python Library Reference.  It's not thread safe for the same reason.  If you
212   think about using ``fcntl`` in a subclass, see the fcntl caution below.
213
214 setup-store.py
215 --------------
216
217 This is a command-line interface to the ``.setup()`` method.  It currently
218 supports MySQL and PostgreSQL/psycopg with the following syntax::
219
220     $ setup-store.py mysql HOST USER PASSWORD DATABASE [TABLE]
221     $ setup-store.py mysql '' joe sEcReT test
222     $ setup-store.py mysql '' joe sEcReT test Session
223
224 The table name defaults to 'sessions'.  All stores except PostgreSQL
225 automatically create themselves when instantiated, but this command is
226 useful if the application won't have permission to create the store.
227
228 This command is not installed by ``setup.py``; it's available only in the
229 application source.  It's not used frequently enough to warrant installation.
230
231 Interactive Testing
232 -------------------
233
234 session2 comes with two ways to test it: an interactive web application, and
235 nose_-based unit tests that require twill_.
236
237 To run the unit tests, run ``nosetests``.
238
239 To run the web demo, cd to the **test/** directory in the application
240 source and run one of::
241
242     $ test_session2.py directory
243     $ test_session2.py durus
244     $ test_session2.py mysql
245     $ test_session2.py psycopg
246     $ test_session2.py shelve
247
248 Point your web browser to **http://localhost:8080/** and play around.
249 You can use '--host=hostname' and ``--port=N`` to bind to a different hostname
250 or port.
251
252 Press ctrl-C to quit the demo (or command-C on the Mac, or ctrl-Break on
253 Windows).
254
255 See the module source for the filenames, databases, and tables it
256 uses.  Note that you'll have to create the PostgreSQL table yourself
257 using 'setup-store.py'.
258
259 ``fcntl`` Caution
260 -----------------
261
262 On Mac OS X when using PTL, import ``fcntl`` *before* enabling PTL.
263 Otherwise the import hook may load the deprecated FCNTL.py instead due to
264 the Mac's case-insensitive filesystem, which will cause errors down the road.
265 This is supposedly fixed in Python 2.4, which doesn't have FCNTL.py.
266
267 .. _Quixote: http://www.mems-exchange.org/software/quixote/
268 .. _MySQL: http://mysql.org/
269 .. _PostgreSQL: http://postgresql.org/
270 .. _Paste: http://pythonpaste.org/
271 .. _Durus: http://www.mems-exchange.org/software/durus/
272 .. _twill: http://www.idyll.org/~t/www-tools/twill.html
273 .. _source documentation: ./epydoc-html/session2-module.html
274 .. _nose: http://somethingaboutorange.com/mrl/projects/nose/
Note: See TracBrowser for help on using the browser.