Move `_file_checksum() to sphinx.builders.html._assets`

This commit is contained in:
Adam Turner 2023-08-12 00:20:00 +01:00
parent 44a7820cd9
commit 42a6546404
3 changed files with 36 additions and 27 deletions

View File

@ -9,7 +9,6 @@ import posixpath
import re
import sys
import warnings
import zlib
from datetime import datetime, timezone
from os import path
from typing import IO, TYPE_CHECKING, Any
@ -27,6 +26,7 @@ from sphinx import __display_version__, package_dir
from sphinx import version_info as sphinx_version
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.builders.html._assets import _file_checksum
from sphinx.config import ENUM, Config
from sphinx.domains import Domain, Index, IndexEntry
from sphinx.environment import BuildEnvironment
@ -1254,29 +1254,6 @@ def setup_js_tag_helper(app: Sphinx, pagename: str, templatename: str,
context['js_tag'] = js_tag
def _file_checksum(outdir: str | os.PathLike[str], filename: str | os.PathLike[str]) -> str:
filename = os.fspath(filename)
# Don't generate checksums for HTTP URIs
if '://' in filename:
return ''
# Some themes and extensions have used query strings
# for a similar asset checksum feature.
# As we cannot safely strip the query string,
# raise an error to the user.
if '?' in filename:
msg = f'Local asset file paths must not contain query strings: {filename!r}'
raise ThemeError(msg)
try:
# Ensure universal newline mode is used to avoid checksum differences
with open(path.join(outdir, filename), encoding='utf-8') as f:
content = f.read().encode(encoding='utf-8')
except FileNotFoundError:
return ''
if not content:
return ''
return f'{zlib.crc32(content):08x}'
def setup_resource_paths(app: Sphinx, pagename: str, templatename: str,
context: dict, doctree: Node) -> None:
"""Set up relative resource paths."""

View File

@ -0,0 +1,32 @@
from __future__ import annotations
import os
import zlib
from typing import TYPE_CHECKING
from sphinx.errors import ThemeError
if TYPE_CHECKING:
from pathlib import Path
def _file_checksum(outdir: Path, filename: str | os.PathLike[str]) -> str:
filename = os.fspath(filename)
# Don't generate checksums for HTTP URIs
if '://' in filename:
return ''
# Some themes and extensions have used query strings
# for a similar asset checksum feature.
# As we cannot safely strip the query string,
# raise an error to the user.
if '?' in filename:
msg = f'Local asset file paths must not contain query strings: {filename!r}'
raise ThemeError(msg)
try:
# Remove all carriage returns to avoid checksum differences
content = outdir.joinpath(filename).read_bytes().translate(None, b'\r')
except FileNotFoundError:
return ''
if not content:
return ''
return f'{zlib.crc32(content):08x}'

View File

@ -12,10 +12,10 @@ from html5lib import HTMLParser
import sphinx.builders.html
from sphinx.builders.html import (
_file_checksum,
validate_html_extra_path,
validate_html_static_path,
)
from sphinx.builders.html._assets import _file_checksum
from sphinx.errors import ConfigError, ThemeError
from sphinx.testing.util import strip_escseq
from sphinx.util.inventory import InventoryFile
@ -1248,10 +1248,10 @@ def test_file_checksum(app):
def test_file_checksum_query_string():
with pytest.raises(ThemeError, match='Local asset file paths must not contain query strings'):
_file_checksum('', 'with_query_string.css?dead_parrots=1')
_file_checksum(Path(), 'with_query_string.css?dead_parrots=1')
with pytest.raises(ThemeError, match='Local asset file paths must not contain query strings'):
_file_checksum('', 'with_query_string.js?dead_parrots=1')
_file_checksum(Path(), 'with_query_string.js?dead_parrots=1')
with pytest.raises(ThemeError, match='Local asset file paths must not contain query strings'):
_file_checksum(Path.cwd(), '_static/with_query_string.css?dead_parrots=1')