diff --git a/CHANGES.rst b/CHANGES.rst index cad61837b..a5a433e21 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,9 @@ +v(next) +------- + +* Removed the use of :mod:`cgi` deprecated in Python 3.11 + -- by :user:`radez`. + v18.9.0 ------- diff --git a/cherrypy/_cpcompat.py b/cherrypy/_cpcompat.py index a43f6d369..8f4a221a4 100644 --- a/cherrypy/_cpcompat.py +++ b/cherrypy/_cpcompat.py @@ -21,6 +21,43 @@ import http.client +def _cgi_parseparam(s): + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + yield f.strip() + s = s[end:] + + +def cgi_parse_header(line): + """Parse a Content-type like header. + + Return the main content-type and a dictionary of options. + + Copied from removed stdlib cgi module. Couldn't find + something to replace it with that provided same functionality + from the email module as suggested. + """ + parts = _cgi_parseparam(';' + line) + key = parts.__next__() + pdict = {} + for p in parts: + i = p.find('=') + if i >= 0: + name = p[:i].strip().lower() + value = p[i + 1:].strip() + if len(value) >= 2 and value[0] == value[-1] == '"': + value = value[1:-1] + value = value.replace('\\\\', '\\').replace('\\"', '"') + pdict[name] = value + return key, pdict + + def ntob(n, encoding='ISO-8859-1'): """Return the given native string as a byte string in the given encoding. diff --git a/cherrypy/lib/covercp.py b/cherrypy/lib/covercp.py index 6c3871fc9..f22cce742 100644 --- a/cherrypy/lib/covercp.py +++ b/cherrypy/lib/covercp.py @@ -22,7 +22,7 @@ import re import sys -import cgi +import html import os import os.path import urllib.parse @@ -352,9 +352,9 @@ def annotated_file(self, filename, statements, excluded, missing): buffer.append((lineno, line)) if empty_the_buffer: for lno, pastline in buffer: - yield template % (lno, cgi.escape(pastline)) + yield template % (lno, html.escape(pastline)) buffer = [] - yield template % (lineno, cgi.escape(line)) + yield template % (lineno, html.escape(line)) @cherrypy.expose def report(self, name): diff --git a/cherrypy/lib/httputil.py b/cherrypy/lib/httputil.py index 62bc1bd04..e72bbf8e7 100644 --- a/cherrypy/lib/httputil.py +++ b/cherrypy/lib/httputil.py @@ -12,7 +12,7 @@ import re import builtins from binascii import b2a_base64 -from cgi import parse_header +from cherrypy._cpcompat import cgi_parse_header as parse_header from email.header import decode_header from http.server import BaseHTTPRequestHandler from urllib.parse import unquote_plus diff --git a/pytest.ini b/pytest.ini index 53e18e200..bcecc9bd5 100644 --- a/pytest.ini +++ b/pytest.ini @@ -59,9 +59,6 @@ filterwarnings = ignore:the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses:DeprecationWarning ignore:the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses:PendingDeprecationWarning - # TODO: Replace the use of `cgi`. It seems untrivial. - ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning - # TODO: Remove once `cheroot.webtest._open_url_once` is fixed to release # TODO: connection properly. ignore:unclosed