Add `sphinx.util._uri`

This commit is contained in:
Adam Turner
2024-10-05 16:43:05 +01:00
parent 4c638d8289
commit 40f8693661
6 changed files with 52 additions and 46 deletions

View File

@@ -42,8 +42,9 @@ 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
from sphinx.util import logging
from sphinx.util._timestamps import _format_rfc3339_microseconds
from sphinx.util._uri import is_url
from sphinx.util.console import bold
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import new_document
@@ -486,9 +487,9 @@ class StandaloneHTMLBuilder(Builder):
logo = self.config.html_logo or ''
favicon = self.config.html_favicon or ''
if not isurl(logo):
if not is_url(logo):
logo = path.basename(logo)
if not isurl(favicon):
if not is_url(favicon):
favicon = path.basename(favicon)
self.relations = self.env.collect_relations()
@@ -873,7 +874,7 @@ class StandaloneHTMLBuilder(Builder):
)
def copy_html_logo(self) -> None:
if self.config.html_logo and not isurl(self.config.html_logo):
if self.config.html_logo and not is_url(self.config.html_logo):
source_path = self.confdir / self.config.html_logo
copyfile(
source_path,
@@ -882,7 +883,7 @@ class StandaloneHTMLBuilder(Builder):
)
def copy_html_favicon(self) -> None:
if self.config.html_favicon and not isurl(self.config.html_favicon):
if self.config.html_favicon and not is_url(self.config.html_favicon):
source_path = self.confdir / self.config.html_favicon
copyfile(
source_path,
@@ -1293,12 +1294,12 @@ def setup_resource_paths(
# favicon_url
favicon_url = context.get('favicon_url')
if favicon_url and not isurl(favicon_url):
if favicon_url and not is_url(favicon_url):
context['favicon_url'] = pathto('_static/' + favicon_url, resource=True)
# logo_url
logo_url = context.get('logo_url')
if logo_url and not isurl(logo_url):
if logo_url and not is_url(logo_url):
context['logo_url'] = pathto('_static/' + logo_url, resource=True)
@@ -1355,7 +1356,7 @@ def validate_html_logo(app: Sphinx, config: Config) -> None:
if (
config.html_logo
and not path.isfile(path.join(app.confdir, config.html_logo))
and not isurl(config.html_logo)
and not is_url(config.html_logo)
):
logger.warning(__('logo file %r does not exist'), config.html_logo)
config.html_logo = None
@@ -1366,7 +1367,7 @@ def validate_html_favicon(app: Sphinx, config: Config) -> None:
if (
config.html_favicon
and not path.isfile(path.join(app.confdir, config.html_favicon))
and not isurl(config.html_favicon)
and not is_url(config.html_favicon)
):
logger.warning(__('favicon file %r does not exist'), config.html_favicon)
config.html_favicon = None

View File

@@ -21,7 +21,8 @@ from requests.exceptions import Timeout as RequestTimeout
from sphinx.builders.dummy import DummyBuilder
from sphinx.locale import __
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util import encode_uri, logging, requests
from sphinx.util import logging, requests
from sphinx.util._uri import encode_uri
from sphinx.util.console import darkgray, darkgreen, purple, red, turquoise
from sphinx.util.http_date import rfc1123_to_epoch
from sphinx.util.nodes import get_node_line

View File

@@ -7,12 +7,13 @@ import os
import posixpath
import re
from typing import Any
from urllib.parse import parse_qsl, quote_plus, urlencode, urlsplit, urlunsplit
from sphinx.errors import FiletypeNotFoundError
from sphinx.locale import __
from sphinx.util import _files, _importer, logging
from sphinx.util import index_entries as _index_entries
from sphinx.util._uri import encode_uri # NoQA: F401
from sphinx.util._uri import is_url as isurl # NoQA: F401
from sphinx.util.console import strip_colors # NoQA: F401
from sphinx.util.matching import patfilter # NoQA: F401
from sphinx.util.nodes import ( # NoQA: F401
@@ -128,20 +129,6 @@ def parselinenos(spec: str, total: int) -> list[int]:
return items
def encode_uri(uri: str) -> str:
split = list(urlsplit(uri))
split[1] = split[1].encode('idna').decode('ascii')
split[2] = quote_plus(split[2].encode(), '/')
query = [(q, v.encode()) for (q, v) in parse_qsl(split[3])]
split[3] = urlencode(query)
return urlunsplit(split)
def isurl(url: str) -> bool:
"""Check *url* is URL or not."""
return bool(url) and '://' in url
# deprecated name -> (object to return, canonical path or empty string)
_DEPRECATED_OBJECTS: dict[str, tuple[Any, str, tuple[int, int]]] = {
'split_index_msg': (

16
sphinx/util/_uri.py Normal file
View File

@@ -0,0 +1,16 @@
from __future__ import annotations
from urllib.parse import parse_qsl, quote_plus, urlencode, urlsplit, urlunsplit
def encode_uri(uri: str) -> str:
scheme, netloc, url, query, fragment = urlsplit(uri)
netloc = netloc.encode('idna').decode('ascii')
url = quote_plus(url.encode(), '/')
query = urlencode([(q, v.encode()) for (q, v) in parse_qsl(query)])
return urlunsplit((scheme, netloc, url, query, fragment))
def is_url(url: str) -> bool:
"""Check *url* is URL or not."""
return bool(url) and '://' in url

View File

@@ -5,30 +5,10 @@ import tempfile
import pytest
from sphinx.util import encode_uri, parselinenos
from sphinx.util import parselinenos
from sphinx.util.osutil import ensuredir
def test_encode_uri():
expected = (
'https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_'
'%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_'
'%D0%B1%D0%B0%D0%B7%D0%B0%D0%BC%D0%B8_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85'
)
uri = 'https://ru.wikipedia.org/wiki/Система_управления_базами_данных'
assert encode_uri(uri) == expected
expected = (
'https://github.com/search?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+is%3A'
'sprint-friendly+user%3Ajupyter&type=Issues&ref=searchresults'
)
uri = (
'https://github.com/search?utf8=✓&q=is%3Aissue+is%3Aopen+is%3A'
'sprint-friendly+user%3Ajupyter&type=Issues&ref=searchresults'
)
assert encode_uri(uri) == expected
def test_ensuredir():
with tempfile.TemporaryDirectory() as tmp_path:
# Does not raise an exception for an existing directory.

View File

@@ -0,0 +1,21 @@
from sphinx.util._uri import encode_uri
def test_encode_uri():
expected = (
'https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_'
'%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_'
'%D0%B1%D0%B0%D0%B7%D0%B0%D0%BC%D0%B8_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85'
)
uri = 'https://ru.wikipedia.org/wiki/Система_управления_базами_данных'
assert encode_uri(uri) == expected
expected = (
'https://github.com/search?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+is%3A'
'sprint-friendly+user%3Ajupyter&type=Issues&ref=searchresults'
)
uri = (
'https://github.com/search?utf8=✓&q=is%3Aissue+is%3Aopen+is%3A'
'sprint-friendly+user%3Ajupyter&type=Issues&ref=searchresults'
)
assert encode_uri(uri) == expected