"""Utility functions for Sphinx."""
from __future__ import annotations
import os
import posixpath
import re
TYPE_CHECKING = False
if TYPE_CHECKING:
import hashlib
from collections.abc import Callable
from types import ModuleType
from typing import Any
# Generally useful regular expressions.
ws_re: re.Pattern[str] = re.compile(r'\s+')
url_re: re.Pattern[str] = re.compile(r'(?P.+)://.*')
# High-level utility functions.
def docname_join(basedocname: str, docname: str) -> str:
return posixpath.normpath(posixpath.join(f'/{basedocname}', '..', docname))[1:]
def get_filetype(
source_suffix: dict[str, str], filename: str | os.PathLike[str]
) -> str:
from sphinx.errors import FiletypeNotFoundError
for suffix, filetype in source_suffix.items():
if os.fspath(filename).endswith(suffix):
# If default filetype (None), considered as restructuredtext.
return filetype or 'restructuredtext'
raise FiletypeNotFoundError
def _md5(data: bytes = b'', **_kw: Any) -> hashlib._Hash:
"""Deprecated wrapper around hashlib.md5
To be removed in Sphinx 9.0
"""
import hashlib
return hashlib.md5(data, usedforsecurity=False)
def _sha1(data: bytes = b'', **_kw: Any) -> hashlib._Hash:
"""Deprecated wrapper around hashlib.sha1
To be removed in Sphinx 9.0
"""
import hashlib
return hashlib.sha1(data, usedforsecurity=False)
def __getattr__(name: str) -> Any:
from sphinx.deprecation import _deprecation_warning
obj: Callable[..., Any]
mod: ModuleType
if name == 'console':
# Explicit temporary workaround for nbsphinx implicit imports.
# https://github.com/sphinx-doc/sphinx/issues/13352
import sphinx.util.console as mod
return mod
# RemovedInSphinx10Warning
if name in {'DownloadFiles', 'FilenameUniqDict'}:
from sphinx.util import _files as mod
obj = getattr(mod, name)
_deprecation_warning(__name__, name, '', remove=(10, 0))
return obj
# Re-exported for backwards compatibility,
# but not currently deprecated
if name == 'encode_uri':
from sphinx.util._uri import encode_uri
return encode_uri
if name == 'import_object':
from sphinx.util._importer import import_object
return import_object
if name == 'isurl':
from sphinx.util._uri import is_url
return is_url
if name == 'parselinenos':
from sphinx.util._lines import parse_line_num_spec
return parse_line_num_spec
if name == 'patfilter':
from sphinx.util.matching import patfilter
return patfilter
if name == 'strip_escape_sequences':
from sphinx._cli.util.errors import strip_escape_sequences
return strip_escape_sequences
if name in {
'caption_ref_re',
'explicit_title_re',
'nested_parse_with_titles',
'split_explicit_title',
}:
from sphinx.util import nodes as mod
return getattr(mod, name)
if name in {
'SEP',
'copyfile',
'ensuredir',
'make_filename',
'os_path',
'relative_uri',
}:
from sphinx.util import osutil as mod
return getattr(mod, name)
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)