From 3ea19cb85b9e559334e6a66252ca1f7b32eb4f6eeb9e53a9067eda5d884ef569 Mon Sep 17 00:00:00 2001 From: Daniel Garcia Date: Tue, 24 Sep 2024 10:48:42 +0000 Subject: [PATCH] - Add upstream patch test-bottle-flask.patch to use Flask instead of bottle for tests. gh#pycurl/pycurl#838 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-pycurl?expand=0&rev=108 --- python-pycurl.changes | 7 ++ python-pycurl.spec | 4 +- test-bottle-flask.patch | 230 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 test-bottle-flask.patch diff --git a/python-pycurl.changes b/python-pycurl.changes index e5f821d..f7a0a9d 100644 --- a/python-pycurl.changes +++ b/python-pycurl.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Tue Sep 24 10:47:25 UTC 2024 - Daniel Garcia + +- Add upstream patch test-bottle-flask.patch to use Flask instead of + bottle for tests. + gh#pycurl/pycurl#838 + ------------------------------------------------------------------- Thu Jun 6 15:17:31 UTC 2024 - Dirk Müller diff --git a/python-pycurl.spec b/python-pycurl.spec index d3e6973..9b0f1f9 100644 --- a/python-pycurl.spec +++ b/python-pycurl.spec @@ -41,6 +41,8 @@ Patch2: disable_randomly_failing_tests.patch # PATCH-FIX-OPENSUSE make-leap15-compat.patch mcepl@suse.com # Make tests passing with Leap 15.2 Patch3: make-leap15-compat.patch +# PATCH-FIX-UPSTREAM test-bottle-flask.patch gh#pycurl/pycurl#838 +Patch4: test-bottle-flask.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module setuptools} BuildRequires: fdupes @@ -49,7 +51,7 @@ BuildRequires: python-rpm-macros BuildRequires: pkgconfig(libcurl) >= 7.19.0 BuildRequires: pkgconfig(openssl) %if %{with test} -BuildRequires: %{python_module bottle} +BuildRequires: %{python_module Flask} BuildRequires: %{python_module flaky} BuildRequires: %{python_module pytest} %endif diff --git a/test-bottle-flask.patch b/test-bottle-flask.patch new file mode 100644 index 0000000..9db4add --- /dev/null +++ b/test-bottle-flask.patch @@ -0,0 +1,230 @@ +Index: pycurl-7.45.3/README.rst +=================================================================== +--- pycurl-7.45.3.orig/README.rst ++++ pycurl-7.45.3/README.rst +@@ -89,7 +89,7 @@ PycURL comes with an automated test suit + + make test + +-The suite depends on packages `pytest`_ and `bottle`_, as well as `vsftpd`_. ++The suite depends on packages `pytest`_ and `flask`_, as well as `vsftpd`_. + + Some tests use vsftpd configured to accept anonymous uploads. These tests + are not run by default. As configured, vsftpd will allow reads and writes to +@@ -103,7 +103,7 @@ vsftpd tests you must explicitly set PYC + export PYCURL_VSFTPD_PATH=/usr/local/libexec/vsftpd + + .. _pytest: https://pytest.org/ +-.. _bottle: http://bottlepy.org/ ++.. _flask: https://flask.palletsprojects.com/ + .. _vsftpd: http://vsftpd.beasts.org/ + + +Index: pycurl-7.45.3/requirements-dev.txt +=================================================================== +--- pycurl-7.45.3.orig/requirements-dev.txt ++++ pycurl-7.45.3/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 +Index: pycurl-7.45.3/tests/app.py +=================================================================== +--- pycurl-7.45.3.orig/tests/app.py ++++ pycurl-7.45.3/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 @@ except ImportError: + + 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(), +- } ++def convert_file(key, file): ++ return { ++ 'name': file.name, ++ 'filename': file.filename, ++ 'data': file.read().decode(), ++ } + +-@app.route('/files', method='post') ++@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') +Index: pycurl-7.45.3/tests/runwsgi.py +=================================================================== +--- pycurl-7.45.3.orig/tests/runwsgi.py ++++ pycurl-7.45.3/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 @@ from . import util + + 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 @@ class ServerThread(threading.Thread): + 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 = {} +