Skip to content

Commit

Permalink
Merge branch 'master' into literallyinclude-options
Browse files Browse the repository at this point in the history
  • Loading branch information
AA-Turner authored Sep 18, 2024
2 parents 91f9162 + 71b1a06 commit 11206b5
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 29 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Contributors
* Michael Wilson -- Intersphinx HTTP basic auth support
* Nathan Damon -- bugfix in validation of static paths in html builders
* Pauli Virtanen -- autodoc improvements, autosummary extension
* A. Rafey Khan -- improved intersphinx typing
* Rob Ruana -- napoleon extension
* Robert Lehmann -- gettext builder (GSOC project)
* Roland Meister -- epub builder
Expand Down
1 change: 1 addition & 0 deletions doc/usage/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2783,6 +2783,7 @@ These options influence LaTeX output.

* :code-py:`'pdflatex'` -- PDFLaTeX (default)
* :code-py:`'xelatex'` -- XeLaTeX
(default if :confval:`language` is one of ``el``, ``zh_CN``, or ``zh_TW``)
* :code-py:`'lualatex'` -- LuaLaTeX
* :code-py:`'platex'` -- pLaTeX
* :code-py:`'uplatex'` -- upLaTeX
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ lint = [
"types-docutils==0.21.0.20240724",
"types-Pillow==10.2.0.20240822",
"types-Pygments==2.18.0.20240506",
"types-requests>=2.30.0", # align with requests
"types-requests==2.32.0.20240914", # align with requests
"types-urllib3==1.26.25.14",
"tomli>=2", # for mypy (Python<=3.10)
"pytest>=6.0",
]
Expand Down
2 changes: 1 addition & 1 deletion sphinx/ext/apidoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def module_join(*modnames: str | None) -> str:

def is_packagedir(dirname: str | None = None, files: list[str] | None = None) -> bool:
"""Check given *files* contains __init__ file."""
if files is dirname is None:
if files is None and dirname is None:
return False

if files is None:
Expand Down
21 changes: 12 additions & 9 deletions sphinx/ext/intersphinx/_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from __future__ import annotations

import concurrent.futures
import functools
import posixpath
import time
from operator import itemgetter
Expand All @@ -20,7 +19,8 @@

if TYPE_CHECKING:
from pathlib import Path
from typing import IO

from urllib3.response import HTTPResponse

from sphinx.application import Sphinx
from sphinx.config import Config
Expand All @@ -31,7 +31,7 @@
InventoryName,
InventoryURI,
)
from sphinx.util.typing import Inventory
from sphinx.util.typing import Inventory, _ReadableStream


def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
Expand Down Expand Up @@ -278,7 +278,7 @@ def _fetch_inventory(
target_uri = _strip_basic_auth(target_uri)
try:
if '://' in inv_location:
f = _read_from_url(inv_location, config=config)
f: _ReadableStream[bytes] = _read_from_url(inv_location, config=config)
else:
f = open(path.join(srcdir, inv_location), 'rb') # NoQA: SIM115
except Exception as err:
Expand Down Expand Up @@ -357,7 +357,7 @@ def _strip_basic_auth(url: str) -> str:
return urlunsplit(frags)


def _read_from_url(url: str, *, config: Config) -> IO:
def _read_from_url(url: str, *, config: Config) -> HTTPResponse:
"""Reads data from *url* with an HTTP *GET*.
This function supports fetching from resources which use basic HTTP auth as
Expand All @@ -377,8 +377,11 @@ def _read_from_url(url: str, *, config: Config) -> IO:
_user_agent=config.user_agent,
_tls_info=(config.tls_verify, config.tls_cacerts))
r.raise_for_status()
r.raw.url = r.url
# decode content-body based on the header.
# ref: https://github.com/psf/requests/issues/2155
r.raw.read = functools.partial(r.raw.read, decode_content=True)

# For inv_location / new_inv_location
r.raw.url = r.url # type: ignore[union-attr]

# Decode content-body based on the header.
# xref: https://github.com/psf/requests/issues/2155
r.raw.decode_content = True
return r.raw
8 changes: 4 additions & 4 deletions sphinx/util/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os
import re
import zlib
from typing import IO, TYPE_CHECKING
from typing import TYPE_CHECKING

from sphinx.locale import __
from sphinx.util import logging
Expand All @@ -17,7 +17,7 @@

from sphinx.builders import Builder
from sphinx.environment import BuildEnvironment
from sphinx.util.typing import Inventory, InventoryItem
from sphinx.util.typing import Inventory, InventoryItem, _ReadableStream


class InventoryFileReader:
Expand All @@ -26,7 +26,7 @@ class InventoryFileReader:
This reader supports mixture of texts and compressed texts.
"""

def __init__(self, stream: IO[bytes]) -> None:
def __init__(self, stream: _ReadableStream[bytes]) -> None:
self.stream = stream
self.buffer = b''
self.eof = False
Expand Down Expand Up @@ -80,7 +80,7 @@ class InventoryFile:
@classmethod
def load(
cls: type[InventoryFile],
stream: IO[bytes],
stream: _ReadableStream[bytes],
uri: str,
joinfunc: Callable[[str, str], str],
) -> Inventory:
Expand Down
23 changes: 23 additions & 0 deletions sphinx/util/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ def __call__(
# title getter functions for enumerable nodes (see sphinx.domains.std)
TitleGetter: TypeAlias = Callable[[nodes.Node], str]

# Readable file stream for inventory loading
if TYPE_CHECKING:
from types import TracebackType

from typing_extensions import Self

_T_co = TypeVar('_T_co', str, bytes, covariant=True)

class _ReadableStream(Protocol[_T_co]):
def read(self, size: int = ...) -> _T_co:
...

def __enter__(self) -> Self:
...

def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None
) -> None:
...

# inventory data on memory
InventoryItem: TypeAlias = tuple[
str, # project name
Expand Down
41 changes: 28 additions & 13 deletions tests/test_builders/test_build_html_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,36 @@ def test_html_scaled_image_link(app):
assert re.search('\n<img alt="_images/img.png" src="_images/img.png" />', context)

# scaled_image_link
# Docutils 0.21 adds a newline before the closing </a> tag
closing_space = '\n' if docutils.__version_info__[:2] >= (0, 21) else ''
assert re.search(
'\n<a class="reference internal image-reference" href="_images/img.png">'
'<img alt="_images/img.png" src="_images/img.png" style="[^"]+" />'
f'{closing_space}</a>',
context,
)
if docutils.__version_info__[:2] >= (0, 22):
assert re.search(
'\n<a class="reference internal image-reference" href="_images/img.png">'
'<img alt="_images/img.png" height="[^"]+" src="_images/img.png" width="[^"]+" />'
'\n</a>',
context,
)
else:
# Docutils 0.21 adds a newline before the closing </a> tag
closing_space = '\n' if docutils.__version_info__[:2] >= (0, 21) else ''
assert re.search(
'\n<a class="reference internal image-reference" href="_images/img.png">'
'<img alt="_images/img.png" src="_images/img.png" style="[^"]+" />'
f'{closing_space}</a>',
context,
)

# no-scaled-link class disables the feature
assert re.search(
'\n<img alt="_images/img.png" class="no-scaled-link"'
' src="_images/img.png" style="[^"]+" />',
context,
)
if docutils.__version_info__[:2] >= (0, 22):
assert re.search(
'\n<img alt="_images/img.png" class="no-scaled-link"'
' height="[^"]+" src="_images/img.png" width="[^"]+" />',
context,
)
else:
assert re.search(
'\n<img alt="_images/img.png" class="no-scaled-link"'
' src="_images/img.png" style="[^"]+" />',
context,
)


@pytest.mark.usefixtures('_http_teapot')
Expand Down
2 changes: 1 addition & 1 deletion tests/test_builders/test_build_linkcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def __init__(self) -> None:

def _collect_connections(self) -> Callable[[object, str], HTTPConnectionPool]:
def connection_collector(obj, url):
connection = self.urllib3_connection_from_url(obj, url)
connection = self.urllib3_connection_from_url(obj, url) # type: ignore[no-untyped-call]
self.connections.add(connection)
return connection

Expand Down

0 comments on commit 11206b5

Please sign in to comment.