diff options
author | Marcel Hellkamp <marc@gsites.de> | 2011-11-15 16:08:40 +0100 |
---|---|---|
committer | Marcel Hellkamp <marc@gsites.de> | 2011-11-15 16:08:40 +0100 |
commit | 8daa140a50670d56e279c55775c3982272de53fa (patch) | |
tree | b201643abfe1d13c3165bb4f3d4e4d764d06005f | |
parent | 620cb12436ab0c64ad8cc4e574016bcf2da4f7b5 (diff) | |
download | bottle-8daa140a50670d56e279c55775c3982272de53fa.tar.gz |
fix #250: The command-line interface now calls gevent.monkey.patch_all() if the gevent server adapter is used.
fix #212: Added MultiDict.getlist alias for MultiDict.getall to support WTForms again.
api: FormsDict.__getattr__ now returns an empty string on missing keys or unicode errors (instead of None).
-rwxr-xr-x | bottle.py | 47 | ||||
-rw-r--r-- | test/servertest.py | 35 | ||||
-rw-r--r-- | test/test_formsdict.py | 8 |
3 files changed, 50 insertions, 40 deletions
@@ -19,6 +19,18 @@ __author__ = 'Marcel Hellkamp' __version__ = '0.10.dev' __license__ = 'MIT' +import sys + +if __name__ == '__main__': + # This needs to happen before thread(ing) is imported. + from optparse import OptionParser + parser = OptionParser() + parser.add_option("-s", "--server") + opt, args = parser.parse_args() + if opt.server.startswith('gevent'): + from gevent import monkey + monkey.patch_all() + import base64 import cgi import email.utils @@ -31,7 +43,6 @@ import mimetypes import os import re import subprocess -import sys import tempfile import thread import threading @@ -1582,9 +1593,6 @@ class MultiDict(DictMixin): pass return default - #: Alias for :meth:`get` to mimic other multi-dict APIs (Django) - getone = get - def append(self, key, value): ''' Add a new value to the list of values for this key. ''' self.dict.setdefault(key, []).append(value) @@ -1597,6 +1605,11 @@ class MultiDict(DictMixin): ''' Return a (possibly empty) list of values for a key. ''' return self.dict.get(key) or [] + #: Aliases for WTForms to mimic other multi-dict APIs (Django) + getone = get + getlist = getall + + class FormsDict(MultiDict): ''' This :class:`MultiDict` subclass is used to store request form data. @@ -1604,7 +1617,7 @@ class FormsDict(MultiDict): unmodified data as native strings), this container also supports attribute-like access to its values. Attribues are automatiically de- or recoded to match :attr:`input_encoding` (default: 'utf8'). Missing - attributes default to ``None``. ''' + attributes default to an empty string. ''' #: Encoding used for attribute values. input_encoding = 'utf8' @@ -1620,7 +1633,7 @@ class FormsDict(MultiDict): except UnicodeError, e: return default - __getattr__ = getunicode + def __getattr__(self, name): return self.getunicode(name, default=u'') class HeaderDict(MultiDict): @@ -2873,19 +2886,16 @@ app.push() #: Example: ``import bottle.ext.sqlite`` actually imports `bottle_sqlite`. ext = _ImportRedirect(__name__+'.ext', 'bottle_%s').module -def main(): - from optparse import OptionParser - parser = OptionParser(usage="usage: %prog [options] package.module:application") +if __name__ == '__main__': + parser = OptionParser(usage="usage: %prog [options] package.module:app") add = parser.add_option add("-b", "--bind", metavar="ADDRESS", help="bind socket to ADDRESS.") - add("-s", "--server", help="use SERVER as backend. (default: wsgiref)") + add("-s", "--server", default='wsgiref', help="use SERVER as backend.") add("-p", "--plugin", action="append", help="install additinal plugin/s.") add("--debug", action="store_true", help="start server in debug mode.") add("--reload", action="store_true", help="auto-reload on file changes.") opt, args = parser.parse_args() - debug(opt.debug) - - if len(args) != 1: parser.error('No application specified.') + if not args: parser.error('No application specified.') try: sys.path.insert(0, '.') @@ -2895,14 +2905,11 @@ def main(): except (AttributeError, ImportError), e: parser.error(e.args[0]) - if opt.bind and ':' in opt.bind: host, port = opt.bind.rsplit(':', 1) - else: host, port = opt.bind or 'localhost', 8080 - if not app.routes: parser.error('App does not define any routes.') if opt.server not in server_names: parser.error('Unknown server backend.') - run(app, host=host, port=port, server=opt.server or 'wsgiref', - reloader=opt.reload) + if opt.bind and ':' in opt.bind: host, port = opt.bind.rsplit(':', 1) + else: host, port = opt.bind or 'localhost', 8080 -if __name__ == '__main__': - main() + debug(opt.debug) + run(app, host=host, port=port, server=opt.server, reloader=opt.reload) # THE END diff --git a/test/servertest.py b/test/servertest.py index 9080b27..4810e1e 100644 --- a/test/servertest.py +++ b/test/servertest.py @@ -1,33 +1,36 @@ +if __name__ != '__main__': + raise ImportError('This is not a module, but a script.') + import sys, os, socket test_root = os.path.dirname(os.path.abspath(__file__)) os.chdir(test_root) sys.path.insert(0, os.path.dirname(test_root)) sys.path.insert(0, test_root) -import bottle -from bottle import route, run - if 'coverage' in sys.argv: import coverage cov = coverage.coverage(data_suffix=True, branch=True) cov.start() -@route() -def test(): - return "OK" - -if __name__ == '__main__': +try: server = sys.argv[1] port = int(sys.argv[2]) - try: - run(port=port, server=server, quiet=True) - except socket.error: - sys.exit(1) - except ImportError: - sys.exit(128) - except KeyboardInterrupt: - pass + if server == 'gevent': + from gevent import monkey + monkey.patch_all() + + from bottle import route, run + route('/test', callback=lambda: 'OK') + run(port=port, server=server, quiet=True) + +except socket.error: + sys.exit(1) +except ImportError: + sys.exit(128) +except KeyboardInterrupt: + pass +finally: if 'coverage' in sys.argv: cov.stop() cov.save() diff --git a/test/test_formsdict.py b/test/test_formsdict.py index 7bd9060..fd862b8 100644 --- a/test/test_formsdict.py +++ b/test/test_formsdict.py @@ -12,14 +12,14 @@ class TestFormsDict(unittest.TestCase): self.assertEqual(u'äöü', d.py3) def test_attr_missing(self): - """ FomsDict.attribute returs None on missing keys. """ + """ FomsDict.attribute returs u'' on missing keys. """ d = FormsDict() - self.assertEqual(None, d.missing) + self.assertEqual(u'', d.missing) def test_attr_unicode_error(self): - """ FomsDict.attribute returs None on UnicodeError. """ + """ FomsDict.attribute returs u'' on UnicodeError. """ d = FormsDict(latin=u'äöü'.encode('latin1')) - self.assertEqual(None, d.latin) + self.assertEqual(u'', d.latin) d.input_encoding = 'latin1' self.assertEqual(u'äöü', d.latin) |