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"',
