Skip to content

Commit

Permalink
Made bottle work with python >= 2.6 and python >= 3.0. Dropped suppor…
Browse files Browse the repository at this point in the history
…t for python <= 2.5 and lower. Sorry.
  • Loading branch information
defnull committed Jul 24, 2009
1 parent 30c1dfc commit 1c15aaf
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 31 deletions.
60 changes: 35 additions & 25 deletions bottle.py
Expand Up @@ -62,25 +62,35 @@ def static_file(filename):
"""

__author__ = 'Marcel Hellkamp'
__version__ = '0.4.14'
__version__ = '0.4.15'
__license__ = 'MIT'


import sys
import cgi
import mimetypes
import os
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.")





Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -198,7 +208,7 @@ def GET(self):
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:
Expand Down Expand Up @@ -235,7 +245,7 @@ def COOKIES(self):
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

Expand All @@ -254,7 +264,7 @@ def bind(self):

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]

Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -397,7 +407,7 @@ def wrapper(**kargs):
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
Expand Down Expand Up @@ -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...")



Expand Down Expand Up @@ -602,7 +612,7 @@ def flush(allow_nobreak=False):
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))
Expand All @@ -617,7 +627,7 @@ def render(self, **args):
''' 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'])


Expand Down Expand Up @@ -692,22 +702,22 @@ def keys(self):
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
self.mmap.clear()
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()

Expand Down Expand Up @@ -740,7 +750,7 @@ def __setitem__(self, key, value):
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.")
Expand All @@ -767,7 +777,7 @@ def save(self):
self.__init__()

def close(self):
for db in self.open.itervalues():
for db in self.open.values():
db.close()
self.open.clear()

Expand Down
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -22,7 +22,8 @@
'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']
)


Expand Down
2 changes: 1 addition & 1 deletion test/test_db.py
Expand Up @@ -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

Expand Down
9 changes: 6 additions & 3 deletions test/test_environ.py
Expand Up @@ -32,8 +32,11 @@ def test_multigetpost(self):
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'
Expand All @@ -50,7 +53,7 @@ def test_multipart(self):
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)
Expand Down
2 changes: 1 addition & 1 deletion test/test_routes.py
Expand Up @@ -19,7 +19,7 @@ def test_static(self):
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])
Expand Down

0 comments on commit 1c15aaf

Please sign in to comment.