Skip to content

Commit

Permalink
馃敡 Stop using the cgi stdlib module
Browse files Browse the repository at this point in the history
the module was deprecatied in py 3.11 and removed in py 3.13
there are examples of using the email module to resolve this:
PEP 594
python-babel/babel#873
https://stackoverflow.com/questions/69068527/python-3-cgi-parse-header

This method doesn't seem to work for cherrypy.
The email.message module is trying to create a higher level
object that is intelligent about the headers it has defined. The
cgi.parse_header function is a very low level unintelligent function
that simply parses header content based on structure and does not
inspect the contents. Because of the intelligence of the email.message
object cherrypy can't use it in the very generic way that the
cgi.parse_header function was being used.

Fix #2014
  • Loading branch information
radez committed Feb 19, 2024
1 parent 6387a2b commit fe764cb
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 7 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v(next)
-------

* Removed the use of :mod:`cgi` deprecated in Python 3.11
-- by :user:`radez`.

v18.9.0
-------

Expand Down
37 changes: 37 additions & 0 deletions cherrypy/_cpcompat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions cherrypy/lib/covercp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import re
import sys
import cgi
import html
import os
import os.path
import urllib.parse
Expand Down Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion cherrypy/lib/httputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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 <socket.socket fd=:ResourceWarning
Expand Down

0 comments on commit fe764cb

Please sign in to comment.