Repository: bepasty/bepasty-server (language: python)

Issue:
upgrade Jinja2, Flask, markupsafe and fix rest_server tests
I needed to do that to get all the tests working:

https://github.com/bepasty/bepasty-server/pull/285/commits/f7cbcb4017d1c5fdbe6ead677ddc67bf5b32e2b2



Discussion / hints:

Fix patch:
diff --git a/setup.cfg b/setup.cfg
index b632a84..a75a787 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,9 +32,7 @@ zip_false = False
 setup_requires =
     setuptools_scm
 install_requires =
-        markupsafe<2  # required so Jinja2 doesn't fail
-        Jinja2<3
-        Flask<2
+        Flask
         Pygments>=2.12.0
         xstatic
         XStatic-asciinema-player


Test patch:
diff --git a/src/bepasty/tests/conftest.py b/src/bepasty/tests/conftest.py
index a797089..cf09048 100644
--- a/src/bepasty/tests/conftest.py
+++ b/src/bepasty/tests/conftest.py
@@ -7,7 +7,7 @@
 from bepasty.app import create_app
 
 
-@pytest.yield_fixture(scope='module')
+@pytest.fixture(scope='module')
 def app(request):
     """
     creates a bepasty App-Instance
@@ -17,7 +17,7 @@ def app(request):
     unlink(app.config['DATABASE'])
 
 
-@pytest.yield_fixture(scope='module')
+@pytest.fixture(scope='module')
 def testclient(request, app):
     """
     creates a Flask-testclient instance for bepasty
diff --git a/src/bepasty/tests/test_rest_server.py b/src/bepasty/tests/test_rest_server.py
index 8d20713..d2943cf 100644
--- a/src/bepasty/tests/test_rest_server.py
+++ b/src/bepasty/tests/test_rest_server.py
@@ -152,8 +152,8 @@ def add_auth(user, password, headers=None):
 def test_invalid_url(client_fixture):
     _, client, _ = client_fixture
 
-    response = client.get('/apis/rest/invalid')
-    assert response.status_code == 404
+    with client.get('/apis/rest/invalid') as response:
+        assert response.status_code == 404
 
 
 def check_response(response, code, ftype='application/json', check_data=True):
@@ -212,18 +212,18 @@ def test_auth(client_fixture):
     url = RestUrl()
 
     # basic auth (unknown user)
-    response = client.get(url.list, headers=add_auth('user', 'invalid'))
-    check_err_response(response, 403)
+    with client.get(url.list, headers=add_auth('user', 'invalid')) as response:
+        check_err_response(response, 403)
     # basic auth (valid user)
-    response = client.get(url.list, headers=add_auth('user', 'full'))
-    check_response(response, 200)
+    with client.get(url.list, headers=add_auth('user', 'full')) as response:
+        check_response(response, 200)
 
     # token auth (unknown user)
-    response = client.get(url.list + '?token=invalid')
-    check_err_response(response, 403)
+    with client.get(url.list + '?token=invalid') as response:
+        check_err_response(response, 403)
     # token auth (valid user)
-    response = client.get(url.list + '?token=full')
-    check_response(response, 200)
+    with client.get(url.list + '?token=full') as response:
+        check_response(response, 200)
 
 
 def test_config(client_fixture):
@@ -232,19 +232,19 @@ def test_config(client_fixture):
     url = RestUrl()
 
     # get server config (post should fail)
-    response = client.post(url.config)
-    check_err_response(response, 405)
+    with client.post(url.config) as response:
+        check_err_response(response, 405)
 
     # get server config
-    response = client.get(url.config)
-    check_response(response, 200)
-    assert len(response.json) == 2
-    assert response.json['MAX_ALLOWED_FILE_SIZE'] == app.config['MAX_ALLOWED_FILE_SIZE']
-    assert response.json['MAX_BODY_SIZE'] == app.config['MAX_BODY_SIZE']
+    with client.get(url.config) as response:
+        check_response(response, 200)
+        assert len(response.json) == 2
+        assert response.json['MAX_ALLOWED_FILE_SIZE'] == app.config['MAX_ALLOWED_FILE_SIZE']
+        assert response.json['MAX_BODY_SIZE'] == app.config['MAX_BODY_SIZE']
 
     # get server config (head)
-    response = client.head(url.config)
-    check_response(response, 200, check_data=False)
+    with client.head(url.config) as response:
+        check_response(response, 200, check_data=False)
 
 
 def _upload(client, data, token=None, filename=None, ftype=None, lifetime=None,
@@ -315,8 +315,8 @@ def make_meta(data, filename=None, ftype=None, lifetime=None, uri=None):
 
 
 def upload(client, data, token=None, filename=None, ftype=None, lifetime=None):
-    response = _upload(client, data, token, filename, ftype, lifetime)
-    uri = check_upload_response(response)
+    with _upload(client, data, token, filename, ftype, lifetime) as response:
+        uri = check_upload_response(response)
 
     return make_meta(data, filename, ftype, lifetime, uri)
 
@@ -357,51 +357,51 @@ def check_detail_or_download(app, client, item_id, meta, data, download=False):
     url = url.download if download else url.detail
 
     # post should fail
-    response = client.post(url)
-    check_err_response(response, 405)
+    with client.post(url) as response:
+        check_err_response(response, 405)
 
     # get with default (no permission)
-    response = client.get(url)
-    check_err_response(response, 403)
+    with client.get(url) as response:
+        check_err_response(response, 403)
     # head with default (no permission)
-    response = client.head(url)
-    check_err_response(response, 403, check_data=False)
+    with client.head(url) as response:
+        check_err_response(response, 403, check_data=False)
 
     with TmpConfig(app, {'DEFAULT_PERMISSIONS': 'read'}):
         # head with default (has permission)
-        response = client.head(url)
-        if download:
-            check_data_response(response, meta, data, check_data=False)
-        else:
-            check_json_response(response, meta, check_data=False)
+        with client.head(url) as response:
+            if download:
+                check_data_response(response, meta, data, check_data=False)
+            else:
+                check_json_response(response, meta, check_data=False)
 
         # get with default (has permission)
-        response = client.get(url)
-        if download:
-            check_data_response(response, meta, data)
-        else:
-            check_json_response(response, meta)
+        with client.get(url) as response:
+            if download:
+                check_data_response(response, meta, data)
+            else:
+                check_json_response(response, meta)
 
     # get with no permission
-    response = client.get(url, headers=add_auth('user', 'none'))
-    check_err_response(response, 403)
+    with client.get(url, headers=add_auth('user', 'none')) as response:
+        check_err_response(response, 403)
     # head with no permission
-    response = client.head(url, headers=add_auth('user', 'none'))
-    check_err_response(response, 403, check_data=False)
+    with client.head(url, headers=add_auth('user', 'none')) as response:
+        check_err_response(response, 403, check_data=False)
 
     # head with permission
-    response = client.head(url, headers=add_auth('user', 'full'))
-    if download:
-        check_data_response(response, meta, data, check_data=False)
-    else:
-        check_json_response(response, meta, check_data=False)
+    with client.head(url, headers=add_auth('user', 'full')) as response:
+        if download:
+            check_data_response(response, meta, data, check_data=False)
+        else:
+            check_json_response(response, meta, check_data=False)
 
     # get with permission
-    response = client.get(url, headers=add_auth('user', 'full'))
-    if download:
-        check_data_response(response, meta, data)
-    else:
-        check_json_response(response, meta)
+    with client.get(url, headers=add_auth('user', 'full')) as response:
+        if download:
+            check_data_response(response, meta, data)
+        else:
+            check_json_response(response, meta)
 
 
 def check_expired(client, item_id, download=False):
@@ -409,17 +409,17 @@ def check_expired(client, item_id, download=False):
     url = url.download if download else url.detail
 
     # expired items
-    response = client.get(url, headers=add_auth('user', 'full'))
-    check_err_response(response, 404)
+    with client.get(url, headers=add_auth('user', 'full')) as response:
+        check_err_response(response, 404)
 
 
 def test_upload_basic(client_fixture):
     _, client, _ = client_fixture
 
     # simple upload without permission
-    response = _upload(client, UPLOAD_DATA, token='none', filename='test.py',
-                       ftype='text/x-python', lifetime=[1, 'FOREVER'])
-    check_err_response(response, 403)
+    with _upload(client, UPLOAD_DATA, token='none', filename='test.py',
+                 ftype='text/x-python', lifetime=[1, 'FOREVER']) as response:
+        check_err_response(response, 403)
 
     # simple upload with permission
     upload(client, UPLOAD_DATA, token='full', filename='test.py',
@@ -439,20 +439,20 @@ def test_upload_params(client_fixture):
 
         url = RestUrl(item_id)
         # get meta for uploaded item
-        response = client.get(url.detail, headers=add_auth('user', 'full'))
-        check_json_response(response, None, check_data=False)
-        assert len(response.json) > 0
-        # copy generated meta
-        if filename:
-            assert response.json['file-meta'][FILENAME] == filename
-        else:
-            assert len(response.json['file-meta'][FILENAME]) > 0
-            meta['file-meta'][FILENAME] = response.json['file-meta'][FILENAME]
-        if ftype:
-            assert response.json['file-meta'][TYPE] == ftype
-        else:
-            assert len(response.json['file-meta'][TYPE]) > 0
-            meta['file-meta'][TYPE] = response.json['file-meta'][TYPE]
+        with client.get(url.detail, headers=add_auth('user', 'full')) as response:
+            check_json_response(response, None, check_data=False)
+            assert len(response.json) > 0
+            # copy generated meta
+            if filename:
+                assert response.json['file-meta'][FILENAME] == filename
+            else:
+                assert len(response.json['file-meta'][FILENAME]) > 0
+                meta['file-meta'][FILENAME] = response.json['file-meta'][FILENAME]
+            if ftype:
+                assert response.json['file-meta'][TYPE] == ftype
+            else:
+                assert len(response.json['file-meta'][TYPE]) > 0
+                meta['file-meta'][TYPE] = response.json['file-meta'][TYPE]
 
         check_detail_or_download(app, client, item_id, meta, UPLOAD_DATA)
         check_detail_or_download(app, client, item_id, meta, UPLOAD_DATA,
@@ -471,77 +471,77 @@ def test_upload_range(client_fixture):
     data = UPLOAD_DATA[:sep]
 
     # (invalid no Content-Range:)
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, set_range=False)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, set_range=False) as response:
+        check_err_response(response, 400)
 
     # Content-Range: invalid (invalid format)
     range_str = 'invalid'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes invalid (invalid format)
     range_str = 'bytes invalid'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: other 0-<sep - 1>/<len(data)> (invalid unit)
     range_str = f'other {0}-{sep - 1}/{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes invalid-<sep - 1>/<len(data)> (invalid first)
     range_str = f'bytes invalid-{sep - 1}/{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes 0-invalid/<len(data)> (invalid last)
     range_str = f'bytes {0}-invalid/{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes <sep - 1>-0/<len(data)> (invalid first > last)
     range_str = f'bytes {sep - 1}-{0}/{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes 0-<sep - 1>/* (not supported)
     range_str = f'bytes {0}-{sep - 1}/*'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes */<len(data)> (not supported)
     range_str = f'bytes */{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # Content-Range: bytes */* (not supported)
     range_str = 'bytes */*'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_err_response(response, 400)
 
     # upload first part of data
     range_str = f'bytes {0}-{sep - 1}/{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_upload_response(response, 200)
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_upload_response(response, 200)
 
     # upload remainder of data
     data = UPLOAD_DATA[sep:]
     range_str = 'bytes {}-{}/{}'.format(sep, len(UPLOAD_DATA) - 1,
                                         len(UPLOAD_DATA))
-    response = _upload(client, data, token='full', range_str=range_str,
-                       trans_id=response.headers[TRANSACTION_ID])
-    uri = check_upload_response(response)
+    with _upload(client, data, token='full', range_str=range_str,
+                 trans_id=response.headers[TRANSACTION_ID]) as response:
+        uri = check_upload_response(response)
     item_id = os.path.basename(uri)
 
     # check a uploaded item
@@ -554,9 +554,9 @@ def test_upload_range(client_fixture):
     data = UPLOAD_DATA[sep + 1:]
     range_str = 'bytes {}-{}/{}'.format(sep + 1, len(UPLOAD_DATA) - 1,
                                         len(UPLOAD_DATA))
-    response = _upload(client, data, token='full', range_str=range_str,
-                       trans_id=response.headers[TRANSACTION_ID])
-    check_err_response(response, 409)
+    with _upload(client, data, token='full', range_str=range_str,
+                 trans_id=response.headers[TRANSACTION_ID]) as response:
+        check_err_response(response, 409)
 
 
 def test_bad_data(client_fixture):
@@ -567,15 +567,15 @@ def test_bad_data(client_fixture):
 
     # upload without Content-Length
     range_str = f'bytes 0-{len(UPLOAD_DATA) - 1}/{len(UPLOAD_DATA)}'
-    response = _upload(client, None, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str, encode=False)
-    check_err_response(response, 400)
+    with _upload(client, None, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str, encode=False) as response:
+        check_err_response(response, 400)
 
     # upload invalid base64 encode
     range_str = f'bytes 0-{len(UPLOAD_DATA) - 1}/{len(UPLOAD_DATA)}'
-    response = _upload(client, UPLOAD_DATA, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str, encode=False)
-    check_err_response(response, 400)
+    with _upload(client, UPLOAD_DATA, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str, encode=False) as response:
+        check_err_response(response, 400)
 
     # server must not have left garbage files
     assert len(os.listdir(app.config['STORAGE_FILESYSTEM_DIRECTORY'])) == 0
@@ -587,12 +587,12 @@ def test_upload_maxlife(client_fixture):
     _, client, _ = client_fixture
 
     lifetime = ['foo', 'MINUTES']
-    response = _upload(client, UPLOAD_DATA, token='full', lifetime=lifetime)
-    assert response.status_code == 400
+    with _upload(client, UPLOAD_DATA, token='full', lifetime=lifetime) as response:
+        assert response.status_code == 400
 
     lifetime = ['1', 'foo']
-    response = _upload(client, UPLOAD_DATA, token='full', lifetime=lifetime)
-    assert response.status_code == 400
+    with _upload(client, UPLOAD_DATA, token='full', lifetime=lifetime) as response:
+        assert response.status_code == 400
 
 
 def test_upload_transaction_id(client_fixture):
@@ -607,15 +607,15 @@ def test_upload_transaction_id(client_fixture):
 
     # upload with invalid Transaction-ID
     trans_id = 'invalid'
-    response = _upload(client, data, token='full', range_str=range_str,
-                       trans_id=trans_id)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', range_str=range_str,
+                 trans_id=trans_id) as response:
+        check_err_response(response, 400)
 
     # upload with Transaction-ID for invalid filename
     trans_id = base64.b64encode(b'invalid')
-    response = _upload(client, data, token='full', range_str=range_str,
-                       trans_id=trans_id)
-    check_err_response(response, 400)
+    with _upload(client, data, token='full', range_str=range_str,
+                 trans_id=trans_id) as response:
+        check_err_response(response, 400)
 
 
 def test_upload_too_big(client_fixture):
@@ -626,8 +626,8 @@ def test_upload_too_big(client_fixture):
     with TmpConfig(app, {'MAX_ALLOWED_FILE_SIZE': size}):
         ftype = 'text/x-bepasty-list'
         data = bytes(b'a' * (size + 10))
-        response = _upload(client, data, token='full', ftype=ftype)
-        check_err_response(response, 413)
+        with _upload(client, data, token='full', ftype=ftype) as response:
+            check_err_response(response, 413)
 
 
 def test_list_basic(client_fixture):
@@ -639,35 +639,35 @@ def test_list_basic(client_fixture):
     datas, metas = upload_files(client)
 
     # list with default (no permission)
-    response = client.get(url.list)
-    check_err_response(response, 403)
-    response = client.head(url.list)
-    check_err_response(response, 403, check_data=False)
+    with client.get(url.list) as response:
+        check_err_response(response, 403)
+    with client.head(url.list) as response:
+        check_err_response(response, 403, check_data=False)
 
     # list with default (has permission)
     with TmpConfig(app, {'DEFAULT_PERMISSIONS': 'list'}):
-        response = client.get(url.list)
-        check_json_response(response, metas)
-        response = client.head(url.list)
-        check_json_response(response, metas, check_data=False)
+        with client.get(url.list) as response:
+            check_json_response(response, metas)
+        with client.head(url.list) as response:
+            check_json_response(response, metas, check_data=False)
 
     # list with no permission
-    response = client.get(url.list, headers=add_auth('user', 'none'))
-    check_err_response(response, 403)
-    response = client.head(url.list, headers=add_auth('user', 'none'))
-    check_err_response(response, 403, check_data=False)
+    with client.get(url.list, headers=add_auth('user', 'none')) as response:
+        check_err_response(response, 403)
+    with client.head(url.list, headers=add_auth('user', 'none')) as response:
+        check_err_response(response, 403, check_data=False)
 
     # list with permission
-    response = client.get(url.list, headers=add_auth('user', 'full'))
-    check_json_response(response, metas)
-    response = client.head(url.list, headers=add_auth('user', 'full'))
-    check_json_response(response, metas, check_data=False)
+    with client.get(url.list, headers=add_auth('user', 'full')) as response:
+        check_json_response(response, metas)
+    with client.head(url.list, headers=add_auth('user', 'full')) as response:
+        check_json_response(response, metas, check_data=False)
 
     # adjust time to exceed lifetime
     faketime.set_time(3600 * 24 * 365 * 2)
     # list for expired items
-    response = client.get(url.list, headers=add_auth('user', 'full'))
-    check_json_response(response, {})
+    with client.get(url.list, headers=add_auth('user', 'full')) as response:
+        check_json_response(response, {})
 
 
 def test_detail_basic(client_fixture):
@@ -731,82 +731,82 @@ def test_download_range(client_fixture):
         offset = 0
         limit = 10
         headers['Range'] = 'other'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=invalid (invalid format)
         offset = 0
         limit = 10
         headers['Range'] = 'bytes=invalid'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: other=0-10 (invalid unit)
         offset = 0
         limit = 10
         headers['Range'] = f'other={offset}-{limit - 1}'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=invalid-10 (invalid first)
         offset = 0
         limit = 10
         headers['Range'] = f'bytes=invalid-{limit - 1}'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=0-invalid (invalid last)
         offset = 0
         limit = 10
         headers['Range'] = f'other={offset}-invalid'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=10-0 (invalid first > last)
         offset = 0
         limit = 10
         headers['Range'] = f'bytes={limit - 1}-{offset}'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=0-9,10-<limit - 1> (not supported for now)
         offset = 0
         limit = len(data)
         headers['Range'] = f'bytes={offset}-9,10-{limit - 1}'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=0-10
         offset = 0
         limit = 10
         headers['Range'] = f'bytes={offset}-{limit - 1}'
-        response = client.get(url.download, headers=headers)
-        check_data_response(response, meta, data[offset:limit], offset=offset,
-                            total_size=len(data))
+        with client.get(url.download, headers=headers) as response:
+            check_data_response(response, meta, data[offset:limit],
+                                offset=offset, total_size=len(data))
 
         # Range: bytes=-9
         # FIXME: suffix-byte-range-spec is not supported for now
         offset = 0
         limit = 10
         headers['Range'] = f'bytes=-{limit - 1}'
-        response = client.get(url.download, headers=headers)
-        check_err_response(response, 400)
+        with client.get(url.download, headers=headers) as response:
+            check_err_response(response, 400)
 
         # Range: bytes=10-<limit - 1>
         offset = 10
         limit = len(data)
         headers['Range'] = f'bytes={offset}-{limit - 1}'
-        response = client.get(url.download, headers=headers)
-        check_data_response(response, meta, data[offset:limit], offset=offset,
-                            total_size=len(data))
+        with client.get(url.download, headers=headers) as response:
+            check_data_response(response, meta, data[offset:limit],
+                                offset=offset, total_size=len(data))
 
         # Range: bytes=10-
         offset = 10
         limit = len(data)
         headers['Range'] = f'bytes={offset}-'
-        response = client.get(url.download, headers=headers)
-        check_data_response(response, meta, data[offset:limit], offset=offset,
-                            total_size=len(data))
+        with client.get(url.download, headers=headers) as response:
+            check_data_response(response, meta, data[offset:limit],
+                                offset=offset, total_size=len(data))
 
 
 def test_modify(client_fixture):
@@ -823,29 +823,29 @@ def test_modify(client_fixture):
     headers = {'Content-Type': 'application/json'}
 
     # no permission
-    response = client.post(url.modify, headers=headers, data='{}')
-    check_err_response(response, 403)
+    with client.post(url.modify, headers=headers, data='{}') as response:
+        check_err_response(response, 403)
 
     headers = add_auth('user', 'full', headers)
 
     # invalid name
-    response = client.post(RestUrl('abcdefgh').modify, headers=headers, data='{}')
-    check_err_response(response, 404)
+    with client.post(RestUrl('abcdefgh').modify, headers=headers, data='{}') as response:
+        check_err_response(response, 404)
 
     # invalid Content-Type
-    response = client.post(url.modify, headers=add_auth('user', 'full'), data='{}')
-    check_err_response(response, 400)
+    with client.post(url.modify, headers=add_auth('user', 'full'), data='{}') as response:
+        check_err_response(response, 400)
 
     # invalid json
-    response = client.post(url.modify, headers=headers, data='')
-    check_err_response(response, 400)
+    with client.post(url.modify, headers=headers, data='') as response:
+        check_err_response(response, 400)
 
     # change filename
     filename = 'test2.py'
     meta['file-meta'][FILENAME] = filename
     data = json.dumps({FILENAME: filename})
-    response = client.post(url.modify, headers=headers, data=data)
-    check_json_response(response, {})
+    with client.post(url.modify, headers=headers, data=data) as response:
+        check_json_response(response, {})
 
     check_detail_or_download(app, client, item_id, meta, None)
 
@@ -853,8 +853,8 @@ def test_modify(client_fixture):
     content_type = 'text/plain'
     meta['file-meta'][TYPE] = content_type
     data = json.dumps({TYPE: content_type})
-    response = client.post(url.modify, headers=headers, data=data)
-    check_json_response(response, {})
+    with client.post(url.modify, headers=headers, data=data) as response:
+        check_json_response(response, {})
 
     check_detail_or_download(app, client, item_id, meta, None)
 
@@ -869,23 +869,23 @@ def test_delete_basic(client_fixture):
     url = RestUrl('abcdefgh')
 
     # delete ENOENT item
-    response = client.post(url.delete, headers=add_auth('user', 'admin'))
-    check_err_response(response, 404)
+    with client.post(url.delete, headers=add_auth('user', 'admin')) as response:
+        check_err_response(response, 404)
 
     for item_id in metas.keys():
         url = RestUrl(item_id)
 
         # no permission
-        response = client.post(url.delete, headers=add_auth('user', 'invalid'))
-        check_err_response(response, 403)
+        with client.post(url.delete, headers=add_auth('user', 'invalid')) as response:
+            check_err_response(response, 403)
 
         # has permission
-        response = client.post(url.delete, headers=add_auth('user', 'full'))
-        check_json_response(response, {})
+        with client.post(url.delete, headers=add_auth('user', 'full')) as response:
+            check_json_response(response, {})
 
         # should already be deleted
-        response = client.post(url.delete, headers=add_auth('user', 'full'))
-        check_err_response(response, 404)
+        with client.post(url.delete, headers=add_auth('user', 'full')) as response:
+            check_err_response(response, 404)
 
 
 def test_lock_basic(client_fixture):
@@ -899,58 +899,58 @@ def test_lock_basic(client_fixture):
 
     for u in (url.lock, url.unlock):
         # lock/unlock ENOENT item
-        response = client.post(u, headers=add_auth('user', 'admin'))
-        check_err_response(response, 404)
+        with client.post(u, headers=add_auth('user', 'admin')) as response:
+            check_err_response(response, 404)
 
     for item_id in metas.keys():
         url = RestUrl(item_id)
 
         for u in (url.lock, url.unlock):
             # lock/unlock, no permission (invalid user)
-            response = client.post(u, headers=add_auth('user', 'invalid'))
-            check_err_response(response, 403)
+            with client.post(u, headers=add_auth('user', 'invalid')) as response:
+                check_err_response(response, 403)
 
             # lock/unlock, no permission (not admin)
-            response = client.post(u, headers=add_auth('user', 'full'))
-            check_err_response(response, 403)
+            with client.post(u, headers=add_auth('user', 'full')) as response:
+                check_err_response(response, 403)
 
             # lock/unlock, has permission
-            response = client.post(u, headers=add_auth('user', 'admin'))
-            check_json_response(response, {})
+            with client.post(u, headers=add_auth('user', 'admin')) as response:
+                check_json_response(response, {})
 
         # lock item
-        response = client.post(url.lock, headers=add_auth('user', 'admin'))
-        check_json_response(response, {})
+        with client.post(url.lock, headers=add_auth('user', 'admin')) as response:
+            check_json_response(response, {})
 
         # download locked item (should fail)
-        response = client.get(url.download, headers=add_auth('user', 'full'))
-        check_err_response(response, 403)
+        with client.get(url.download, headers=add_auth('user', 'full')) as response:
+            check_err_response(response, 403)
 
         # download locked item with admin (should succeed)
-        response = client.get(url.download, headers=add_auth('user', 'admin'))
-        check_data_response(response, metas[item_id], datas[item_id])
+        with client.get(url.download, headers=add_auth('user', 'admin')) as response:
+            check_data_response(response, metas[item_id], datas[item_id])
 
         # modify locked item (should fail)
         headers = add_auth('user', 'full', {'Content-Type': 'application/json'})
-        response = client.post(url.modify, headers=headers, data='{}')
-        check_err_response(response, 403)
+        with client.post(url.modify, headers=headers, data='{}') as response:
+            check_err_response(response, 403)
 
         # modify locked item with admin (should succeed)
         headers = add_auth('user', 'admin', {'Content-Type': 'application/json'})
-        response = client.post(url.modify, headers=headers, data='{}')
-        check_json_response(response, {})
+        with client.post(url.modify, headers=headers, data='{}') as response:
+            check_json_response(response, {})
 
         # delete locked item (should fail)
-        response = client.post(url.delete, headers=add_auth('user', 'full'))
-        check_err_response(response, 403)
+        with client.post(url.delete, headers=add_auth('user', 'full')) as response:
+            check_err_response(response, 403)
 
         # delete locked item with admin (should succeed)
-        response = client.post(url.delete, headers=add_auth('user', 'admin'))
-        check_json_response(response, {})
+        with client.post(url.delete, headers=add_auth('user', 'admin')) as response:
+            check_json_response(response, {})
 
         # deleted item
-        response = client.post(url.delete, headers=add_auth('user', 'admin'))
-        check_err_response(response, 404)
+        with client.post(url.delete, headers=add_auth('user', 'admin')) as response:
+            check_err_response(response, 404)
 
 
 def test_incomplete(client_fixture):
@@ -963,50 +963,51 @@ def test_incomplete(client_fixture):
     sep = 10
     data = UPLOAD_DATA[:sep]
     range_str = f'bytes {0}-{sep - 1}/{len(UPLOAD_DATA)}'
-    response = _upload(client, data, token='full', filename=filename,
-                       ftype=ftype, range_str=range_str)
-    check_upload_response(response, 200)
-    assert len(response.headers[TRANSACTION_ID]) > 0
+    with _upload(client, data, token='full', filename=filename,
+                 ftype=ftype, range_str=range_str) as response:
+        check_upload_response(response, 200)
+        assert len(response.headers[TRANSACTION_ID]) > 0
 
     # get incomplete item from list
     url = RestUrl()
     headers = add_auth('user', 'full')
-    response = client.get(url.list, headers=headers)
-    check_response(response, 200)
-    assert len(response.json) == 1
+    with client.get(url.list, headers=headers) as response:
+        print(f'{response}')
+        check_response(response, 200)
+        assert len(response.json) == 1
 
-    item_id = list(response.json.keys())[0]
+        item_id = list(response.json.keys())[0]
 
     url = RestUrl(item_id)
 
     # detail should error with incomplete
-    response = client.get(url.detail, headers=add_auth('user', 'full'))
-    check_err_response(response, 409)
+    with client.get(url.detail, headers=add_auth('user', 'full')) as response:
+        check_err_response(response, 409)
 
     # download should error with incomplete
-    response = client.get(url.download, headers=add_auth('user', 'full'))
-    check_err_response(response, 409)
+    with client.get(url.download, headers=add_auth('user', 'full')) as response:
+        check_err_response(response, 409)
 
     # modify should error with incomplete
     headers = add_auth('user', 'full', {'Content-Type': 'application/json'})
-    response = client.post(url.modify, headers=headers, data='{}')
-    check_err_response(response, 409)
+    with client.post(url.modify, headers=headers, data='{}') as response:
+        check_err_response(response, 409)
 
     # lock should error with incomplete
-    response = client.post(url.lock, headers=add_auth('user', 'admin'))
-    check_err_response(response, 409)
+    with client.post(url.lock, headers=add_auth('user', 'admin')) as response:
+        check_err_response(response, 409)
 
     # unlock should error with incomplete
-    response = client.post(url.unlock, headers=add_auth('user', 'admin'))
-    check_err_response(response, 409)
+    with client.post(url.unlock, headers=add_auth('user', 'admin')) as response:
+        check_err_response(response, 409)
 
     # delete should error with incomplete
-    response = client.post(url.delete, headers=add_auth('user', 'full'))
-    check_err_response(response, 409)
+    with client.post(url.delete, headers=add_auth('user', 'full')) as response:
+        check_err_response(response, 409)
 
     # delete by admin with incomplete should succeed
-    response = client.post(url.delete, headers=add_auth('user', 'admin'))
-    check_json_response(response, {})
+    with client.post(url.delete, headers=add_auth('user', 'admin')) as response:
+        check_json_response(response, {})
 
 
 def test_magic(client_fixture):
@@ -1027,21 +1028,21 @@ def test_magic(client_fixture):
             sep = 10
             data = UPLOAD_DATA[:sep]
             range_str = f'bytes {0}-{sep - 1}/{len(UPLOAD_DATA)}'
-            response = _upload(client, data, token='full', filename=filename,
-                               ftype=ftype, range_str=range_str)
-            check_upload_response(response, 200)
-            assert len(response.headers[TRANSACTION_ID]) > 0
-            trans_id = response.headers[TRANSACTION_ID]
+            with _upload(client, data, token='full', filename=filename,
+                         ftype=ftype, range_str=range_str) as response:
+                check_upload_response(response, 200)
+                assert len(response.headers[TRANSACTION_ID]) > 0
+                trans_id = response.headers[TRANSACTION_ID]
 
             # get incomplete item from list
             url = RestUrl()
             headers = add_auth('user', 'full')
-            response = client.get(url.list, headers=headers)
-            check_response(response, 200)
-            assert len(response.json) == 1
+            with client.get(url.list, headers=headers) as response:
+                check_response(response, 200)
+                assert len(response.json) == 1
 
-            fid = list(response.json.keys())[0]
-            meta = list(response.json.values())[0]
+                fid = list(response.json.keys())[0]
+                meta = list(response.json.values())[0]
 
             # 'type-hint' should be invisible
             assert meta['file-meta'] is not None
@@ -1054,14 +1055,14 @@ def test_magic(client_fixture):
             data = UPLOAD_DATA[sep:]
             range_str = 'bytes {}-{}/{}'.format(sep, len(UPLOAD_DATA) - 1,
                                                 len(UPLOAD_DATA))
-            response = _upload(client, data, token='full', range_str=range_str,
-                               trans_id=trans_id)
-            check_upload_response(response)
+            with _upload(client, data, token='full', range_str=range_str,
+                         trans_id=trans_id) as response:
+                check_upload_response(response)
 
             # get detail to check python-magic auto detection
             url = RestUrl(fid)
-            response = client.get(url.detail, headers=add_auth('user', 'full'))
-            check_json_response(response, None, check_data=False)
+            with client.get(url.detail, headers=add_auth('user', 'full')) as response:
+                check_json_response(response, None, check_data=False)
 
-            assert response.json['file-meta'] is not None
-            assert response.json['file-meta'][TYPE] == 'text/x-python'
+                assert response.json['file-meta'] is not None
+                assert response.json['file-meta'][TYPE] in ('text/x-python', 'text/x-script.python')