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

Issue:
utils/upload: guess file content type also using pygments
It is possible for `mimetypes.guess_type()` to not recognize a file which is otherwise supported by pygments. It happens for example on Nix files (`*.nix`), which have `text/x-nix` mimetype. This patch makes bepasty to try to recognize a file using `pygments.lexers.get_lexer_for_filename()` if `mimetypes.guess_type()` does not know it.


Discussion / hints:
Can you check if the failing test is related to your change or does it also happen without your change?
```
response = <WrapperTestResponse streamed [415 UNSUPPORTED MEDIA TYPE]>
code = 400, ftype = 'application/json', check_data = True
```
I've tried to run it locally and I have the same failure on master on py310. It seems to be an error in the test. I'd say that the unsupported media type comes from here: https://github.com/pallets/werkzeug/blob/76b049dd45fd072fb62a54bccc0e8d513b03f4d8/src/werkzeug/wrappers/request.py#L654. See also the doc at https://github.com/pallets/werkzeug/blob/76b049dd45fd072fb62a54bccc0e8d513b03f4d8/src/werkzeug/wrappers/request.py#L556. It is called from https://github.com/bepasty/bepasty-server/blob/master/src/bepasty/apis/rest.py#L259. Apparently the 415 code is a new behaviour since v2.3... I've added a commit to fix it.

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 611d425..3e84429 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -46,9 +46,6 @@ jobs:
     strategy:
       matrix:
         include:
-            - os: ubuntu-20.04
-              python-version: '3.7'
-              toxenv: py37
             - os: ubuntu-20.04
               python-version: '3.8'
               toxenv: py38
diff --git a/setup.cfg b/setup.cfg
index eff2e97..347960c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -17,14 +17,13 @@ classifiers =
     Operating System :: OS Independent
     Programming Language :: Python
     Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
     Programming Language :: Python :: 3.10
     Programming Language :: Python :: 3.11
 
 [options]
-python_requires = >=3.7
+python_requires = >=3.8
 package_dir =
     =src
 packages = find:
@@ -34,6 +33,7 @@ setup_requires =
     setuptools_scm
 install_requires =
         Flask
+        markupsafe
         Pygments>=2.12.0
         xstatic
         XStatic-asciinema-player
diff --git a/src/bepasty/app.py b/src/bepasty/app.py
index b38f9b4..dbc09a9 100644
--- a/src/bepasty/app.py
+++ b/src/bepasty/app.py
@@ -4,12 +4,12 @@
 
 from flask import (
     Flask,
-    Markup,
     current_app,
     g as flaskg,  # searching for 1 letter name "g" isn't nice, thus we use flaskg
     render_template,
     session,
 )
+from markupsafe import Markup
 
 from .apis import blueprint as blueprint_apis
 from .storage import create_storage
diff --git a/src/bepasty/views/display.py b/src/bepasty/views/display.py
index 70860cd..7f5b78f 100644
--- a/src/bepasty/views/display.py
+++ b/src/bepasty/views/display.py
@@ -1,8 +1,9 @@
 import errno
 import time
 
-from flask import current_app, render_template, Markup, url_for, request
+from flask import current_app, render_template, url_for, request
 from flask.views import MethodView
+from markupsafe import Markup
 from werkzeug.exceptions import NotFound, Forbidden
 from pygments import highlight
 from pygments.lexers import get_lexer_for_mimetype
diff --git a/tox.ini b/tox.ini
index d83716f..e547b1a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist=py{37,38,39,310,311},flake8
+envlist=py{38,39,310,311},flake8
 
 [testenv]
 deps = -r{toxinidir}/requirements.d/dev.txt


Test patch:
diff --git a/src/bepasty/tests/test_rest_server.py b/src/bepasty/tests/test_rest_server.py
index d2943cf..dd6d20b 100644
--- a/src/bepasty/tests/test_rest_server.py
+++ b/src/bepasty/tests/test_rest_server.py
@@ -612,7 +612,7 @@ def test_upload_transaction_id(client_fixture):
         check_err_response(response, 400)
 
     # upload with Transaction-ID for invalid filename
-    trans_id = base64.b64encode(b'invalid')
+    trans_id = base64.b64encode(b'invalid').decode()
     with _upload(client, data, token='full', range_str=range_str,
                  trans_id=trans_id) as response:
         check_err_response(response, 400)
@@ -834,7 +834,7 @@ def test_modify(client_fixture):
 
     # invalid Content-Type
     with client.post(url.modify, headers=add_auth('user', 'full'), data='{}') as response:
-        check_err_response(response, 400)
+        check_err_response(response, 415)
 
     # invalid json
     with client.post(url.modify, headers=headers, data='') as response: