From 5ddc8460de1d3bf1ea41eb4fdc7079d15dcf6837 Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Thu, 27 Mar 2008 14:40:50 +0100 Subject: epydoc update --- wsgitools/digest.py | 19 ++++++-- wsgitools/filters.py | 113 ++++++++++++++++++++++++++++++++++++++--------- wsgitools/middlewares.py | 44 ++++++++++++++---- 3 files changed, 142 insertions(+), 34 deletions(-) diff --git a/wsgitools/digest.py b/wsgitools/digest.py index 19fb975..28fb9c7 100755 --- a/wsgitools/digest.py +++ b/wsgitools/digest.py @@ -50,7 +50,9 @@ class AuthTokenGenerator: self.getpass = getpass def __call__(self, username, algo="md5"): """Generates an authentification token from a username. - @type username: str""" + @type username: str + @rtype: str + """ assert algo.lower() in ["md5", "md5-sess"] password = self.getpass(username) if password is None: @@ -161,7 +163,10 @@ class AuthDigestMiddleware: return self.app(environ, modified_start_response) def auth_response(self, credentials, reqmethod): - """internal method generating authentication tokens""" + """internal method generating authentication tokens + @raise KeyError: + @raise ValueError: + """ username = credentials["username"] algo = credentials["algorithm"] uri = credentials["uri"] @@ -191,7 +196,10 @@ class AuthDigestMiddleware: self.nonces.pop(0) def is_nonce(self, credentials): - """internal method checking whether a nonce might be from this server""" + """internal method checking whether a nonce might be from this server + @raise KeyError: + @raise ValueError: + """ nonce = credentials["nonce"] # raises KeyError # raises ValueError nonce_time, nonce_value, nonce_hash = nonce.split(':') @@ -200,7 +208,10 @@ class AuthDigestMiddleware: return nonce_hash == token def check_nonce(self, credentials): - """internal method checking nonce validity""" + """internal method checking nonce validity + @raise KeyError: + @raise ValueError: + """ nonce = credentials["nonce"] # raises ValueError nonce_time, nonce_value, nonce_hash = nonce.split(':') diff --git a/wsgitools/filters.py b/wsgitools/filters.py index 759b20c..509ffde 100644 --- a/wsgitools/filters.py +++ b/wsgitools/filters.py @@ -14,12 +14,16 @@ class CloseableIterator: def __init__(self, close_function, *iterators): """If close_function is not None, it will be the close attribute of the created iterator object. Further parameters specify iterators - that are to be concatenated.""" + that are to be concatenated. + @type close_function: a function or None + """ if close_function is not None: self.close = close_function self.iterators = map(iter, iterators) def __iter__(self): - """iterator interface""" + """iterator interface + @rtype: gen() + """ return self def next(self): """iterator interface""" @@ -37,11 +41,14 @@ class CloseableList(list): def __init__(self, close_function, *args): """If close_function is not None, it will be the close attribute of the created list object. Other parameters are passed to the list - constructor.""" + constructor. + @type close_function: a function or None + """ if close_function is not None: self.close = close_function list.__init__(self, *args) def __iter__(self): + """iterator interface""" return CloseableIterator(getattr(self, "close", None), list.__iter__(self)) @@ -69,7 +76,10 @@ class BaseWSGIFilter: pass def filter_environ(self, environ): """Receives a dict with the environment passed to the wsgi application - and a dict must be returned. The default is to return the same dict.""" + and a dict must be returned. The default is to return the same dict. + @type environ: {str: str} + @rtype: {str: str} + """ return environ def filter_exc_info(self, exc_info): """Receives either None or a tuple passed as third argument to @@ -79,28 +89,42 @@ class BaseWSGIFilter: def filter_status(self, status): """Receives a status string passed as first argument to start_response from the wrapped wsgi application. A valid HTTP status string must be - returned.""" + returned. + @type status: str + @rtype: str + """ return status def filter_header(self, headername, headervalue): """This function is invoked for each (headername, headervalue) tuple in the second argument to the start_response from the wrapped wsgi application. Such a value or None for discarding the header must be - returned.""" + returned. + @type headername: str + @type headervalue: str + @rtype: (str, str) + """ return (headername, headervalue) def filter_headers(self, headers): """A list of headers passed as the second argument to the start_response from the wrapped wsgi application is passed to this function and such a - list must also be returned.""" + list must also be returned. + @type headers: [(str, str)] + @rtype: [(str, str)] + """ return headers def filter_data(self, data): """For each string that is either written by the write callable or returned from the wrapped wsgi application this method is invoked. It - must return a string.""" + must return a string. + @type data: str + @rtype: str + """ return data def append_data(self): """This function can be used to append data to the response. A list of strings or some kind of iterable yielding strings has to be returned. The default is to return an empty list. + @rtype: gen([str]) """ return [] def handle_close(self): @@ -114,12 +138,16 @@ class WSGIFilterMiddleware: def __init__(self, app, filterclass): """ @param app: is a wsgi application. + @type filterclass: BaseWSGIFilters subclass @param filterclass: is a subclass of BaseWSGIFilter or some class that implements the interface.""" self.app = app self.filterclass = filterclass def __call__(self, environ, start_response): - """wsgi interface""" + """wsgi interface + @type environ: {str, str} + @rtype: gen([str]) + """ assert isinstance(environ, dict) reqfilter = self.filterclass() environ = reqfilter.filter_environ(environ) @@ -163,15 +191,23 @@ class RequestLogWSGIFilter(BaseWSGIFilter): @classmethod def creator(cls, log): """Returns a function creating RequestLogWSGIFilters on given log file. - log has to be a file-like object.""" + log has to be a file-like object. + @type log: file-like + """ return lambda:cls(log) def __init__(self, log=sys.stdout): + """ + @type log: file-like + """ assert hasattr(log, "write") self.log = log self.time = time.strftime("%d/%b/%Y:%T %z") self.length = 0 def filter_environ(self, environ): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type environ: {str: str} + @rtype: {str: str} + """ assert isinstance(environ, dict) self.remote = environ.get("REMOTE_ADDR", "?") self.user = environ.get("REMOTE_USER", "-") @@ -182,12 +218,18 @@ class RequestLogWSGIFilter(BaseWSGIFilter): self.useragent = environ.get("HTTP_USER_AGENT", "-") return environ def filter_status(self, status): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type status: str + @rtype: str + """ assert isinstance(status, str) self.status = status.split()[0] return status def filter_data(self, data): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type data: str + @rtype: str + """ self.length += len(data) return data def handle_close(self): @@ -218,13 +260,21 @@ class TimerWSGIFilter(BaseWSGIFilter): @classmethod def creator(cls, pattern): """Returns a function creating TimerWSGIFilters with a given pattern - beeing a string of exactly eight bytes.""" + beeing a string of exactly eight bytes. + @type pattern: str + """ return lambda:cls(pattern) def __init__(self, pattern="?GenTime"): + """ + @type pattern: str + """ self.pattern = pattern self.start = time.time() def filter_data(self, data): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type data: str + @rtype: str + """ if data == self.pattern: return "%8.3g" % (time.time() - self.start) return data @@ -235,15 +285,26 @@ class EncodeWSGIFilter(BaseWSGIFilter): @classmethod def creator(cls, charset): """Returns a function creating EncodeWSGIFilters with a given charset. + @type charset: str """ return lambda:cls(charset) def __init__(self, charset="utf-8"): + """ + @type charset: str + """ self.charset = charset def filter_data(self, data): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type data: str + @rtype: str + """ return data.encode(self.charset) def filter_header(self, header, value): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type header: str + @type value: str + @rtype (str, str) + """ if header.lower() != "content-type": return (header, value) return (header, "%s; charset=%s" % (value, self.charset)) @@ -256,7 +317,9 @@ class GzipWSGIFilter(BaseWSGIFilter): self.sio = None self.gzip = None def filter_environ(self, environ): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type environ: {str: str} + """ assert isinstance(environ, dict) if "HTTP_ACCEPT_ENCODING" in environ: acceptenc = environ["HTTP_ACCEPT_ENCODING"].split(',') @@ -267,13 +330,19 @@ class GzipWSGIFilter(BaseWSGIFilter): self.gzip = gzip.GzipFile(fileobj=self.sio, mode="w") return environ def filter_headers(self, headers): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type headers: [(str, str)] + @rtype: [(str, str)] + """ assert isinstance(headers, list) if self.compress: headers.append(("Content-encoding", "gzip")) return headers def filter_data(self, data): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @type data: str + @rtype: str + """ if not self.compress: return data self.gzip.write(data) @@ -282,7 +351,9 @@ class GzipWSGIFilter(BaseWSGIFilter): self.sio.truncate(0) return data def append_data(self): - """BaseWSGIFilter interface""" + """BaseWSGIFilter interface + @rtype: [str] + """ if not self.compress: return [] self.gzip.close() diff --git a/wsgitools/middlewares.py b/wsgitools/middlewares.py index bee0ac3..871105c 100644 --- a/wsgitools/middlewares.py +++ b/wsgitools/middlewares.py @@ -13,10 +13,17 @@ __all__.append("SubdirMiddleware") class SubdirMiddleware: """Middleware choosing wsgi applications based on a dict.""" def __init__(self, default, mapping={}): + """ + @type default: wsgi app + @type mapping: {str: wsgi app} + """ self.default = default self.mapping = mapping def __call__(self, environ, start_response): - """wsgi interface""" + """wsgi interface + @type environ: {str: str} + @rtype: gen([str]) + """ assert isinstance(environ, dict) app = None script = environ["PATH_INFO"] @@ -45,7 +52,10 @@ class NoWriteCallableMiddleware: """Wraps wsgi application app.""" self.app = app def __call__(self, environ, start_response): - """wsgi interface""" + """wsgi interface + @type environ: {str, str} + @rtype: gen([str]) + """ assert isinstance(environ, dict) todo = [] def modified_start_response(status, headers, exc_info=None): @@ -196,7 +206,9 @@ class CachingMiddleware: self.cacheable = cacheable self.cache = {} def __call__(self, environ, start_response): - """wsgi interface""" + """wsgi interface + @type environ: {str: str} + """ assert isinstance(environ, dict) if not self.storable(environ): return self.app(environ, start_response) @@ -241,11 +253,17 @@ __all__.append("DictAuthChecker") class DictAuthChecker: """Verifies usernames and passwords by looking them up in a dict.""" def __init__(self, users): - """@param users: is a dict mapping usernames to password.""" + """ + @type users: {str: str} + @param users: is a dict mapping usernames to password.""" self.users = users def __call__(self, username, password): """check_function interface taking username and password and resulting - in a bool.""" + in a bool. + @type username: str + @type password: str + @rtype: bool + """ return username in self.users and self.users[username] == password __all__.append("BasicAuthMiddleware") @@ -256,13 +274,17 @@ class BasicAuthMiddleware: @param app: is a WSGI application. @param check_function: is a function taking two arguments username and password returning a bool indicating whether the request may is - allowed.""" + allowed. + @type realm: str + """ self.app = app self.check_function = check_function self.realm = realm def __call__(self, environ, start_response): - """wsgi interface""" + """wsgi interface + @type environ: {str: str} + """ assert isinstance(environ, dict) auth = environ.get("HTTP_AUTHORIZATION") if not auth or ' ' not in auth: @@ -281,7 +303,9 @@ class BasicAuthMiddleware: return self.authorization_required(environ, start_response) def authorization_required(self, environ, start_response): - """wsgi application for indicating authorization is required.""" + """wsgi application for indicating authorization is required. + @type environ: {str: str} + """ status = "401 Authorization required" html = "Authorization required" + \ "

Authorization required

\n" @@ -301,7 +325,9 @@ class TracebackMiddleware: """app is the wsgi application to proxy.""" self.app = app def __call__(self, environ, start_response): - """wsgi interface""" + """wsgi interface + @type environ: {str: str} + """ try: assert isinstance(environ, dict) ret = self.app(environ, start_response) -- cgit v1.2.3