Deprecate `md5 and sha1 wrappers in sphinx.util` (#11512)

This commit is contained in:
Adam Turner 2023-07-25 02:29:28 +01:00 committed by GitHub
parent f804da4b45
commit 5cf3dce36e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 42 additions and 25 deletions

View File

@ -12,6 +12,9 @@ Incompatible changes
Deprecated
----------
* #11512: Deprecate ``sphinx.util.md5`` and ``sphinx.util.sha1``.
Use ``hashlib`` instead.
Features added
--------------

View File

@ -22,6 +22,16 @@ The following is a list of deprecated interfaces.
- Removed
- Alternatives
* - ``sphinx.util.md5``
- 7.2
- 9.0
- ``hashlib.md5``
* - ``sphinx.util.sha1``
- 7.2
- 9.0
- ``hashlib.sha1``
* - ``sphinx.util.osutil.cd``
- 6.2
- 8.0

View File

@ -2,6 +2,7 @@
from __future__ import annotations
import hashlib
import html
import os
import posixpath
@ -37,7 +38,7 @@ from sphinx.highlighting import PygmentsBridge
from sphinx.locale import _, __
from sphinx.search import js_index
from sphinx.theming import HTMLThemeFactory
from sphinx.util import isurl, logging, md5
from sphinx.util import isurl, logging
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import new_document
from sphinx.util.fileutil import copy_asset
@ -80,7 +81,7 @@ def get_stable_hash(obj: Any) -> str:
return get_stable_hash(list(obj.items()))
elif isinstance(obj, (list, tuple)):
obj = sorted(get_stable_hash(o) for o in obj)
return md5(str(obj).encode()).hexdigest()
return hashlib.md5(str(obj).encode(), usedforsecurity=False).hexdigest()
def convert_locale_to_language_tag(locale: str | None) -> str | None:

View File

@ -6,6 +6,7 @@ from __future__ import annotations
import posixpath
import re
import subprocess
from hashlib import sha1
from os import path
from subprocess import CalledProcessError
from typing import TYPE_CHECKING, Any
@ -18,7 +19,7 @@ import sphinx
from sphinx.application import Sphinx
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.util import logging, sha1
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective, SphinxTranslator
from sphinx.util.i18n import search_image_for_language
from sphinx.util.nodes import set_source_info
@ -62,7 +63,7 @@ class ClickableMapDefinition:
if self.id == '%3':
# graphviz generates wrong ID if graph name not specified
# https://gitlab.com/graphviz/graphviz/issues/1327
hashed = sha1(dot.encode()).hexdigest()
hashed = sha1(dot.encode(), usedforsecurity=False).hexdigest()
self.id = 'grapviz%s' % hashed[-10:]
self.content[0] = self.content[0].replace('%3', self.id)
@ -221,7 +222,7 @@ def render_dot(self: SphinxTranslator, code: str, options: dict, format: str,
hashkey = (code + str(options) + str(graphviz_dot) +
str(self.builder.config.graphviz_dot_args)).encode()
fname = f'{prefix}-{sha1(hashkey).hexdigest()}.{format}'
fname = f'{prefix}-{sha1(hashkey, usedforsecurity=False).hexdigest()}.{format}'
relfn = posixpath.join(self.builder.imgpath, fname)
outfn = path.join(self.builder.outdir, self.builder.imagedir, fname)

View File

@ -7,6 +7,7 @@ import re
import shutil
import subprocess
import tempfile
from hashlib import sha1
from os import path
from subprocess import CalledProcessError
from typing import Any
@ -21,7 +22,7 @@ from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.util import logging, sha1
from sphinx.util import logging
from sphinx.util.math import get_node_equation_number, wrap_displaymath
from sphinx.util.osutil import ensuredir
from sphinx.util.png import read_png_depth, write_png_depth
@ -239,7 +240,7 @@ def render_math(
self.builder.config,
self.builder.confdir)
filename = f"{sha1(latex.encode()).hexdigest()}.{image_format}"
filename = f"{sha1(latex.encode(), usedforsecurity=False).hexdigest()}.{image_format}"
generated_path = path.join(self.builder.outdir, self.builder.imagedir, 'math', filename)
ensuredir(path.dirname(generated_path))
if path.isfile(generated_path):

View File

@ -31,6 +31,7 @@ LaTeX.
from __future__ import annotations
import builtins
import hashlib
import inspect
import re
from collections.abc import Iterable
@ -52,7 +53,6 @@ from sphinx.ext.graphviz import (
render_dot_latex,
render_dot_texinfo,
)
from sphinx.util import md5
from sphinx.util.docutils import SphinxDirective
from sphinx.util.typing import OptionSpec
from sphinx.writers.html import HTML5Translator
@ -392,7 +392,7 @@ class InheritanceDiagram(SphinxDirective):
def get_graph_hash(node: inheritance_diagram) -> str:
encoded = (node['content'] + str(node['parts'])).encode()
return md5(encoded).hexdigest()[-10:]
return hashlib.md5(encoded, usedforsecurity=False).hexdigest()[-10:]
def html_visit_inheritance_diagram(self: HTML5Translator, node: inheritance_diagram) -> None:

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import os
import re
from hashlib import sha1
from math import ceil
from typing import Any
@ -12,7 +13,7 @@ from docutils import nodes
from sphinx.application import Sphinx
from sphinx.locale import __
from sphinx.transforms import SphinxTransform
from sphinx.util import logging, requests, sha1
from sphinx.util import logging, requests
from sphinx.util.http_date import epoch_to_rfc1123, rfc1123_to_epoch
from sphinx.util.images import get_image_extension, guess_mimetype, parse_data_uri
from sphinx.util.osutil import ensuredir
@ -57,13 +58,13 @@ class ImageDownloader(BaseImageConverter):
basename = basename.split('?')[0]
if basename == '' or len(basename) > MAX_FILENAME_LEN:
filename, ext = os.path.splitext(node['uri'])
basename = sha1(filename.encode()).hexdigest() + ext
basename = sha1(filename.encode(), usedforsecurity=False).hexdigest() + ext
basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename)
dirname = node['uri'].replace('://', '/').translate({ord("?"): "/",
ord("&"): "/"})
if len(dirname) > MAX_FILENAME_LEN:
dirname = sha1(dirname.encode()).hexdigest()
dirname = sha1(dirname.encode(), usedforsecurity=False).hexdigest()
ensuredir(os.path.join(self.imagedir, dirname))
path = os.path.join(self.imagedir, dirname, basename)
@ -125,7 +126,7 @@ class DataURIExtractor(BaseImageConverter):
return
ensuredir(os.path.join(self.imagedir, 'embeded'))
digest = sha1(image.data).hexdigest()
digest = sha1(image.data, usedforsecurity=False).hexdigest()
path = os.path.join(self.imagedir, 'embeded', digest + ext)
self.app.env.original_image_uri[path] = node['uri']

View File

@ -104,21 +104,19 @@ class FilenameUniqDict(dict):
self._existing = state
def md5(data=b'', **kwargs):
"""Wrapper around hashlib.md5
def _md5(data=b'', **_kw):
"""Deprecated wrapper around hashlib.md5
Call with 'usedforsecurity=False'.
To be removed in Sphinx 9.0
"""
return hashlib.md5(data, usedforsecurity=False)
def sha1(data=b'', **kwargs):
"""Wrapper around hashlib.sha1
def _sha1(data=b'', **_kw):
"""Deprecated wrapper around hashlib.sha1
Call with 'usedforsecurity=False'.
To be removed in Sphinx 9.0
"""
return hashlib.sha1(data, usedforsecurity=False)
@ -131,7 +129,7 @@ class DownloadFiles(dict):
def add_file(self, docname: str, filename: str) -> str:
if filename not in self:
digest = md5(filename.encode()).hexdigest()
digest = hashlib.md5(filename.encode(), usedforsecurity=False).hexdigest()
dest = f'{digest}/{os.path.basename(filename)}'
self[filename] = (set(), dest)
@ -349,6 +347,8 @@ _DEPRECATED_OBJECTS = {
'format_exception_cut_frames': (_exceptions.format_exception_cut_frames,
'sphinx.exceptions.format_exception_cut_frames'),
'xmlname_checker': (_xml_name_checker, 'sphinx.builders.epub3._XML_NAME_PATTERN'),
'md5': (_md5, ''),
'sha1': (_sha1, ''),
}

View File

@ -1,5 +1,6 @@
"""Test the HTML builder and check output against XPath."""
import hashlib
import os
import re
from itertools import chain, cycle
@ -12,7 +13,6 @@ from html5lib import HTMLParser
from sphinx.builders.html import validate_html_extra_path, validate_html_static_path
from sphinx.errors import ConfigError
from sphinx.testing.util import strip_escseq
from sphinx.util import md5
from sphinx.util.inventory import InventoryFile
FIGURE_CAPTION = ".//figure/figcaption/p"
@ -474,9 +474,9 @@ def test_html_download(app):
@pytest.mark.sphinx('html', testroot='roles-download')
def test_html_download_role(app, status, warning):
app.build()
digest = md5(b'dummy.dat').hexdigest()
digest = hashlib.md5(b'dummy.dat', usedforsecurity=False).hexdigest()
assert (app.outdir / '_downloads' / digest / 'dummy.dat').exists()
digest_another = md5(b'another/dummy.dat').hexdigest()
digest_another = hashlib.md5(b'another/dummy.dat', usedforsecurity=False).hexdigest()
assert (app.outdir / '_downloads' / digest_another / 'dummy.dat').exists()
content = (app.outdir / 'index.html').read_text(encoding='utf8')