mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Deprecate `md5
and
sha1
wrappers in
sphinx.util
` (#11512)
This commit is contained in:
parent
f804da4b45
commit
5cf3dce36e
3
CHANGES
3
CHANGES
@ -12,6 +12,9 @@ Incompatible changes
|
|||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* #11512: Deprecate ``sphinx.util.md5`` and ``sphinx.util.sha1``.
|
||||||
|
Use ``hashlib`` instead.
|
||||||
|
|
||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
@ -22,6 +22,16 @@ The following is a list of deprecated interfaces.
|
|||||||
- Removed
|
- Removed
|
||||||
- Alternatives
|
- Alternatives
|
||||||
|
|
||||||
|
* - ``sphinx.util.md5``
|
||||||
|
- 7.2
|
||||||
|
- 9.0
|
||||||
|
- ``hashlib.md5``
|
||||||
|
|
||||||
|
* - ``sphinx.util.sha1``
|
||||||
|
- 7.2
|
||||||
|
- 9.0
|
||||||
|
- ``hashlib.sha1``
|
||||||
|
|
||||||
* - ``sphinx.util.osutil.cd``
|
* - ``sphinx.util.osutil.cd``
|
||||||
- 6.2
|
- 6.2
|
||||||
- 8.0
|
- 8.0
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
import html
|
import html
|
||||||
import os
|
import os
|
||||||
import posixpath
|
import posixpath
|
||||||
@ -37,7 +38,7 @@ from sphinx.highlighting import PygmentsBridge
|
|||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
from sphinx.search import js_index
|
from sphinx.search import js_index
|
||||||
from sphinx.theming import HTMLThemeFactory
|
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.display import progress_message, status_iterator
|
||||||
from sphinx.util.docutils import new_document
|
from sphinx.util.docutils import new_document
|
||||||
from sphinx.util.fileutil import copy_asset
|
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()))
|
return get_stable_hash(list(obj.items()))
|
||||||
elif isinstance(obj, (list, tuple)):
|
elif isinstance(obj, (list, tuple)):
|
||||||
obj = sorted(get_stable_hash(o) for o in obj)
|
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:
|
def convert_locale_to_language_tag(locale: str | None) -> str | None:
|
||||||
|
@ -6,6 +6,7 @@ from __future__ import annotations
|
|||||||
import posixpath
|
import posixpath
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from hashlib import sha1
|
||||||
from os import path
|
from os import path
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
@ -18,7 +19,7 @@ import sphinx
|
|||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import _, __
|
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.docutils import SphinxDirective, SphinxTranslator
|
||||||
from sphinx.util.i18n import search_image_for_language
|
from sphinx.util.i18n import search_image_for_language
|
||||||
from sphinx.util.nodes import set_source_info
|
from sphinx.util.nodes import set_source_info
|
||||||
@ -62,7 +63,7 @@ class ClickableMapDefinition:
|
|||||||
if self.id == '%3':
|
if self.id == '%3':
|
||||||
# graphviz generates wrong ID if graph name not specified
|
# graphviz generates wrong ID if graph name not specified
|
||||||
# https://gitlab.com/graphviz/graphviz/issues/1327
|
# 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.id = 'grapviz%s' % hashed[-10:]
|
||||||
self.content[0] = self.content[0].replace('%3', self.id)
|
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) +
|
hashkey = (code + str(options) + str(graphviz_dot) +
|
||||||
str(self.builder.config.graphviz_dot_args)).encode()
|
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)
|
relfn = posixpath.join(self.builder.imgpath, fname)
|
||||||
outfn = path.join(self.builder.outdir, self.builder.imagedir, fname)
|
outfn = path.join(self.builder.outdir, self.builder.imagedir, fname)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from hashlib import sha1
|
||||||
from os import path
|
from os import path
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -21,7 +22,7 @@ from sphinx.builders import Builder
|
|||||||
from sphinx.config import Config
|
from sphinx.config import Config
|
||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import _, __
|
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.math import get_node_equation_number, wrap_displaymath
|
||||||
from sphinx.util.osutil import ensuredir
|
from sphinx.util.osutil import ensuredir
|
||||||
from sphinx.util.png import read_png_depth, write_png_depth
|
from sphinx.util.png import read_png_depth, write_png_depth
|
||||||
@ -239,7 +240,7 @@ def render_math(
|
|||||||
self.builder.config,
|
self.builder.config,
|
||||||
self.builder.confdir)
|
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)
|
generated_path = path.join(self.builder.outdir, self.builder.imagedir, 'math', filename)
|
||||||
ensuredir(path.dirname(generated_path))
|
ensuredir(path.dirname(generated_path))
|
||||||
if path.isfile(generated_path):
|
if path.isfile(generated_path):
|
||||||
|
@ -31,6 +31,7 @@ LaTeX.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
|
import hashlib
|
||||||
import inspect
|
import inspect
|
||||||
import re
|
import re
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
@ -52,7 +53,6 @@ from sphinx.ext.graphviz import (
|
|||||||
render_dot_latex,
|
render_dot_latex,
|
||||||
render_dot_texinfo,
|
render_dot_texinfo,
|
||||||
)
|
)
|
||||||
from sphinx.util import md5
|
|
||||||
from sphinx.util.docutils import SphinxDirective
|
from sphinx.util.docutils import SphinxDirective
|
||||||
from sphinx.util.typing import OptionSpec
|
from sphinx.util.typing import OptionSpec
|
||||||
from sphinx.writers.html import HTML5Translator
|
from sphinx.writers.html import HTML5Translator
|
||||||
@ -392,7 +392,7 @@ class InheritanceDiagram(SphinxDirective):
|
|||||||
|
|
||||||
def get_graph_hash(node: inheritance_diagram) -> str:
|
def get_graph_hash(node: inheritance_diagram) -> str:
|
||||||
encoded = (node['content'] + str(node['parts'])).encode()
|
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:
|
def html_visit_inheritance_diagram(self: HTML5Translator, node: inheritance_diagram) -> None:
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from hashlib import sha1
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ from docutils import nodes
|
|||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.transforms import SphinxTransform
|
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.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.images import get_image_extension, guess_mimetype, parse_data_uri
|
||||||
from sphinx.util.osutil import ensuredir
|
from sphinx.util.osutil import ensuredir
|
||||||
@ -57,13 +58,13 @@ class ImageDownloader(BaseImageConverter):
|
|||||||
basename = basename.split('?')[0]
|
basename = basename.split('?')[0]
|
||||||
if basename == '' or len(basename) > MAX_FILENAME_LEN:
|
if basename == '' or len(basename) > MAX_FILENAME_LEN:
|
||||||
filename, ext = os.path.splitext(node['uri'])
|
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)
|
basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename)
|
||||||
|
|
||||||
dirname = node['uri'].replace('://', '/').translate({ord("?"): "/",
|
dirname = node['uri'].replace('://', '/').translate({ord("?"): "/",
|
||||||
ord("&"): "/"})
|
ord("&"): "/"})
|
||||||
if len(dirname) > MAX_FILENAME_LEN:
|
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))
|
ensuredir(os.path.join(self.imagedir, dirname))
|
||||||
path = os.path.join(self.imagedir, dirname, basename)
|
path = os.path.join(self.imagedir, dirname, basename)
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ class DataURIExtractor(BaseImageConverter):
|
|||||||
return
|
return
|
||||||
|
|
||||||
ensuredir(os.path.join(self.imagedir, 'embeded'))
|
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)
|
path = os.path.join(self.imagedir, 'embeded', digest + ext)
|
||||||
self.app.env.original_image_uri[path] = node['uri']
|
self.app.env.original_image_uri[path] = node['uri']
|
||||||
|
|
||||||
|
@ -104,21 +104,19 @@ class FilenameUniqDict(dict):
|
|||||||
self._existing = state
|
self._existing = state
|
||||||
|
|
||||||
|
|
||||||
def md5(data=b'', **kwargs):
|
def _md5(data=b'', **_kw):
|
||||||
"""Wrapper around hashlib.md5
|
"""Deprecated wrapper around hashlib.md5
|
||||||
|
|
||||||
Call with 'usedforsecurity=False'.
|
To be removed in Sphinx 9.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return hashlib.md5(data, usedforsecurity=False)
|
return hashlib.md5(data, usedforsecurity=False)
|
||||||
|
|
||||||
|
|
||||||
def sha1(data=b'', **kwargs):
|
def _sha1(data=b'', **_kw):
|
||||||
"""Wrapper around hashlib.sha1
|
"""Deprecated wrapper around hashlib.sha1
|
||||||
|
|
||||||
Call with 'usedforsecurity=False'.
|
To be removed in Sphinx 9.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return hashlib.sha1(data, usedforsecurity=False)
|
return hashlib.sha1(data, usedforsecurity=False)
|
||||||
|
|
||||||
|
|
||||||
@ -131,7 +129,7 @@ class DownloadFiles(dict):
|
|||||||
|
|
||||||
def add_file(self, docname: str, filename: str) -> str:
|
def add_file(self, docname: str, filename: str) -> str:
|
||||||
if filename not in self:
|
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)}'
|
dest = f'{digest}/{os.path.basename(filename)}'
|
||||||
self[filename] = (set(), dest)
|
self[filename] = (set(), dest)
|
||||||
|
|
||||||
@ -349,6 +347,8 @@ _DEPRECATED_OBJECTS = {
|
|||||||
'format_exception_cut_frames': (_exceptions.format_exception_cut_frames,
|
'format_exception_cut_frames': (_exceptions.format_exception_cut_frames,
|
||||||
'sphinx.exceptions.format_exception_cut_frames'),
|
'sphinx.exceptions.format_exception_cut_frames'),
|
||||||
'xmlname_checker': (_xml_name_checker, 'sphinx.builders.epub3._XML_NAME_PATTERN'),
|
'xmlname_checker': (_xml_name_checker, 'sphinx.builders.epub3._XML_NAME_PATTERN'),
|
||||||
|
'md5': (_md5, ''),
|
||||||
|
'sha1': (_sha1, ''),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Test the HTML builder and check output against XPath."""
|
"""Test the HTML builder and check output against XPath."""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from itertools import chain, cycle
|
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.builders.html import validate_html_extra_path, validate_html_static_path
|
||||||
from sphinx.errors import ConfigError
|
from sphinx.errors import ConfigError
|
||||||
from sphinx.testing.util import strip_escseq
|
from sphinx.testing.util import strip_escseq
|
||||||
from sphinx.util import md5
|
|
||||||
from sphinx.util.inventory import InventoryFile
|
from sphinx.util.inventory import InventoryFile
|
||||||
|
|
||||||
FIGURE_CAPTION = ".//figure/figcaption/p"
|
FIGURE_CAPTION = ".//figure/figcaption/p"
|
||||||
@ -474,9 +474,9 @@ def test_html_download(app):
|
|||||||
@pytest.mark.sphinx('html', testroot='roles-download')
|
@pytest.mark.sphinx('html', testroot='roles-download')
|
||||||
def test_html_download_role(app, status, warning):
|
def test_html_download_role(app, status, warning):
|
||||||
app.build()
|
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()
|
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()
|
assert (app.outdir / '_downloads' / digest_another / 'dummy.dat').exists()
|
||||||
|
|
||||||
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
||||||
|
Loading…
Reference in New Issue
Block a user