Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-httpbin for openSUSE:Factory 
checked in at 2026-07-22 19:00:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-httpbin (Old)
 and      /work/SRC/openSUSE:Factory/.python-httpbin.new.24530 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-httpbin"

Wed Jul 22 19:00:44 2026 rev:12 rq:1364122 version:0.10.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-httpbin/python-httpbin.changes    
2025-01-29 16:09:54.042276411 +0100
+++ /work/SRC/openSUSE:Factory/.python-httpbin.new.24530/python-httpbin.changes 
2026-07-22 19:00:47.472180877 +0200
@@ -1,0 +2,15 @@
+Sat Jul  4 09:24:49 UTC 2026 - Dirk Müller <[email protected]>
+
+- Update to 0.10.4:
+  * Made flasgger an optional dependency (falls back to a static
+    landing page when absent)
+  * Fixed invalid escape sequence SyntaxWarnings on Python 3.12+
+  * Included tox.ini and the tests in the source distribution
+  * Added Python 3.13 and 3.14 to the test matrix and classifiers
+  * Fixed the /bytes endpoint to return bytes (not bytearray)
+    for WSGI compliance with newer Werkzeug (from 0.10.3)
+  * Dropped support for Python 3.7
+- Increase Werkzeug minimum version to 2.2.2.
+- Refresh remove-six.patch
+
+-------------------------------------------------------------------

Old:
----
  httpbin-0.10.2.tar.gz

New:
----
  httpbin-0.10.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-httpbin.spec ++++++
--- /var/tmp/diff_new_pack.OhiqbJ/_old  2026-07-22 19:00:48.756224788 +0200
+++ /var/tmp/diff_new_pack.OhiqbJ/_new  2026-07-22 19:00:48.756224788 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-httpbin
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %define modname httpbin
 %{?sle15_python_module_pythons}
 Name:           python-httpbin
-Version:        0.10.2
+Version:        0.10.4
 Release:        0
 Summary:        HTTP Request and Response Service
 License:        MIT
@@ -29,10 +29,11 @@
 Patch0:         remove-six.patch
 BuildRequires:  %{python_module Brotli}
 BuildRequires:  %{python_module Flask >= 2.2.4}
-BuildRequires:  %{python_module Werkzeug >= 2.0}
+BuildRequires:  %{python_module Werkzeug >= 2.2.2}
 BuildRequires:  %{python_module decorator}
 BuildRequires:  %{python_module flasgger}
 BuildRequires:  %{python_module gevent}
+BuildRequires:  %{python_module greenlet}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
@@ -45,6 +46,7 @@
 Requires:       python-decorator
 Requires:       python-flasgger
 Requires:       python-gevent
+Requires:       python-greenlet
 BuildArch:      noarch
 %python_subpackages
 
@@ -60,8 +62,6 @@
 
 %prep
 %autosetup -p1 -n %{modname}-%{version}
-# we are running CPython, let us use Brotli instead of brotlicffi (they should 
be compatible)
-sed -i 's/brotlicffi/brotli/' httpbin/filters.py
 
 %build
 export LANG=en_US.UTF-8

++++++ httpbin-0.10.2.tar.gz -> httpbin-0.10.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/MANIFEST.in 
new/httpbin-0.10.4/MANIFEST.in
--- old/httpbin-0.10.2/MANIFEST.in      2024-02-20 22:29:51.000000000 +0100
+++ new/httpbin-0.10.4/MANIFEST.in      2026-06-16 23:41:08.000000000 +0200
@@ -1,3 +1,4 @@
-include README.md LICENSE.ISC LICENSE.MIT AUTHORS test_httpbin.py
+include README.md LICENSE.ISC LICENSE.MIT AUTHORS tox.ini
+recursive-include tests *.py
 recursive-include httpbin/templates *
 recursive-include httpbin/static *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/PKG-INFO new/httpbin-0.10.4/PKG-INFO
--- old/httpbin-0.10.2/PKG-INFO 2024-02-20 22:30:02.681246300 +0100
+++ new/httpbin-0.10.4/PKG-INFO 2026-06-16 23:41:13.247149700 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: httpbin
-Version: 0.10.2
+Version: 0.10.4
 Summary: HTTP Request and Response Service
 Author-email: Kenneth Reitz <[email protected]>
 License: MIT or ISC
@@ -12,13 +12,14 @@
 Classifier: License :: OSI Approved :: ISC License (ISCL)
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
-Requires-Python: >=3.7
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
+Requires-Python: >=3.8
 Description-Content-Type: text/markdown
 License-File: LICENSE
 License-File: LICENSE.ISC
@@ -26,7 +27,6 @@
 License-File: AUTHORS
 Requires-Dist: brotlicffi
 Requires-Dist: decorator
-Requires-Dist: flasgger
 Requires-Dist: flask>=2.2.4
 Requires-Dist: greenlet<3.0; python_version < "3.12"
 Requires-Dist: greenlet>=3.0.0a1; python_version >= "3.12.0rc0"
@@ -37,8 +37,10 @@
 Requires-Dist: pytest; extra == "test"
 Requires-Dist: tox; extra == "test"
 Provides-Extra: mainapp
+Requires-Dist: flasgger; extra == "mainapp"
 Requires-Dist: gunicorn; extra == "mainapp"
 Requires-Dist: gevent; extra == "mainapp"
+Dynamic: license-file
 
 # httpbin(1): HTTP Request & Response Service
 
@@ -117,6 +119,15 @@
 
 
 ## Changelog
+* 0.10.4:
+  - Made flasgger an optional dependency (falls back to a static landing page 
when absent), thanks @AdamWill and @mgorny
+  - Fixed invalid escape sequence SyntaxWarnings on Python 3.12+, thanks @hseg
+  - Included tox.ini and the tests in the source distribution, thanks 
@Mirochill
+  - Added Python 3.13 and 3.14 to the test matrix and classifiers
+* 0.10.3:
+  - Fixed the /bytes endpoint to return bytes (not bytearray) for WSGI 
compliance with newer Werkzeug, thanks @swt2c
+  - Dropped support for Python 3.7
+  - Build and publish arm64 Docker images
 * 0.10.2:
   - Added support for Flask 3.0
 * 0.10.1:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/README.md new/httpbin-0.10.4/README.md
--- old/httpbin-0.10.2/README.md        2024-02-20 22:29:51.000000000 +0100
+++ new/httpbin-0.10.4/README.md        2026-06-16 23:41:08.000000000 +0200
@@ -75,6 +75,15 @@
 
 
 ## Changelog
+* 0.10.4:
+  - Made flasgger an optional dependency (falls back to a static landing page 
when absent), thanks @AdamWill and @mgorny
+  - Fixed invalid escape sequence SyntaxWarnings on Python 3.12+, thanks @hseg
+  - Included tox.ini and the tests in the source distribution, thanks 
@Mirochill
+  - Added Python 3.13 and 3.14 to the test matrix and classifiers
+* 0.10.3:
+  - Fixed the /bytes endpoint to return bytes (not bytearray) for WSGI 
compliance with newer Werkzeug, thanks @swt2c
+  - Dropped support for Python 3.7
+  - Build and publish arm64 Docker images
 * 0.10.2:
   - Added support for Flask 3.0
 * 0.10.1:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/httpbin/core.py 
new/httpbin-0.10.4/httpbin/core.py
--- old/httpbin-0.10.2/httpbin/core.py  2024-02-20 22:29:51.000000000 +0100
+++ new/httpbin-0.10.4/httpbin/core.py  2026-06-16 23:41:08.000000000 +0200
@@ -33,7 +33,10 @@
 except ImportError:  # werkzeug < 2.1
     from werkzeug.wrappers import BaseResponse as Response
 
-from flasgger import Swagger, NO_SANITIZER
+try:
+    from flasgger import Swagger, NO_SANITIZER
+except ImportError:
+    Swagger = False
 
 from . import filters
 from .helpers import (
@@ -89,83 +92,89 @@
 
 app = Flask(__name__, template_folder=tmpl_dir)
 app.debug = bool(os.environ.get("DEBUG"))
-app.config["JSONIFY_PRETTYPRINT_REGULAR"] = True
+app.json.compact = False
 
 app.add_template_global("HTTPBIN_TRACKING" in os.environ, 
name="tracking_enabled")
 
 app.config["SWAGGER"] = {"title": "httpbin.org", "uiversion": 3}
 
-template = {
-    "swagger": "2.0",
-    "info": {
-        "title": "httpbin.org",
-        "description": (
-            "A simple HTTP Request & Response Service."
-            "<br/> A <a href='http://kennethreitz.com/'>Kenneth Reitz</a> 
project."
-            "<br/> <br/> <b>Run locally: </b> <br/> "
-            "<code>$ docker pull ghcr.io/psf/httpbin</code> <br/>"
-            "<code>$ docker run -p 80:8080 ghcr.io/psf/httpbin</code>"
-        ),
-        "contact": {
-            "responsibleOrganization": "Python Software Foundation",
-            "responsibleDeveloper": "Kenneth Reitz",
-            "url": "https://github.com/psf/httpbin/";,
-        },
-        # "termsOfService": "http://me.com/terms";,
-        "version": version,
-    },
-    "host": "httpbin.org",  # overrides localhost:5000
-    "basePath": "/",  # base bash for blueprint registration
-    "schemes": ["https"],
-    "protocol": "https",
-    "tags": [
-        {
-            "name": "HTTP Methods",
-            "description": "Testing different HTTP verbs",
-            # 'externalDocs': {'description': 'Learn more', 'url': 
'https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html'}
-        },
-        {"name": "Auth", "description": "Auth methods"},
-        {
-            "name": "Status codes",
-            "description": "Generates responses with given status code",
-        },
-        {"name": "Request inspection", "description": "Inspect the request 
data"},
-        {
-            "name": "Response inspection",
-            "description": "Inspect the response data like caching and 
headers",
+if Swagger:
+    template = {
+        "swagger": "2.0",
+        "info": {
+            "title": "httpbin.org",
+            "description": (
+                "A simple HTTP Request & Response Service."
+                "<br/> A <a href='http://kennethreitz.com/'>Kenneth Reitz</a> 
project."
+                "<br/> <br/> <b>Run locally: </b> <br/> "
+                "<code>$ docker pull ghcr.io/psf/httpbin</code> <br/>"
+                "<code>$ docker run -p 80:8080 ghcr.io/psf/httpbin</code>"
+            ),
+            "contact": {
+                "responsibleOrganization": "Python Software Foundation",
+                "responsibleDeveloper": "Kenneth Reitz",
+                "url": "https://github.com/psf/httpbin/";,
+            },
+            # "termsOfService": "http://me.com/terms";,
+            "version": version,
         },
-        {
-            "name": "Response formats",
-            "description": "Returns responses in different data formats",
-        },
-        {"name": "Dynamic data", "description": "Generates random and dynamic 
data"},
-        {"name": "Cookies", "description": "Creates, reads and deletes 
Cookies"},
-        {"name": "Images", "description": "Returns different image formats"},
-        {"name": "Redirects", "description": "Returns different redirect 
responses"},
-        {
-            "name": "Anything",
-            "description": "Returns anything that is passed to request",
-        },
-    ],
-}
-
-swagger_config = {
-    "headers": [],
-    "specs": [
-        {
-            "endpoint": "spec",
-            "route": "/spec.json",
-            "rule_filter": lambda rule: True,  # all in
-            "model_filter": lambda tag: True,  # all in
-        }
-    ],
-    "static_url_path": "/flasgger_static",
-    # "static_folder": "static",  # must be set by user
-    "swagger_ui": True,
-    "specs_route": "/",
-}
-
-swagger = Swagger(app, sanitizer=NO_SANITIZER, template=template, 
config=swagger_config)
+        "host": "httpbin.org",  # overrides localhost:5000
+        "basePath": "/",  # base bash for blueprint registration
+        "schemes": ["https"],
+        "protocol": "https",
+        "tags": [
+            {
+                "name": "HTTP Methods",
+                "description": "Testing different HTTP verbs",
+                # 'externalDocs': {'description': 'Learn more', 'url': 
'https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html'}
+            },
+            {"name": "Auth", "description": "Auth methods"},
+            {
+                "name": "Status codes",
+                "description": "Generates responses with given status code",
+            },
+            {"name": "Request inspection", "description": "Inspect the request 
data"},
+            {
+                "name": "Response inspection",
+                "description": "Inspect the response data like caching and 
headers",
+            },
+            {
+                "name": "Response formats",
+                "description": "Returns responses in different data formats",
+            },
+            {"name": "Dynamic data", "description": "Generates random and 
dynamic data"},
+            {"name": "Cookies", "description": "Creates, reads and deletes 
Cookies"},
+            {"name": "Images", "description": "Returns different image 
formats"},
+            {"name": "Redirects", "description": "Returns different redirect 
responses"},
+            {
+                "name": "Anything",
+                "description": "Returns anything that is passed to request",
+            },
+        ],
+    }
+
+    swagger_config = {
+        "headers": [],
+        "specs": [
+            {
+                "endpoint": "spec",
+                "route": "/spec.json",
+                "rule_filter": lambda rule: True,  # all in
+                "model_filter": lambda tag: True,  # all in
+            }
+        ],
+        "static_url_path": "/flasgger_static",
+        # "static_folder": "static",  # must be set by user
+        "swagger_ui": True,
+        "specs_route": "/",
+    }
+
+    swagger = Swagger(app, sanitizer=NO_SANITIZER, template=template, 
config=swagger_config)
+else:
+    app.logger.warning(
+        "flasgger is not installed; serving the static landing page at / "
+        "and skipping the Swagger UI and /spec.json."
+    )
 
 # Set up Bugsnag exception tracking, if desired. To use Bugsnag, install the
 # Bugsnag Python client with the command "pip install bugsnag", and set the
@@ -243,8 +252,12 @@
 # Routes
 # ------
 
+if Swagger:
+    staticroute = "/legacy"
+else:
+    staticroute = "/"
 
[email protected]("/legacy")
[email protected](staticroute)
 def view_landing_page():
     """Generates Landing Page in legacy layout."""
     return render_template("index.html")
@@ -1449,7 +1462,7 @@
     response = make_response()
 
     # Note: can't just use os.urandom here because it ignores the seed
-    response.data = bytearray(random.randint(0, 255) for i in range(n))
+    response.data = bytes(random.randint(0, 255) for i in range(n))
     response.content_type = "application/octet-stream"
     return response
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/httpbin/helpers.py 
new/httpbin-0.10.4/httpbin/helpers.py
--- old/httpbin-0.10.2/httpbin/helpers.py       2024-02-20 22:29:51.000000000 
+0100
+++ new/httpbin-0.10.4/httpbin/helpers.py       2026-06-16 23:41:08.000000000 
+0200
@@ -29,7 +29,7 @@
 from .structures import CaseInsensitiveDict
 
 
-ASCII_ART = """
+ASCII_ART = r'''
     -=[ teapot ]=-
 
        _...._
@@ -38,8 +38,8 @@
     \_;`"---"`|//
       |       ;/
       \_     _/
-        `\"\"\"`
-"""
+        `"""`
+'''
 
 REDIRECT_LOCATION = '/redirect/1'
 
@@ -74,10 +74,10 @@
     'image/*'
 ]
 
-ANGRY_ASCII ="""
+ANGRY_ASCII = r"""
           .-''''''-.
         .' _      _ '.
-       /   O      O   \\
+       /   O      O   \
       :                :
       |                |
       :       __       :
@@ -441,7 +441,7 @@
     if header_str:
         parts = header_str.split(',')
         for part in parts:
-            match = re.search('\s*(W/)?\"?([^"]*)\"?\s*', part)
+            match = re.search(r'\s*(W/)?\"?([^"]*)\"?\s*', part)
             if match is not None:
                 parsed_parts.append(match.group(2))
     return parsed_parts
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/httpbin.egg-info/PKG-INFO 
new/httpbin-0.10.4/httpbin.egg-info/PKG-INFO
--- old/httpbin-0.10.2/httpbin.egg-info/PKG-INFO        2024-02-20 
22:30:02.000000000 +0100
+++ new/httpbin-0.10.4/httpbin.egg-info/PKG-INFO        2026-06-16 
23:41:13.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: httpbin
-Version: 0.10.2
+Version: 0.10.4
 Summary: HTTP Request and Response Service
 Author-email: Kenneth Reitz <[email protected]>
 License: MIT or ISC
@@ -12,13 +12,14 @@
 Classifier: License :: OSI Approved :: ISC License (ISCL)
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
-Requires-Python: >=3.7
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
+Requires-Python: >=3.8
 Description-Content-Type: text/markdown
 License-File: LICENSE
 License-File: LICENSE.ISC
@@ -26,7 +27,6 @@
 License-File: AUTHORS
 Requires-Dist: brotlicffi
 Requires-Dist: decorator
-Requires-Dist: flasgger
 Requires-Dist: flask>=2.2.4
 Requires-Dist: greenlet<3.0; python_version < "3.12"
 Requires-Dist: greenlet>=3.0.0a1; python_version >= "3.12.0rc0"
@@ -37,8 +37,10 @@
 Requires-Dist: pytest; extra == "test"
 Requires-Dist: tox; extra == "test"
 Provides-Extra: mainapp
+Requires-Dist: flasgger; extra == "mainapp"
 Requires-Dist: gunicorn; extra == "mainapp"
 Requires-Dist: gevent; extra == "mainapp"
+Dynamic: license-file
 
 # httpbin(1): HTTP Request & Response Service
 
@@ -117,6 +119,15 @@
 
 
 ## Changelog
+* 0.10.4:
+  - Made flasgger an optional dependency (falls back to a static landing page 
when absent), thanks @AdamWill and @mgorny
+  - Fixed invalid escape sequence SyntaxWarnings on Python 3.12+, thanks @hseg
+  - Included tox.ini and the tests in the source distribution, thanks 
@Mirochill
+  - Added Python 3.13 and 3.14 to the test matrix and classifiers
+* 0.10.3:
+  - Fixed the /bytes endpoint to return bytes (not bytearray) for WSGI 
compliance with newer Werkzeug, thanks @swt2c
+  - Dropped support for Python 3.7
+  - Build and publish arm64 Docker images
 * 0.10.2:
   - Added support for Flask 3.0
 * 0.10.1:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/httpbin.egg-info/SOURCES.txt 
new/httpbin-0.10.4/httpbin.egg-info/SOURCES.txt
--- old/httpbin-0.10.2/httpbin.egg-info/SOURCES.txt     2024-02-20 
22:30:02.000000000 +0100
+++ new/httpbin-0.10.4/httpbin.egg-info/SOURCES.txt     2026-06-16 
23:41:13.000000000 +0200
@@ -6,6 +6,7 @@
 README.md
 pyproject.toml
 setup.cfg
+tox.ini
 httpbin/__init__.py
 httpbin/core.py
 httpbin/filters.py
@@ -31,4 +32,5 @@
 httpbin/templates/images/pig_icon.png
 httpbin/templates/images/svg_logo.svg
 httpbin/templates/images/wolf_1.webp
+tests/__init__.py
 tests/test_httpbin.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/httpbin.egg-info/requires.txt 
new/httpbin-0.10.4/httpbin.egg-info/requires.txt
--- old/httpbin-0.10.2/httpbin.egg-info/requires.txt    2024-02-20 
22:30:02.000000000 +0100
+++ new/httpbin-0.10.4/httpbin.egg-info/requires.txt    2026-06-16 
23:41:13.000000000 +0200
@@ -1,6 +1,5 @@
 brotlicffi
 decorator
-flasgger
 flask>=2.2.4
 six
 werkzeug>=2.2.2
@@ -15,6 +14,7 @@
 greenlet>=3.0.0a1
 
 [mainapp]
+flasgger
 gunicorn
 gevent
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/pyproject.toml 
new/httpbin-0.10.4/pyproject.toml
--- old/httpbin-0.10.2/pyproject.toml   2024-02-20 22:29:51.000000000 +0100
+++ new/httpbin-0.10.4/pyproject.toml   2026-06-16 23:41:08.000000000 +0200
@@ -8,8 +8,8 @@
 
 [project]
 name = "httpbin"
-version = "0.10.2"
-requires-python = ">=3.7"
+version = "0.10.4"
+requires-python = ">=3.8"
 description = "HTTP Request and Response Service"
 readme = "README.md"
 license = {text = "MIT or ISC"}
@@ -23,17 +23,17 @@
     "License :: OSI Approved :: ISC License (ISCL)",
     "License :: OSI Approved :: MIT License",
     "Programming Language :: Python",
-    "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",
     "Programming Language :: Python :: 3.12",
+    "Programming Language :: Python :: 3.13",
+    "Programming Language :: Python :: 3.14",
 ]
 dependencies = [
     "brotlicffi",
     "decorator",
-    "flasgger",
     "flask >= 2.2.4",
     'greenlet < 3.0; python_version<"3.12"',
     'greenlet >= 3.0.0a1; python_version>="3.12.0rc0"',
@@ -45,6 +45,7 @@
 [project.optional-dependencies]
 test = ["pytest", "tox"]
 mainapp = [
+    "flasgger",
     "gunicorn",
     "gevent",
 ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/tests/test_httpbin.py 
new/httpbin-0.10.4/tests/test_httpbin.py
--- old/httpbin-0.10.2/tests/test_httpbin.py    2024-02-20 22:29:51.000000000 
+0100
+++ new/httpbin-0.10.4/tests/test_httpbin.py    2026-06-16 23:41:08.000000000 
+0200
@@ -1,7 +1,9 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 import os
+import sys
 import base64
+import subprocess
 import unittest
 import contextlib
 import json
@@ -519,6 +521,19 @@
             response.data, b'\xc5\xd7\x14\x84\xf8\xcf\x9b\xf4\xb7o'
         )
 
+    def test_bytes_endpoint_yields_bytes(self):
+        """WSGI bodies must be bytes (not bytearray) so strict servers
+        (wsgiref / pytest-httpbin) don't 500. The test client coerces the
+        body, so we inspect the raw WSGI iterable. Regression for /bytes."""
+        from werkzeug.test import create_environ
+        env = create_environ('/bytes/64', 'http://localhost/')
+        chunks = list(httpbin.app(env, lambda *a, **k: None))
+        self.assertTrue(chunks, "no body produced")
+        self.assertTrue(
+            all(type(c) is bytes for c in chunks),
+            [type(c).__name__ for c in chunks]
+        )
+
     def test_delete_endpoint_returns_body(self):
         response = self.app.delete(
             '/delete',
@@ -783,6 +798,52 @@
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.headers.get('ETag'), 'abc')
 
+    def test_index_falls_back_to_static_page_without_flasgger(self):
+        """When flasgger isn't installed, / serves the static legacy landing
+        page (HTTP 200) instead of the Swagger UI, rather than 500ing.
+
+        flasgger is imported at module load, so this runs in a subprocess that
+        poisons sys.modules['flasgger'] before httpbin is imported.
+        """
+        code = (
+            "import sys\n"
+            "sys.modules['flasgger'] = None\n"  # makes `import flasgger` 
raise ImportError
+            "import httpbin\n"
+            "assert httpbin.core.Swagger is False, 
repr(httpbin.core.Swagger)\n"
+            "r = httpbin.app.test_client().get('/')\n"
+            "assert r.status_code == 200, r.status_code\n"
+            "body = r.get_data(as_text=True)\n"
+            "assert 'httpbin(1): HTTP Client Testing Service' in body, 'legacy 
page not served'\n"
+            "assert 'swagger-ui' not in body, 'swagger UI unexpectedly 
rendered'\n"
+            "print('OK')\n"
+        )
+        result = subprocess.run(
+            [sys.executable, "-c", code], capture_output=True, text=True
+        )
+        self.assertEqual(result.returncode, 0, result.stderr)
+        self.assertIn("OK", result.stdout)
+
+    def test_sources_have_no_invalid_escape_sequences(self):
+        """Every module in the httpbin package compiles without escape-sequence
+        warnings. Invalid escapes are a SyntaxWarning on 3.12+ 
(DeprecationWarning
+        earlier) and will become a SyntaxError in a future Python."""
+        import glob
+        import warnings
+
+        pkg_dir = os.path.dirname(httpbin.__file__)
+        py_files = glob.glob(os.path.join(pkg_dir, "**", "*.py"), 
recursive=True)
+        self.assertTrue(py_files, "no source files found")
+        with warnings.catch_warnings():
+            warnings.simplefilter("error", SyntaxWarning)
+            warnings.simplefilter("error", DeprecationWarning)
+            for path in py_files:
+                with open(path, encoding="utf-8") as f:
+                    src = f.read()
+                try:
+                    compile(src, path, "exec")
+                except (SyntaxWarning, DeprecationWarning) as exc:
+                    self.fail("{}: {}".format(path, exc))
+
     def test_parse_multi_value_header(self):
         self.assertEqual(parse_multi_value_header('xyzzy'), [ "xyzzy" ])
         self.assertEqual(parse_multi_value_header('"xyzzy"'), [ "xyzzy" ])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/httpbin-0.10.2/tox.ini new/httpbin-0.10.4/tox.ini
--- old/httpbin-0.10.2/tox.ini  1970-01-01 01:00:00.000000000 +0100
+++ new/httpbin-0.10.4/tox.ini  2026-06-16 23:41:08.000000000 +0200
@@ -0,0 +1,7 @@
+[tox]
+envlist = py38,py39,py310,py311,py312,py313,py314
+
+[testenv]
+extras = test
+commands =
+    pytest tests

++++++ remove-six.patch ++++++
--- /var/tmp/diff_new_pack.OhiqbJ/_old  2026-07-22 19:00:48.952231491 +0200
+++ /var/tmp/diff_new_pack.OhiqbJ/_new  2026-07-22 19:00:48.960231764 +0200
@@ -9,24 +9,27 @@
  pyproject.toml     | 1 -
  3 files changed, 3 insertions(+), 3 deletions(-)
 
-diff --git a/httpbin/filters.py b/httpbin/filters.py
-index 4deeaaad..a656279e 100644
---- a/httpbin/filters.py
-+++ b/httpbin/filters.py
-@@ -12,7 +12,7 @@
+Index: httpbin-0.10.4/httpbin/filters.py
+===================================================================
+--- httpbin-0.10.4.orig/httpbin/filters.py
++++ httpbin-0.10.4/httpbin/filters.py
+@@ -10,9 +10,9 @@ This module provides response filter dec
+ import gzip as gzip2
+ import zlib
  
- import brotlicffi as _brotli
+-import brotlicffi as _brotli
++import brotli as _brotli
  
 -from six import BytesIO
 +from io import BytesIO
  from decimal import Decimal
  from time import time as now
  
-diff --git a/httpbin/helpers.py b/httpbin/helpers.py
-index 836c8026..cdf045c0 100644
---- a/httpbin/helpers.py
-+++ b/httpbin/helpers.py
-@@ -13,6 +13,8 @@
+Index: httpbin-0.10.4/httpbin/helpers.py
+===================================================================
+--- httpbin-0.10.4.orig/httpbin/helpers.py
++++ httpbin-0.10.4/httpbin/helpers.py
+@@ -13,6 +13,8 @@ import re
  import time
  import os
  from hashlib import md5, sha256, sha512
@@ -35,7 +38,7 @@
  from werkzeug.datastructures import WWWAuthenticate
  from werkzeug.http import dump_header
  
-@@ -23,7 +25,6 @@
+@@ -23,7 +25,6 @@ except ImportError: # werkzeug < 2.3
      parse_authorization_header = Authorization.from_header
  
  from flask import request, make_response
@@ -43,10 +46,10 @@
  
  
  from .structures import CaseInsensitiveDict
-diff --git a/pyproject.toml b/pyproject.toml
-index c5bdb811..b82f7b6f 100644
---- a/pyproject.toml
-+++ b/pyproject.toml
+Index: httpbin-0.10.4/pyproject.toml
+===================================================================
+--- httpbin-0.10.4.orig/pyproject.toml
++++ httpbin-0.10.4/pyproject.toml
 @@ -38,7 +38,6 @@ dependencies = [
      'greenlet < 3.0; python_version<"3.12"',
      'greenlet >= 3.0.0a1; python_version>="3.12.0rc0"',

Reply via email to