Skip to content

Commit

Permalink
Docstrings.
Browse files Browse the repository at this point in the history
  • Loading branch information
defnull committed Sep 20, 2010
1 parent 3932ae5 commit 5f88aa2
Showing 1 changed file with 66 additions and 48 deletions.
114 changes: 66 additions & 48 deletions bottle.py
Expand Up @@ -660,8 +660,8 @@ def copy(self):
def path_shift(self, shift=1):
''' Shift path fragments from PATH_INFO to SCRIPT_NAME and vice versa.
:param shift: The number of path fragments to shift. May be negative to
change the shift direction. (default: 1)
:param shift: The number of path fragments to shift. May be negative
to change the shift direction. (default: 1)
'''
script_name = self.environ.get('SCRIPT_NAME','/')
self['SCRIPT_NAME'], self.path = path_shift(script_name, self.path, shift)
Expand All @@ -687,12 +687,12 @@ def __setitem__(self, key, value):

@property
def query_string(self):
""" The content of the QUERY_STRING environment variable. """
""" The part of the URL following the '?'. """
return self.environ.get('QUERY_STRING', '')

@property
def fullpath(self):
""" Request path including SCRIPT_NAME (if present) """
""" Request path including SCRIPT_NAME (if present). """
return self.environ.get('SCRIPT_NAME', '').rstrip('/') + self.path

@property
Expand All @@ -703,19 +703,20 @@ def url(self):
and includes scheme, host, port, scriptname, path and query string.
"""
scheme = self.environ.get('wsgi.url_scheme', 'http')
host = self.environ.get('HTTP_X_FORWARDED_HOST', self.environ.get('HTTP_HOST', None))
host = self.environ.get('HTTP_X_FORWARDED_HOST')
host = host or self.environ.get('HTTP_HOST', None)
if not host:
host = self.environ.get('SERVER_NAME')
port = self.environ.get('SERVER_PORT', '80')
if scheme + port not in ('https443', 'http80'):
if (scheme, port) not in (('https','443'), ('http','80')):
host += ':' + port
parts = (scheme, host, urlquote(self.fullpath), self.query_string, '')
return urlunsplit(parts)

@property
def content_length(self):
""" Content-Length header as an integer, -1 if not specified """
return int(self.environ.get('CONTENT_LENGTH','') or -1)
return int(self.environ.get('CONTENT_LENGTH', '') or -1)

@property
def header(self):
Expand All @@ -724,17 +725,22 @@ def header(self):

@property
def headers(self):
''' :class:`WSGIHeaderDict` filled with request headers. '''
''' A dict-like object filled with request headers.
This dictionary uses case-insensitive keys and native strings as
keys and values. See :class:`WSGIHeaderDict` for details.
'''
if 'bottle.headers' not in self.environ:
self.environ['bottle.headers'] = WSGIHeaderDict(self.environ)
return self.environ['bottle.headers']

@property
def GET(self):
""" The QUERY_STRING parsed into a MultiDict.
""" The QUERY_STRING parsed into an instance of :class:`MultiDict`.
Keys and values are strings. Multiple values per key are possible.
See MultiDict for details.
If you expect more than one value for a key, use ``.getall(key)`` on
this dictionary to get a list of all values. Otherwise, only the
first value is returned.
"""
if 'bottle.get' not in self.environ:
data = parse_qs(self.query_string, keep_blank_values=True)
Expand All @@ -746,13 +752,13 @@ def GET(self):

@property
def POST(self):
""" Property: The HTTP POST body parsed into a MultiDict.
This supports url-encoded and multipart POST requests. Multipart
is commonly used for file uploads and may result in some of the
values being cgi.FieldStorage objects instead of strings.
""" The combined values from :attr:`forms` and :attr:`files`. Values are
either strings (form values) or instances of
:class:`cgi.FieldStorage` (file uploads).
Multiple values per key are possible. See MultiDict for details.
If you expect more than one value for a key, use ``.getall(key)`` on
this dictionary to get a list of all values. Otherwise, only the
first value is returned.
"""
if 'bottle.post' not in self.environ:
self.environ['bottle.post'] = MultiDict()
Expand All @@ -779,28 +785,47 @@ def POST(self):

@property
def forms(self):
""" Property: HTTP POST form data parsed into a MultiDict. """
""" POST form values parsed into an instance of :class:`MultiDict`.
This property contains form values parsed from an `url-encoded`
or `multipart/form-data` encoded POST request bidy. The values are
native strings.
If you expect more than one value for a key, use ``.getall(key)`` on
this dictionary to get a list of all values. Otherwise, only the
first value is returned.
"""
if 'bottle.forms' not in self.environ: self.POST
return self.environ['bottle.forms']

@property
def files(self):
""" Property: HTTP POST file uploads parsed into a MultiDict. """
""" File uploads parsed into an instance of :class:`MultiDict`.
This property contains file uploads parsed from an
`multipart/form-data` encoded POST request body. The values are
instances of :class:`cgi.FieldStorage`.
If you expect more than one value for a key, use ``.getall(key)`` on
this dictionary to get a list of all values. Otherwise, only the
first value is returned.
"""
if 'bottle.files' not in self.environ: self.POST
return self.environ['bottle.files']

@property
def params(self):
""" A combined MultiDict with POST and GET parameters. """
""" A combined :class:`MultiDict` with values from :attr:`forms` and
:attr:`GET`. File-uploads are not included. """
if 'bottle.params' not in self.environ:
self.environ['bottle.params'] = MultiDict(self.GET)
self.environ['bottle.params'].update(dict(self.forms))
return self.environ['bottle.params']

@property
def body(self):
""" The HTTP request body as a seekable buffer object.
""" The HTTP request body as a seekable file-like object.
This property returns a copy of the `wsgi.input` stream and should
be used instead of `environ['wsgi.input']`.
"""
Expand All @@ -822,18 +847,16 @@ def body(self):
@property
def auth(self): #TODO: Tests and docs. Add support for digest. namedtuple?
""" HTTP authorization data as a (user, passwd) tuple. (experimental)
This implementation currently only supports basic auth and returns
None on errors.
"""
return parse_auth(self.headers.get('Authorization',''))

@property
def COOKIES(self):
""" Cookie information parsed into a dictionary.
Secure cookies are NOT decoded automatically. See
Request.get_cookie() for details.
""" Cookies parsed into a dictionary. Secure cookies are NOT decoded
automatically. See :meth:`get_cookie` for details.
"""
if 'bottle.cookies' not in self.environ:
raw_dict = SimpleCookie(self.headers.get('Cookie',''))
Expand Down Expand Up @@ -882,7 +905,7 @@ def header(self):
return self.headers

def copy(self):
''' Returns a copy of self '''
''' Returns a copy of self. '''
copy = Response()
copy.status = self.status
copy.headers = self.headers.copy()
Expand Down Expand Up @@ -918,7 +941,7 @@ def charset(self):

@property
def COOKIES(self):
""" A dict-like SimpleCookie instance. Use Response.set_cookie() instead. """
""" A dict-like SimpleCookie instance. Use :meth:`set_cookie` instead. """
if not self._COOKIES:
self._COOKIES = SimpleCookie()
return self._COOKIES
Expand All @@ -927,14 +950,14 @@ def set_cookie(self, key, value, secret=None, **kargs):
''' Add a cookie. If the `secret` parameter is set, this creates a
`Secure Cookie` (described below).
|param key| the name of the cookie.
|param value| the value of the cookie.
|param secret| required for secure cookies. (default: None)
|param max_age| maximum age in seconds. (default: None)
|param expires| a datetime object or UNIX timestamp. (defaut: None)
|param domain| the domain that is allowed to read the cookie.
:param key: the name of the cookie.
:param value: the value of the cookie.
:param secret: required for secure cookies. (default: None)
:param max_age: maximum age in seconds. (default: None)
:param expires: a datetime object or UNIX timestamp. (defaut: None)
:param domain: the domain that is allowed to read the cookie.
(default: current domain)
|param path| limits the cookie to a given path (default: /)
:param path: limits the cookie to a given path (default: /)
If neither `expires` nor `max_age` are set (default), the cookie
lasts only as long as the browser is not closed.
Expand All @@ -952,15 +975,14 @@ def set_cookie(self, key, value, secret=None, **kargs):
value = touni(cookie_encode((key, value), secret))
elif not isinstance(value, basestring):
raise TypeError('Secret missing for non-string Cookie.')

self.COOKIES[key] = value
for k, v in kargs.iteritems():
self.COOKIES[key][k.replace('_', '-')] = v

def delete_cookie(self, key, **kwargs):
''' Delete a cookie. Be sure to use the same `domain` and `path`
parameters as used to create the cookie.
'''
parameters as used to create the cookie. '''
kwargs['max_age'] = -1
kwargs['expires'] = 0
self.set_cookie(key, **kwargs)
Expand Down Expand Up @@ -1329,8 +1351,8 @@ def default():

class ServerAdapter(object):
quiet = False
def __init__(self, host='127.0.0.1', port=8080, **kargs):
self.options = kargs
def __init__(self, host='127.0.0.1', port=8080, **config):
self.options = config
self.host = host
self.port = int(port)

Expand Down Expand Up @@ -1389,10 +1411,7 @@ def run(self, handler):
server.run(handler)

class FapwsServer(ServerAdapter):
"""
Extremely fast webserver using libev.
See http://william-os4y.livejournal.com/
"""
""" Extremely fast webserver using libev. See http://www.fapws.org/ """
def run(self, handler): # pragma: no cover
import fapws._evwsgi as evwsgi
from fapws import base, config
Expand All @@ -1414,8 +1433,7 @@ def app(environ, start_response):


class TornadoServer(ServerAdapter):
""" Untested. As described here:
http://github.com/facebook/tornado/blob/master/tornado/wsgi.py#L187 """
""" The super hyped asynchronous server by facebook. Untested. """
def run(self, handler): # pragma: no cover
import tornado.wsgi
import tornado.httpserver
Expand All @@ -1427,7 +1445,7 @@ def run(self, handler): # pragma: no cover


class AppEngineServer(ServerAdapter):
""" Untested. """
""" Adapter for Google App Engine. """
quiet = True
def run(self, handler):
from google.appengine.ext.webapp import util
Expand Down

0 comments on commit 5f88aa2

Please sign in to comment.