From 71b7f8d0246064f28fadef0cef88f1907b0ed874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 9 Oct 2024 09:03:23 +0200 Subject: [PATCH] Replace cgi.parse_header() with custom function for Python 3.13 compat The cgi module has been deprecated since Python 3.11 and got removed in Python 3.13. Replace the cgi.parse_header() function with a custom one, as recommended by the Python documentation. Closes #712 --- spyne/protocol/soap/mime.py | 2 +- spyne/protocol/soap/soap11.py | 5 ++--- spyne/server/wsgi.py | 6 +++--- spyne/util/http.py | 6 ++++++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/spyne/protocol/soap/mime.py b/spyne/protocol/soap/mime.py index d4aaa1de4..90b536020 100644 --- a/spyne/protocol/soap/mime.py +++ b/spyne/protocol/soap/mime.py @@ -115,7 +115,7 @@ def collapse_swa(ctx, content_type, ns_soap_env): http://www.w3.org/Submission/soap11mtom10/ :param content_type: value of the Content-Type header field, parsed by - cgi.parse_header() function + spyne.util.http.parse_content_type_header() function :param ctx: request context """ diff --git a/spyne/protocol/soap/soap11.py b/spyne/protocol/soap/soap11.py index 75e1add71..21a02b890 100644 --- a/spyne/protocol/soap/soap11.py +++ b/spyne/protocol/soap/soap11.py @@ -38,8 +38,6 @@ logger = logging.getLogger(__name__) logger_invalid = logging.getLogger(__name__ + ".invalid") -import cgi - from itertools import chain import spyne.const.xml as ns @@ -50,6 +48,7 @@ from spyne import BODY_STYLE_WRAPPED from spyne.util import six +from spyne.util.http import parse_content_type_header from spyne.const.xml import DEFAULT_NS from spyne.const.http import HTTP_405, HTTP_500 from spyne.error import RequestNotAllowed @@ -197,7 +196,7 @@ def create_in_document(self, ctx, charset=None): "You must issue a POST request with the Content-Type " "header properly set.") - content_type = cgi.parse_header(content_type) + content_type = parse_content_type_header(content_type) ctx.in_string = collapse_swa(ctx, content_type, self.ns_soap_env) ctx.in_document = _parse_xml_string(ctx.in_string, diff --git a/spyne/server/wsgi.py b/spyne/server/wsgi.py index 4c5e6ef60..6275ae404 100644 --- a/spyne/server/wsgi.py +++ b/spyne/server/wsgi.py @@ -27,7 +27,6 @@ import logging logger = logging.getLogger(__name__) -import cgi import threading from inspect import isgenerator @@ -44,6 +43,7 @@ from spyne.server.http import HttpBase, HttpMethodContext, HttpTransportContext from spyne.util.odict import odict from spyne.util.address import address_parser +from spyne.util.http import parse_content_type_header from spyne.const.ansi_color import LIGHT_GREEN from spyne.const.ansi_color import END_COLOR @@ -527,9 +527,9 @@ def __reconstruct_wsgi_request(self, http_env): charset = None if content_type is not None: # fyi, here's what the parse_header function returns: - # >>> import cgi; cgi.parse_header("text/xml; charset=utf-8") + # >>> parse_content_type_header("text/xml; charset=utf-8") # ('text/xml', {'charset': 'utf-8'}) - content_type = cgi.parse_header(content_type) + content_type = parse_content_type_header(content_type) charset = content_type[1].get('charset', None) return self.__wsgi_input_to_iterable(http_env), charset diff --git a/spyne/util/http.py b/spyne/util/http.py index f066e028d..0330f5fdb 100644 --- a/spyne/util/http.py +++ b/spyne/util/http.py @@ -23,6 +23,7 @@ import sys import time +from email.message import EmailMessage from time import strftime from time import gmtime from collections import deque @@ -72,3 +73,8 @@ def generate_cookie(k, v, max_age=None, domain=None, path=None, retval.append("Secure") return '; '.join(retval) + +def parse_content_type_header(h): + msg = EmailMessage() + msg['content-type'] = h + return msg.get_content_type(), msg['content-type'].params