diff --git a/requirements-dev.txt b/requirements-dev.txt index 0c89c6d53..27389a792 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,5 @@ -# bottle 0.12.17 changed behavior -# https://github.com/pycurl/pycurl/issues/573 -bottle flaky +flask pyflakes pytest>=5 sphinx diff --git a/tests/app.py b/tests/app.py index 62ff5744c..ea847ad5f 100644 --- a/tests/app.py +++ b/tests/app.py @@ -2,7 +2,7 @@ # vi:ts=4:et import time as _time, sys -import bottle +import flask try: import json except ImportError: @@ -10,7 +10,7 @@ py3 = sys.version_info[0] == 3 -app = bottle.Bottle() +app = flask.Flask(__name__) app.debug = True @app.route('/success') @@ -24,62 +24,47 @@ def short_wait(): @app.route('/status/403') def forbidden(): - return bottle.HTTPResponse('forbidden', 403) + return flask.Response('forbidden', 403) @app.route('/status/404') def not_found(): - return bottle.HTTPResponse('not found', 404) + return flask.Response('not found', 404) -@app.route('/postfields', method='get') -@app.route('/postfields', method='post') +@app.route('/postfields', methods=['GET', 'POST']) def postfields(): - return json.dumps(dict(bottle.request.forms)) + return json.dumps(dict(flask.request.form)) -@app.route('/raw_utf8', method='post') +@app.route('/raw_utf8', methods=['POST']) def raw_utf8(): - data = bottle.request.body.getvalue().decode('utf8') + data = flask.request.data.decode('utf8') return json.dumps(data) -# XXX file is not a bottle FileUpload instance, but FieldStorage? def xconvert_file(key, file): return { 'key': key, 'name': file.name, - 'raw_filename': file.raw_filename, + 'filename': file.filename, 'headers': file.headers, 'content_type': file.content_type, 'content_length': file.content_length, 'data': file.read(), } -if hasattr(bottle, 'FileUpload'): - # bottle 0.12 - def convert_file(key, file): - return { - 'name': file.name, - # file.filename lowercases the file name - # https://github.com/defnull/bottle/issues/582 - # raw_filenames is a string on python 3 - 'filename': file.raw_filename, - 'data': file.file.read().decode(), - } -else: - # bottle 0.11 - def convert_file(key, file): - return { - 'name': file.name, - 'filename': file.filename, - 'data': file.file.read().decode(), - } - -@app.route('/files', method='post') +def convert_file(key, file): + return { + 'name': file.name, + 'filename': file.filename, + 'data': file.read().decode(), + } + +@app.route('/files', methods=['POST']) def files(): - files = [convert_file(key, bottle.request.files[key]) for key in bottle.request.files] + files = [convert_file(key, flask.request.files[key]) for key in flask.request.files] return json.dumps(files) @app.route('/header') def header(): - return bottle.request.headers.get(bottle.request.query['h'], '') + return flask.request.headers.get(flask.request.args['h'], '') # This is a hacky endpoint to test non-ascii text being given to libcurl # via headers. @@ -89,7 +74,7 @@ def header(): # Thanks to bdarnell for the idea: https://github.com/pycurl/pycurl/issues/124 @app.route('/header_utf8') def header_utf8(): - header_value = bottle.request.headers.get(bottle.request.query['h'], '' if py3 else b'') + header_value = flask.request.headers.get(flask.request.args['h'], '' if py3 else b'') if py3: # header_value is a string, headers are decoded in latin1 header_value = header_value.encode('latin1').decode('utf8') @@ -98,13 +83,9 @@ def header_utf8(): header_value = header_value.decode('utf8') return header_value -@app.route('/param_utf8_hack', method='post') +@app.route('/param_utf8_hack', methods=['POST']) def param_utf8_hack(): - param = bottle.request.forms['p'] - if py3: - # python 3 decodes bytes as latin1 perhaps? - # apply the latin1-utf8 hack - param = param.encode('latin').decode('utf8') + param = flask.request.form['p'] return param def pause_writer(interval): @@ -127,19 +108,25 @@ def utf8_body(): @app.route('/invalid_utf8_body') def invalid_utf8_body(): - # bottle encodes the body - raise bottle.HTTPResponse(b'\xb3\xd2\xda\xcd\xd7', 200) + return flask.Response(b'\xb3\xd2\xda\xcd\xd7', 200) @app.route('/set_cookie_invalid_utf8') def set_cookie_invalid_utf8(): - bottle.response.set_header('Set-Cookie', '\xb3\xd2\xda\xcd\xd7=%96%A6g%9Ay%B0%A5g%A7tm%7C%95%9A') - return 'cookie set' + response = flask.Response('cookie set') + # WARNING: The original bottle test passed '\xb3\xd2\xda\xcd\xd7...' as string + # Presumably bottle encoded that as utf-8 in the response. + # Flask on the other hand encodes such strings as latin-1 (chars in == bytes out). + # In order to make the test pass I replicate the original bottle behavior by utf-8->latin1 roundtrip. + response.headers['Set-Cookie'] = '\xb3\xd2\xda\xcd\xd7=%96%A6g%9Ay%B0%A5g%A7tm%7C%95%9A'.encode('utf-8').decode('latin-1') + return response @app.route('/content_type_invalid_utf8') def content_type_invalid_utf8(): - bottle.response.set_header('Content-Type', '\xb3\xd2\xda\xcd\xd7') - return 'content type set' + response = flask.Response('content type set') + # See the WARNING in set_cookie_invalid_utf8 + response.headers['Content-Type'] = '\xb3\xd2\xda\xcd\xd7'.encode('utf-8').decode('latin-1') + return response @app.route('/status_invalid_utf8') def status_invalid_utf8(): - raise bottle.HTTPResponse('status set', '555 \xb3\xd2\xda\xcd\xd7') + raise flask.Response('status set', b'555 \xb3\xd2\xda\xcd\xd7') diff --git a/tests/runwsgi.py b/tests/runwsgi.py index ff00b8cac..b072b73ad 100644 --- a/tests/runwsgi.py +++ b/tests/runwsgi.py @@ -1,6 +1,5 @@ # Run a WSGI application in a daemon thread -import bottle import threading import os.path @@ -8,7 +7,14 @@ global_stop = False -class Server(bottle.WSGIRefServer): +class Server: + quiet = False + + def __init__(self, host, port, **options): + self.options = options + self.host = host + self.port = int(port) + def run(self, handler): # pragma: no cover self.srv = self.make_server(handler) self.serve() @@ -66,7 +72,7 @@ def __init__(self, app, port, server, server_kwargs): self.server = server(host='127.0.0.1', port=self.port, **self.server_kwargs) def run(self): - bottle.run(self.app, server=self.server, quiet=True) + self.server.run(self.app) started_servers = {}