summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hellkamp <marc@gsites.de>2009-07-24 22:30:36 +0200
committerMarcel Hellkamp <marc@gsites.de>2009-07-24 22:30:36 +0200
commit1c15aaf2ee01dc11662e2c02c072e8d218012c6e (patch)
tree3cda74e5c7cc38e87b65a206cb936be78203f6e8
parent30c1dfcf354e756ebe3454f5697bcaa0c48419a1 (diff)
downloadbottle-1c15aaf2ee01dc11662e2c02c072e8d218012c6e.tar.gz
Made bottle work with python >= 2.6 and python >= 3.0. Dropped support for python <= 2.5 and lower. Sorry.0.4.14
-rw-r--r--bottle.py60
-rw-r--r--setup.py3
-rw-r--r--test/test_db.py2
-rw-r--r--test/test_environ.py9
-rw-r--r--test/test_routes.py2
5 files changed, 45 insertions, 31 deletions
diff --git a/bottle.py b/bottle.py
index 3cb888c..d063976 100644
--- a/bottle.py
+++ b/bottle.py
@@ -62,10 +62,10 @@ Example
"""
__author__ = 'Marcel Hellkamp'
-__version__ = '0.4.14'
+__version__ = '0.4.15'
__license__ = 'MIT'
-
+import sys
import cgi
import mimetypes
import os
@@ -73,14 +73,24 @@ import os.path
import traceback
import re
import random
-from Cookie import SimpleCookie
import threading
import time
-from urlparse import parse_qs
-import cPickle as pickle
-import anydbm as dbm
from wsgiref.headers import Headers as HeaderWrapper
+if (2,6) <= sys.version_info < (3,0):
+ from Cookie import SimpleCookie
+ from urlparse import parse_qs
+ import cPickle as pickle
+ import anydbm as dbm
+elif (3,0) <= sys.version_info:
+ from http.cookies import SimpleCookie
+ from urllib.parse import parse_qs
+ import pickle
+ import dbm
+else:
+ raise NotImplementedError("Sorry, you need at least Python 2.6 or Python 3.x to use bottle.")
+
+
@@ -133,9 +143,9 @@ def WSGIHandler(environ, start_response):
if not handler:
raise HTTPError(404, "Not found")
output = handler(**args)
- except BreakTheBottle, e:
+ except BreakTheBottle as e:
output = e.output
- except Exception, e:
+ except Exception as e:
response.status = getattr(e, 'http_status', 500)
errorhandler = ERROR_HANDLER.get(response.status, error_default)
try:
@@ -198,7 +208,7 @@ class Request(threading.local):
if self._GET is None:
raw_dict = parse_qs(self.query_string, keep_blank_values=1)
self._GET = {}
- for key, value in raw_dict.iteritems():
+ for key, value in raw_dict.items():
if len(value) == 1:
self._GET[key] = value[0]
else:
@@ -235,7 +245,7 @@ class Request(threading.local):
if self._COOKIES is None:
raw_dict = SimpleCookie(self._environ.get('HTTP_COOKIE',''))
self._COOKIES = {}
- for cookie in raw_dict.itervalues():
+ for cookie in raw_dict.values():
self._COOKIES[cookie.key] = cookie.value
return self._COOKIES
@@ -254,7 +264,7 @@ class Response(threading.local):
def wsgiheaders(self):
''' Returns a wsgi conform list of header/value pairs '''
- for c in self.COOKIES.itervalues():
+ for c in self.COOKIES.values():
self.header.add_header('Set-Cookie', c.OutputString())
return [(h.title(), v) for h, v in self.header_list]
@@ -358,7 +368,7 @@ def match_url(url, method='GET'):
# Now search regexp routes
routes = ROUTES_REGEXP.get(method,[])
- for i in xrange(len(routes)):
+ for i in range(len(routes)):
match = routes[i][0].match(url)
if match:
handler = routes[i][1]
@@ -397,7 +407,7 @@ def validate(**vkargs):
abort(403, 'Missing parameter: %s' % key)
try:
kargs[key] = vkargs[key](kargs[key])
- except ValueError, e:
+ except ValueError as e:
abort(403, 'Wrong parameter format for: %s' % key)
return func(**kargs)
return wrapper
@@ -506,15 +516,15 @@ def run(server=WSGIRefServer, host='127.0.0.1', port=8080, optinmize = False, **
raise RuntimeError("Server must be a subclass of ServerAdapter")
if not quiet:
- print 'Bottle server starting up (using %s)...' % repr(server)
- print 'Listening on http://%s:%d/' % (server.host, server.port)
- print 'Use Ctrl-C to quit.'
- print
+ print('Bottle server starting up (using %s)...' % repr(server))
+ print('Listening on http://%s:%d/' % (server.host, server.port))
+ print('Use Ctrl-C to quit.')
+ print()
try:
server.run(WSGIHandler)
except KeyboardInterrupt:
- print "Shuting down..."
+ print("Shuting down...")
@@ -602,7 +612,7 @@ class SimpleTemplate(BaseTemplate):
strbuffer.append(line)
else:
flush()
- for i in xrange(1, len(splits), 2):
+ for i in range(1, len(splits), 2):
splits[i] = PyStmt(splits[i])
splits = [x for x in splits if bool(x)]
code.append(" " * indent + "stdout.extend(%s)\n" % repr(splits))
@@ -617,7 +627,7 @@ class SimpleTemplate(BaseTemplate):
''' Returns the rendered template using keyword arguments as local variables. '''
args['stdout'] = []
args['_subtemplates'] = self.subtemplates
- exec self.co in args
+ eval(self.co, args)
return ''.join(args['stdout'])
@@ -692,14 +702,14 @@ class BottleBucket(object):
return list(self.ukeys())
def ukeys(self):
- return set(self.db.keys() + self.mmap.keys())
+ return set(self.db.keys()) | set(self.mmap.keys())
def save(self):
self.close()
self.__init__(self.name)
def close(self):
- for key in self.mmap.iterkeys():
+ for key in self.mmap.keys():
pvalue = pickle.dumps(self.mmap[key], pickle.HIGHEST_PROTOCOL)
if key not in self.db or pvalue != self.db[key]:
self.db[key] = pvalue
@@ -707,7 +717,7 @@ class BottleBucket(object):
self.db.close()
def clear(self):
- for key in self.db.iterkeys():
+ for key in self.db.keys():
del self.db[key]
self.mmap.clear()
@@ -740,7 +750,7 @@ class BottleDB(threading.local):
if key not in self.open:
self.open[key] = BottleBucket(key)
self.open[key].clear()
- for k, v in value.iteritems():
+ for k, v in value.items():
self.open[key][k] = v
else:
raise ValueError("Only dicts and BottleBuckets are allowed.")
@@ -767,7 +777,7 @@ class BottleDB(threading.local):
self.__init__()
def close(self):
- for db in self.open.itervalues():
+ for db in self.open.values():
db.close()
self.open.clear()
diff --git a/setup.py b/setup.py
index 2bb21db..b5a2a3a 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,8 @@ setup(name='bottle',
'Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware',
'Topic :: Internet :: WWW/HTTP :: WSGI :: Server',
'Topic :: Software Development :: Libraries :: Application Frameworks',
- 'Programming Language :: Python :: 2']
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 3']
)
diff --git a/test/test_db.py b/test/test_db.py
index 2341d38..a627cbc 100644
--- a/test/test_db.py
+++ b/test/test_db.py
@@ -15,7 +15,7 @@ class TestDB(unittest.TestCase):
def test_save(self):
""" DB: Save to disk """
- data = [1, 1.5, 'a', u'ä']
+ data = [1, 1.5, 'a', 'ä']
bottle.db.db1.value1 = data
bottle.db['db2']['value2'] = data
diff --git a/test/test_environ.py b/test/test_environ.py
index fe43188..e4805de 100644
--- a/test/test_environ.py
+++ b/test/test_environ.py
@@ -32,8 +32,11 @@ class TestEnviron(unittest.TestCase):
self.assertEqual(qd, request.POST)
def test_multipart(self):
- """ Environ: POST (multipart) """
- import StringIO
+ """ Environ: POST (multipart) """
+ if sys.version_info[0] == 2:
+ from StringIO import StringIO
+ else:
+ from io import StringIO
e = {}
e['SERVER_PROTOCOL'] = "HTTP/1.1"
e['REQUEST_METHOD'] = 'POST'
@@ -50,7 +53,7 @@ class TestEnviron(unittest.TestCase):
e['wsgi.input'] += 'Content-Transfer-Encoding: binary\n'
e['wsgi.input'] += 'This is a sample\n'
e['wsgi.input'] += '------------------314159265358979323846--\n'
- e['wsgi.input'] = StringIO.StringIO(e['wsgi.input'])
+ e['wsgi.input'] = StringIO(e['wsgi.input'])
e['wsgi.input'].seek(0)
request.bind(e)
self.assertTrue('test.txt' in request.POST)
diff --git a/test/test_routes.py b/test/test_routes.py
index d9a93f2..fa33f57 100644
--- a/test/test_routes.py
+++ b/test/test_routes.py
@@ -19,7 +19,7 @@ class TestRoutes(unittest.TestCase):
for r in routes:
add_route(r, token, simple=True)
self.assertTrue('GET' in ROUTES_SIMPLE)
- r = [r for r in ROUTES_SIMPLE['GET'].itervalues() if r == 'abc']
+ r = [r for r in ROUTES_SIMPLE['GET'].values() if r == 'abc']
self.assertEqual(5, len(r))
for r in routes:
self.assertEqual(token, match_url(r)[0])