witten
/
luminotes
Archived
1
0
Fork 0

More docstrings.

This commit is contained in:
Dan Helfman 2007-08-09 19:44:26 +00:00
parent a866c617ec
commit 8fd463e22d
5 changed files with 106 additions and 3 deletions

View File

@ -7,10 +7,12 @@ from formatter import AbstractFormatter, NullWriter
from htmlentitydefs import entitydefs
from xml.sax.saxutils import quoteattr
def xssescape(text):
"""Gets rid of < and > and & and, for good measure, :"""
"""Gets rid of < and > and & and, for good measure"""
return escape(text, quote=True)
class Html_cleaner(HTMLParser):
"""
Cleans HTML of any tags not matching a whitelist.

View File

@ -103,6 +103,7 @@ class Notebooks( object ):
@rtype: json dict
@return: { 'notebook': notebookdict, 'note': notedict or None }
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -152,6 +153,7 @@ class Notebooks( object ):
@rtype: json dict
@return: { 'note': notedict or None }
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -197,6 +199,7 @@ class Notebooks( object ):
@rtype: json dict
@return: { 'note': notedict or None }
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -246,6 +249,7 @@ class Notebooks( object ):
@rtype: json dict
@return: { 'new_revision': new revision of saved note, or None }
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -305,6 +309,7 @@ class Notebooks( object ):
@rtype: json dict
@return: {}
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -349,6 +354,7 @@ class Notebooks( object ):
@rtype: json dict
@return: {}
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -393,6 +399,7 @@ class Notebooks( object ):
@rtype: json dict
@return: {}
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -443,6 +450,7 @@ class Notebooks( object ):
@rtype: json dict
@return: {}
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -481,6 +489,7 @@ class Notebooks( object ):
@type id: id of the note
@rtype: unicode
@return: rendered HTML page
@raise Validation_error: the argument is invalid
"""
return dict( id = id )
@ -510,6 +519,7 @@ class Notebooks( object ):
@rtype: json dict
@return: { 'notes': [ matching notes ] }
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -561,6 +571,7 @@ class Notebooks( object ):
@rtype: json dict
@return: { 'notes': [ recent notes ] }
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
@ -601,6 +612,7 @@ class Notebooks( object ):
@rtype: unicode
@return: rendered HTML page
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):

View File

@ -84,9 +84,14 @@ class Scheduler( object ):
self.__idle.release()
yield None
# used for unit tests
IDLE_SLEEP_SECONDS = 0.01
def wait_for( self, thread ):
"""
Block until the given thread exits. Intended for use in unit tests only.
@type thread: generator
@param thread: thread to wait for
"""
while thread in self.__running or thread in self.__sleeping:
sleep( self.IDLE_SLEEP_SECONDS )
@ -94,15 +99,32 @@ class Scheduler( object ):
raise self.__last_error
def wait_until_idle( self ):
"""
Block until all threads have exited. Intended for use in unit tests only.
"""
while len( self.__running ) > 1 or len( self.__sleeping ) > 0:
sleep( self.IDLE_SLEEP_SECONDS )
def sleep( self, thread ):
"""
Put the given thread to sleep so that is is no longer actively running.
@type thread: generator
@param thread: thread to put to sleep
"""
self.__idle.acquire( blocking = False )
self.__sleeping.append( thread )
self.__running.remove( thread )
def add( self, thread, *args ):
"""
Add the given thread to the running list for this Scheduler, and wake it up if it's asleep.
@type thread: generator
@param thread: thread to add
@type args: tuple
@param args: arguments to send() to the given thread when it is executed
"""
self.__idle.release()
if thread in self.__sleeping:
@ -116,6 +138,9 @@ class Scheduler( object ):
self.__messages[ thread ].append( args )
def shutdown( self ):
"""
Stop all running threads and shutdown the Scheduler.
"""
self.__done = True
self.__idle.release()
self.__scheduler_thread.join()

View File

@ -39,7 +39,8 @@ def update_client( function ):
Note that this decorator itself is a generator function and works by passing along next()/send()
calls to its decorated generator. Only yielded values that are dictionaries are sent to the
client. All other yielded values are in turn yielded by this decorator itself.
client via the provided queue. All other types of yielded values are in turn yielded by this
decorator itself.
"""
def put_message( *args, **kwargs ):
# look in the called function's kwargs for the queue where results should be sent

View File

@ -103,7 +103,22 @@ def update_auth( function ):
class Users( object ):
"""
Controller for dealing with users, corresponding to the "/users" URL.
"""
def __init__( self, scheduler, database, http_url ):
"""
Create a new Users object.
@type scheduler: controller.Scheduler
@param scheduler: scheduler to use for asynchronous calls
@type database: controller.Database
@param database: database that users are stored in
@type http_url: unicode
@param http_url: base URL to use for non-SSL http requests, or an empty string
@rtype: Users
@return: newly constructed Users
"""
self.__scheduler = scheduler
self.__database = database
self.__http_url = http_url
@ -121,6 +136,25 @@ class Users( object ):
signup_button = unicode,
)
def signup( self, username, password, password_repeat, email_address, signup_button ):
"""
Create a new User based on the given information. Start that user with their own Notebook and a
"welcome to your wiki" Note. For convenience, login the newly created user as well.
@type username: unicode (alphanumeric only)
@param username: username to use for this new user
@type password: unicode
@param password: password to use
@type password_repeat: unicode
@param password_repeat: password to use, again
@type email_address: unicode
@param email_address: user's email address
@type signup_button: unicode
@param signup_button: ignored
@rtype: json dict
@return: { 'redirect': url, 'authenticated': userdict }
@raise Signup_error: passwords don't match or the username is unavailable
@raise Validation_error: one of the arguments is invalid
"""
if password != password_repeat:
raise Signup_error( u"The passwords you entered do not match. Please try again." )
@ -171,6 +205,19 @@ class Users( object ):
login_button = unicode,
)
def login( self, username, password, login_button ):
"""
Attempt to authenticate the user. If successful, associate the given user with the current
session.
@type username: unicode (alphanumeric only)
@param username: username to login
@type password: unicode
@param password: the user's password
@rtype: json dict
@return: { 'redirect': url, 'authenticated': userdict }
@raise Authentication_error: invalid username or password
@raise Validation_error: one of the arguments is invalid
"""
self.__database.load( "User %s" % username, self.__scheduler.thread )
user = ( yield Scheduler.SLEEP )
@ -194,6 +241,12 @@ class Users( object ):
@async
@update_client
def logout( self ):
"""
Deauthenticate the user and log them out of their current session.
@rtype: json dict
@return: { 'redirect': url, 'deauthenticated': True }
"""
yield dict(
redirect = self.__http_url + u"/",
deauthenticated = True,
@ -209,6 +262,15 @@ class Users( object ):
user_id = Valid_id( none_okay = True ),
)
def current( self, user_id ):
"""
Return information on the currently logged-in user. If not logged in, default to the anonymous
user.
@type user_id: unicode
@param user_id: id of current logged-in user (if any), determined by @grab_user_id
@rtype: json dict
@return: { 'user': userdict or None, 'notebooks': notebooksdict, 'http_url': url }
"""
# if there's no logged-in user, default to the anonymous user
self.__database.load( user_id or u"User anonymous", self.__scheduler.thread )
user = ( yield Scheduler.SLEEP )
@ -217,6 +279,7 @@ class Users( object ):
yield dict(
user = None,
notebooks = None,
http_url = u"",
)
return