Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-sphinx-scrapy for
openSUSE:Factory checked in at 2026-08-22 21:36:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sphinx-scrapy (Old)
and /work/SRC/openSUSE:Factory/.python-sphinx-scrapy.new.1258 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sphinx-scrapy"
Sat Aug 22 21:36:23 2026 rev:3 rq:1373068 version:0.8.12
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-sphinx-scrapy/python-sphinx-scrapy.changes
2026-07-06 12:35:37.062260245 +0200
+++
/work/SRC/openSUSE:Factory/.python-sphinx-scrapy.new.1258/python-sphinx-scrapy.changes
2026-08-22 21:38:29.564261254 +0200
@@ -1,0 +2,21 @@
+Sat Aug 22 13:45:02 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.8.12:
+ * Extended easy Intersphinx configuration to platformdirs
+ * Added an explicit dependency on docutils.
+ * Added the :gh: role, to link to GitHub issues and pull
+ requests, of the current repository or of a different one.
+ * Fixed project data from pyproject.toml, like the automatic
+ html_baseurl value, being read relative to the current
+ working directory instead of relative to conf.py.
+ * Fixed the docs tox environment getting an invalid Python
+ interpreter in projects without a pyproject.toml.
+ * Fixed the docs tox environment failing to find its Python
+ interpreter when tox-uv is installed.
+ * Added the stat cross-reference type, for the .. stat::
+ directive and the :stat: role, to document and link to Scrapy
+ stats.
+ * Extended easy Intersphinx configuration to scrapy-lint
+ * Extended easy Intersphinx configuration to pypug
+
+-------------------------------------------------------------------
Old:
----
sphinx_scrapy-0.8.6.tar.gz
New:
----
sphinx_scrapy-0.8.12.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-sphinx-scrapy.spec ++++++
--- /var/tmp/diff_new_pack.3WnUfo/_old 2026-08-22 21:38:30.237285361 +0200
+++ /var/tmp/diff_new_pack.3WnUfo/_new 2026-08-22 21:38:30.239285432 +0200
@@ -19,7 +19,7 @@
# Enable libalternatives by default
%bcond_without libalternatives
Name: python-sphinx-scrapy
-Version: 0.8.6
+Version: 0.8.12
Release: 0
Summary: Sphinx extension for documentation in the Scrapy ecosystem
License: BSD-3-Clause
++++++ sphinx_scrapy-0.8.6.tar.gz -> sphinx_scrapy-0.8.12.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/.github/actionlint.yaml
new/sphinx-scrapy-0.8.12/.github/actionlint.yaml
--- old/sphinx-scrapy-0.8.6/.github/actionlint.yaml 1970-01-01
01:00:00.000000000 +0100
+++ new/sphinx-scrapy-0.8.12/.github/actionlint.yaml 2026-08-14
14:28:50.000000000 +0200
@@ -0,0 +1,6 @@
+paths:
+ .github/workflows/publish.yml:
+ ignore:
+ # The job is disabled on purpose while the package cannot be published to
+ # PyPI, see the README.
+ - 'constant expression "false" in condition'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/.github/dependabot.yml
new/sphinx-scrapy-0.8.12/.github/dependabot.yml
--- old/sphinx-scrapy-0.8.6/.github/dependabot.yml 1970-01-01
01:00:00.000000000 +0100
+++ new/sphinx-scrapy-0.8.12/.github/dependabot.yml 2026-08-14
14:28:50.000000000 +0200
@@ -0,0 +1,12 @@
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: "/"
+ schedule:
+ interval: monthly
+ groups:
+ github-actions:
+ patterns:
+ - "*"
+ cooldown:
+ default-days: 7
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/.github/workflows/ci.yml
new/sphinx-scrapy-0.8.12/.github/workflows/ci.yml
--- old/sphinx-scrapy-0.8.6/.github/workflows/ci.yml 1970-01-01
01:00:00.000000000 +0100
+++ new/sphinx-scrapy-0.8.12/.github/workflows/ci.yml 2026-08-14
14:28:50.000000000 +0200
@@ -0,0 +1,26 @@
+name: CI
+
+permissions:
+ contents: read
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+concurrency:
+ group: ${{github.workflow}}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ pre-commit:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #
v7.0.0
+ with:
+ python-version: 3.14
+ - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/.github/workflows/publish.yml
new/sphinx-scrapy-0.8.12/.github/workflows/publish.yml
--- old/sphinx-scrapy-0.8.6/.github/workflows/publish.yml 2026-05-12
09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/.github/workflows/publish.yml 2026-08-14
14:28:50.000000000 +0200
@@ -1,10 +1,20 @@
name: Publish
+
+permissions:
+ contents: read
+
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
+
+concurrency:
+ group: ${{github.workflow}}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
publish:
+ if: false # Cannot be published to PyPI at the moment, see the README.
runs-on: ubuntu-latest
environment:
name: pypi
@@ -12,14 +22,16 @@
permissions:
id-token: write
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #
v7.0.0
with:
python-version: 3.14
- run: |
python -m pip install --upgrade build
python -m build
- name: Publish to PyPI
- uses: pypa/gh-action-pypi-publish@release/v1
+ uses:
pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
verbose: true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/.pre-commit-config.yaml
new/sphinx-scrapy-0.8.12/.pre-commit-config.yaml
--- old/sphinx-scrapy-0.8.6/.pre-commit-config.yaml 2026-05-12
09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/.pre-commit-config.yaml 2026-08-14
14:28:50.000000000 +0200
@@ -9,6 +9,10 @@
rev: v1.16.0
hooks:
- id: mypy
+ additional_dependencies:
+ - sphinx
+ - tox
+ - types-docutils
- repo: https://github.com/adamchainz/blacken-docs
rev: 1.19.1
hooks:
@@ -16,6 +20,20 @@
additional_dependencies:
- black==25.1.0
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
+ - id: end-of-file-fixer
- id: trailing-whitespace
+- repo: https://github.com/sphinx-contrib/sphinx-lint
+ rev: v1.0.2
+ hooks:
+ - id: sphinx-lint
+- repo: https://github.com/rhysd/actionlint
+ rev: v1.7.12
+ hooks:
+ - id: actionlint
+- repo: https://github.com/zizmorcore/zizmor-pre-commit
+ rev: v1.29.0
+ hooks:
+ - id: zizmor
+ args: [--no-progress, --fix]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/CHANGES.rst
new/sphinx-scrapy-0.8.12/CHANGES.rst
--- old/sphinx-scrapy-0.8.6/CHANGES.rst 2026-05-12 09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/CHANGES.rst 2026-08-14 14:28:50.000000000
+0200
@@ -2,6 +2,51 @@
Release notes
=============
+0.8.12 (2026-08-14)
+===================
+
+- | Extended easy Intersphinx configuration to
+ | `platformdirs <https://platformdirs.readthedocs.io/en/latest/>`_
+
+- Added an explicit dependency on ``docutils``.
+
+0.8.11 (2026-08-10)
+===================
+
+- Added the ``:gh:`` role, to link to GitHub issues and pull requests, of the
+ current repository or of a different one.
+
+- Fixed project data from ``pyproject.toml``, like the automatic
+ ``html_baseurl`` value, being read relative to the current working
+ directory instead of relative to ``conf.py``.
+
+- Fixed the ``docs`` tox environment getting an invalid Python interpreter in
+ projects without a ``pyproject.toml``.
+
+0.8.10 (2026-07-31)
+===================
+
+- Fixed the ``docs`` tox environment failing to find its Python interpreter
+ when `tox-uv <https://github.com/tox-dev/tox-uv>`_ is installed.
+
+0.8.9 (2026-07-29)
+==================
+
+- Added the ``stat`` cross-reference type, for the ``.. stat::`` directive
+ and the ``:stat:`` role, to document and link to Scrapy stats.
+
+0.8.8 (2026-06-15)
+==================
+
+- | Extended easy Intersphinx configuration to
+ | `scrapy-lint <https://scrapy-lint.readthedocs.io/en/latest/>`_
+
+0.8.7 (2026-06-11)
+==================
+
+- | Extended easy Intersphinx configuration to
+ | `pypug <https://packaging.python.org/en/latest/>`_
+
0.8.6 (2026-05-12)
==================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/README.rst
new/sphinx-scrapy-0.8.12/README.rst
--- old/sphinx-scrapy-0.8.6/README.rst 2026-05-12 09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/README.rst 2026-08-14 14:28:50.000000000 +0200
@@ -30,7 +30,7 @@
`additional packages <#intersphinx-packages>`_.
- Allows you to easily link to Scrapy settings, request metadata keys,
- signals and commands:
+ signals, commands and stats:
.. code-block:: rst
@@ -39,6 +39,21 @@
:reqmeta:`download_slot`
:signal:`spider_opened`
:command:`crawl`
+ :stat:`item_scraped_count`
+
+- Allows you to easily link to GitHub issues and pull requests:
+
+ .. code-block:: rst
+
+ :gh:`1908`
+ :gh:`parsel#12`
+ :gh:`sphinx-doc/sphinx#13000`
+
+ They render as ``#1908``, ``parsel#12`` and ``sphinx#13000``. Use the
number
+ alone for the current repository, which comes from the GitHub URLs in
+ ``pyproject.toml``. For a different repository, its name alone is enough if
+ it is a known repository of the Scrapy ecosystem or it belongs to the same
+ owner as the current repository.
Setup
=====
@@ -50,7 +65,7 @@
[tool.sphinx-scrapy]
python-version = "3.14"
-
+
It must be `supported by Read the Docs
<https://docs.readthedocs.com/platform/latest/config-file/v2.html#build-tools-python>`_.
@@ -61,7 +76,7 @@
.. code-block:: text
- sphinx-scrapy @ git+https://github.com/scrapy/[email protected]
+ sphinx-scrapy @ git+https://github.com/scrapy/[email protected]
#. Add to ``docs/conf.py``:
@@ -111,7 +126,7 @@
repos:
- repo: https://github.com/scrapy/sphinx-scrapy
- rev: 0.8.6
+ rev: 0.8.12
hooks:
- id: sphinx-scrapy
@@ -121,7 +136,7 @@
[tox]
requires =
- sphinx-scrapy[tox] @
git+https://github.com/scrapy/[email protected]
+ sphinx-scrapy[tox] @
git+https://github.com/scrapy/[email protected]
envlist = …,docs
.. note:: ``docs`` in ``envlist`` is required.
@@ -175,7 +190,9 @@
| `niquests <https://niquests.readthedocs.io/en/latest/>`_
| `packaging <https://packaging.pypa.io/en/stable/>`_
| `parsel <https://parsel.readthedocs.io/en/latest/>`_
+| `platformdirs <https://platformdirs.readthedocs.io/en/latest/>`_
| `pydantic <https://docs.pydantic.dev/latest/>`_
+| `pypug <https://packaging.python.org/en/latest/>`_
| `pytest <https://docs.pytest.org/en/stable/>`_
| `python-scrapinghub <https://python-scrapinghub.readthedocs.io/en/latest/>`_
| `python-zyte-api <https://python-zyte-api.readthedocs.io/en/stable/>`_
@@ -206,4 +223,4 @@
<https://github.com/scrapy/sphinx-scrapy/blob/main/CHANGES.rst>`_ for a list of
releases and their changes.
-.. _sphinx.ext.intersphinx:
https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
\ No newline at end of file
+.. _sphinx.ext.intersphinx:
https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/pyproject.toml
new/sphinx-scrapy-0.8.12/pyproject.toml
--- old/sphinx-scrapy-0.8.6/pyproject.toml 2026-05-12 09:03:58.000000000
+0200
+++ new/sphinx-scrapy-0.8.12/pyproject.toml 2026-08-14 14:28:50.000000000
+0200
@@ -4,9 +4,10 @@
[project]
name = "sphinx-scrapy"
-version = "0.8.6"
+version = "0.8.12"
description = "Sphinx extension for documentation in the Scrapy ecosystem"
dependencies = [
+ "docutils",
"packaging",
"sphinx",
"sphinx-copybutton",
@@ -59,7 +60,7 @@
strict = true
[tool.bumpversion]
-current_version = "0.8.6"
+current_version = "0.8.12"
commit = true
tag = true
tag_name = "{new_version}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/sphinx_scrapy/__init__.py
new/sphinx-scrapy-0.8.12/sphinx_scrapy/__init__.py
--- old/sphinx-scrapy-0.8.6/sphinx_scrapy/__init__.py 2026-05-12
09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/sphinx_scrapy/__init__.py 2026-08-14
14:28:50.000000000 +0200
@@ -1,9 +1,14 @@
from __future__ import annotations
import re
+from functools import cache
from logging import getLogger
+from pathlib import Path
from typing import TYPE_CHECKING
+from docutils import nodes
+from sphinx.util.docutils import SphinxRole
+
from .config import load_project_config, normalize_project_id
if TYPE_CHECKING:
@@ -12,6 +17,8 @@
from sphinx.application import Sphinx
from sphinx.config import Config
+ from .config import ProjectConfig
+
logger = getLogger(__name__)
INTERSPHINX_MAPPING = {
@@ -31,7 +38,9 @@
"niquests": ("https://niquests.readthedocs.io/en/latest/", None),
"packaging": ("https://packaging.pypa.io/en/stable/", None),
"parsel": ("https://parsel.readthedocs.io/en/latest/", None),
+ "platformdirs": ("https://platformdirs.readthedocs.io/en/latest/", None),
"pydantic": ("https://pydantic.dev/docs/validation/latest/", None),
+ "pypug": ("https://packaging.python.org/en/latest/", None),
"pytest": ("https://docs.pytest.org/en/stable/", None),
"python": ("https://docs.python.org/3/", None),
"python-scrapinghub": (
@@ -40,6 +49,7 @@
),
"python-zyte-api": ("https://python-zyte-api.readthedocs.io/en/stable/",
None),
"scrapy": ("https://docs.scrapy.org/en/latest/", None),
+ "scrapy-lint": ("https://scrapy-lint.readthedocs.io/en/latest/", None),
"scrapy-poet": ("https://scrapy-poet.readthedocs.io/en/stable/", None),
"scrapy-spider-metadata": (
"https://scrapy-spider-metadata.readthedocs.io/en/latest/",
@@ -83,6 +93,58 @@
"zyte": False,
}
+# Repositories that :gh: can target by name alone, e.g. :gh:`parsel#12`.
+_GITHUB_OWNERS = {
+ "scrapinghub": (
+ "andi",
+ "dateparser",
+ "extruct",
+ "price-parser",
+ "python-scrapinghub",
+ "scrapy-poet",
+ "scrapyrt",
+ "shub",
+ "spidermon",
+ "web-poet",
+ ),
+ "scrapy": (
+ "cssselect",
+ "form2request",
+ "itemadapter",
+ "itemloaders",
+ "parsel",
+ "protego",
+ "queuelib",
+ "scrapy",
+ "scrapy-lint",
+ "scrapyd",
+ "scrapyd-client",
+ "sphinx-scrapy",
+ "w3lib",
+ ),
+ "scrapy-plugins": (
+ "scrapy-playwright",
+ "scrapy-splash",
+ "scrapy-zyte-api",
+ "scrapy-zyte-smartproxy",
+ ),
+ "zytedata": (
+ "python-zyte-api",
+ "scrapy-spider-metadata",
+ "url-matcher",
+ "zyte-common-items",
+ "zyte-parsers",
+ "zyte-spider-templates",
+ ),
+}
+_GITHUB_REPO_OWNERS = {
+ repo: owner for owner, repos in _GITHUB_OWNERS.items() for repo in repos
+}
+
+_GITHUB_REFERENCE = re.compile(
+ r"(?:(?:(?P<owner>[\w.-]+)/)?(?P<repo>[\w.-]+)#)?(?P<number>\d+)"
+)
+
COPY_AS_MARKDOWN_BUTTON_JS = """
(function () {
@@ -246,12 +308,14 @@
):
app.setup_extension(extension)
+ app.add_role("gh", _GitHubRole())
+
app.connect("builder-inited", add_copy_as_markdown_button)
app.connect("builder-inited", set_better_defaults)
app.connect("config-inited", update_config)
#
https://github.com/scrapy/scrapy/blob/dba37674e6eaa6c2030c8eb35ebf8127cd488062/docs/_ext/scrapydocs.py#L90C16-L110C6
- for crossref_type in ("setting", "signal", "command", "reqmeta"):
+ for crossref_type in ("setting", "signal", "command", "reqmeta", "stat"):
app.add_crossref_type(
directivename=crossref_type,
rolename=crossref_type,
@@ -265,9 +329,55 @@
app.add_js_file(None, body=COPY_AS_MARKDOWN_BUTTON_JS)
+class _GitHubRole(SphinxRole):
+ """Link to a GitHub issue or pull request, given ``123`` for the current
+ repository, or ``repo#123`` or ``owner/repo#123`` for a different one.
+ """
+
+ def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]:
+ current_repo = _project_config(self.env.app.confdir).github_repo or ""
+ match = _GITHUB_REFERENCE.fullmatch(self.text.strip())
+ error = owner = repo = number = ""
+ if not match:
+ error = f"Unsupported GitHub reference: {self.text!r}"
+ else:
+ number = match["number"]
+ repo = match["repo"] or current_repo.partition("/")[2]
+ owner = (
+ match["owner"]
+ or _GITHUB_REPO_OWNERS.get(repo)
+ or current_repo.partition("/")[0]
+ )
+ if not (owner and repo):
+ error = (
+ f"Could not determine the repository of {self.text!r}; use
"
+ f"the owner/repo#number syntax"
+ )
+ elif match["repo"] and f"{owner}/{repo}" == current_repo:
+ error = (
+ f"{self.text!r} targets the current repository; use the "
+ f"number alone"
+ )
+ if error:
+ message = self.inliner.reporter.error(error, line=self.lineno)
+ problem = self.inliner.problematic(self.rawtext, self.rawtext,
message)
+ return [problem], [message]
+ label = (
+ f"#{number}" if f"{owner}/{repo}" == current_repo else
f"{repo}#{number}"
+ )
+ # GitHub redirects the issue URL of a pull request to the pull request.
+ url = f"https://github.com/{owner}/{repo}/issues/{number}"
+ return [nodes.reference(self.rawtext, label, refuri=url)], []
+
+
+@cache
+def _project_config(confdir: str | Path) -> ProjectConfig:
+ return load_project_config(Path(confdir))
+
+
def update_config(app: Sphinx, config: Config) -> None:
configure_intersphinx(config)
- configure_sitemap(config)
+ configure_sitemap(config, _project_config(app.confdir))
def set_better_defaults(app: Sphinx) -> None:
@@ -301,10 +411,9 @@
config.intersphinx_mapping[k] = INTERSPHINX_MAPPING[k]
-def configure_sitemap(config: Config) -> None:
+def configure_sitemap(config: Config, project_config: ProjectConfig) -> None:
if not config.html_baseurl:
package: str | None = None
- project_config = load_project_config()
if project_config.project_id:
package = normalize_project_id(project_config.project_id)
elif hasattr(config, "project"):
@@ -318,7 +427,10 @@
config.html_baseurl = base_url
if not config.html_baseurl.endswith("/"):
config.html_baseurl = config.html_baseurl + "/"
- logger.warning("html_baseurl should end with a slash; automatically
fixed to %r", config.html_baseurl)
+ logger.warning(
+ "html_baseurl should end with a slash; automatically fixed to %r",
+ config.html_baseurl,
+ )
def installed(names: set[str]) -> Generator[str, None, None]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/sphinx_scrapy/cli.py
new/sphinx-scrapy-0.8.12/sphinx_scrapy/cli.py
--- old/sphinx-scrapy-0.8.6/sphinx_scrapy/cli.py 2026-05-12
09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/sphinx_scrapy/cli.py 2026-08-14
14:28:50.000000000 +0200
@@ -1,7 +1,6 @@
from __future__ import annotations
import argparse
-from collections.abc import Callable
import concurrent.futures
import re
import shutil
@@ -19,6 +18,7 @@
from .config import LATEST_RTD_PYTHON_VERSION, load_project_config,
normalize_project_id
if TYPE_CHECKING:
+ from collections.abc import Callable
from pathlib import Path
@@ -48,7 +48,7 @@
def _split_wrapped_markdown_target(target: str) -> tuple[str, str, str]:
- if len(target) >= 2 and target.startswith("<") and target.endswith(">"):
+ if target.startswith("<") and target.endswith(">"):
return "<", target[1:-1], ">"
return "", target, ""
@@ -69,15 +69,12 @@
title = match.group("title") or ""
return (
- f"{match.group('prefix')}"
- f"{rewritten_target}"
- f"{title}"
- f"{match.group('suffix')}"
+
f"{match.group('prefix')}{rewritten_target}{title}{match.group('suffix')}"
)
for line in content.splitlines(keepends=True):
stripped = line.lstrip()
- if stripped.startswith("```") or stripped.startswith("~~~"):
+ if stripped.startswith(("```", "~~~")):
marker = stripped[0]
if not in_fence:
in_fence = True
@@ -102,8 +99,8 @@
docs_host: str,
docs_path_prefix: str,
) -> str:
- wrapper_prefix, wrapped_target, wrapper_suffix = (
- _split_wrapped_markdown_target(target)
+ wrapper_prefix, wrapped_target, wrapper_suffix =
_split_wrapped_markdown_target(
+ target
)
parts = urlsplit(wrapped_target)
@@ -174,7 +171,8 @@
request = Request(probe_url, headers=headers, method=method) # noqa:
S310
try:
with urlopen(request, timeout=5) as response: # noqa: S310
- return HTTPStatus.OK <= response.status <
HTTPStatus.BAD_REQUEST
+ status = int(response.status)
+ return HTTPStatus.OK <= status < HTTPStatus.BAD_REQUEST
except HTTPError as error:
if method == "HEAD" and error.code in {
HTTPStatus.METHOD_NOT_ALLOWED,
@@ -187,7 +185,9 @@
return False
-def _rewrite_url_to_markdown(url: str, enabled_base_urls: set[str], base_urls:
tuple[str, ...]) -> str:
+def _rewrite_url_to_markdown(
+ url: str, enabled_base_urls: set[str], base_urls: tuple[str, ...]
+) -> str:
base_url = _matching_base_url(url, base_urls)
if not base_url or base_url not in enabled_base_urls:
return url
@@ -198,7 +198,9 @@
return url
new_path = f"{path[:-5]}.md"
- return urlunsplit((parts.scheme, parts.netloc, new_path, parts.query,
parts.fragment))
+ return urlunsplit(
+ (parts.scheme, parts.netloc, new_path, parts.query, parts.fragment)
+ )
def _rewrite_intersphinx_links_to_markdown(output_dir: Path) -> None:
@@ -232,9 +234,7 @@
for base_url in candidate_base_urls
}
enabled_base_urls = {
- base_url
- for base_url, future in availability.items()
- if future.result()
+ base_url for base_url, future in availability.items() if
future.result()
}
if not enabled_base_urls:
@@ -258,8 +258,10 @@
return ["-D", "llms_txt_uri_template={docname}.md"]
if builder == "singlemarkdown":
return [
- "-D", "llms_txt_uri_template={docname}.md",
- "-D", "singlemarkdown_flavor=llm",
+ "-D",
+ "llms_txt_uri_template={docname}.md",
+ "-D",
+ "singlemarkdown_flavor=llm",
]
return []
@@ -309,7 +311,9 @@
shutil.copytree(sphinx_build_dir / "html", all_dir, dirs_exist_ok=True)
shutil.copytree(sphinx_build_dir / "markdown", all_dir, dirs_exist_ok=True)
- shutil.copy2(sphinx_build_dir / "singlemarkdown" / "index.md", all_dir /
"llms-full.txt")
+ shutil.copy2(
+ sphinx_build_dir / "singlemarkdown" / "index.md", all_dir /
"llms-full.txt"
+ )
_rewrite_intersphinx_links_to_markdown(all_dir)
_rewrite_llms_links_to_docs_path(all_dir, docs_base_url)
@@ -321,7 +325,7 @@
config = load_project_config()
try:
- config_python_version = Version(config.python_version)
+ config_python_version = Version(str(config.python_version))
except InvalidVersion:
print(
f"Invalid Python version in pyproject.toml:
{config.python_version}",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/sphinx_scrapy/config.py
new/sphinx-scrapy-0.8.12/sphinx_scrapy/config.py
--- old/sphinx-scrapy-0.8.6/sphinx_scrapy/config.py 2026-05-12
09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/sphinx_scrapy/config.py 2026-08-14
14:28:50.000000000 +0200
@@ -1,17 +1,22 @@
from __future__ import annotations
+import re
+import sys
from dataclasses import dataclass, field
from pathlib import Path
+from typing import Any
from packaging.utils import canonicalize_name
-try:
+if sys.version_info >= (3, 11):
import tomllib
-except ModuleNotFoundError:
+else:
import tomli as tomllib
LATEST_RTD_PYTHON_VERSION = "3.14"
+_GITHUB_URL =
re.compile(r"https?://github\.com/(?P<owner>[\w.-]+)/(?P<repo>[\w.-]+)")
+
@dataclass(frozen=True)
class ProjectConfig:
@@ -19,6 +24,7 @@
python_version: str | None = None
extras: set[str] = field(default_factory=set)
project_id: str | None = None
+ github_repo: str | None = None
def find_project_root(start: Path | None = None) -> Path:
@@ -30,27 +36,40 @@
raise FileNotFoundError(msg)
-def get_extras(pyproject_data: dict[str, object]) -> set[str]:
+def get_extras(pyproject_data: dict[str, Any]) -> set[str]:
project_data = pyproject_data.get("project", {})
optional_dependencies = project_data.get("optional-dependencies", {})
return {str(key) for key in optional_dependencies}
+def _get_github_repo(pyproject_data: dict[str, Any]) -> str | None:
+ urls: dict[str, Any] = pyproject_data.get("project", {}).get("urls", {})
+ # Repository URLs first, since other entries may point to a different
+ # repository, e.g. a documentation page hosted elsewhere.
+ keys = sorted(urls, key=lambda key: key.lower() not in {"repository",
"source"})
+ for key in keys:
+ match = _GITHUB_URL.match(str(urls[key]))
+ if match:
+ owner, repo = match.group("owner", "repo")
+ return f"{owner}/{repo.removesuffix('.git')}"
+ return None
+
+
def normalize_project_id(project_id: str) -> str:
return canonicalize_name(project_id.strip())
-def load_project_config(root: Path | None = None) -> ProjectConfig:
- """Load project configuration from a pyproject.toml if available.
+def load_project_config(start: Path | None = None) -> ProjectConfig:
+ """Load project configuration from a :file:`pyproject.toml` if available.
- If no pyproject.toml can be found (starting from ``root`` or CWD),
- return a minimal ``ProjectConfig`` containing only the resolved
- project root and leaving other fields empty/None.
+ The file is searched for in *start* (CWD by default) and its parents. If
+ there is none, return a minimal ``ProjectConfig`` containing only the
+ resolved project root and leaving other fields empty/None.
"""
try:
- project_root = root or find_project_root()
+ project_root = find_project_root(start)
except FileNotFoundError:
- resolved_root = (root or Path.cwd()).resolve()
+ resolved_root = (start or Path.cwd()).resolve()
return ProjectConfig(root=resolved_root)
pyproject_path = project_root / "pyproject.toml"
@@ -71,4 +90,5 @@
python_version=str(python_version) if python_version is not None else
None,
extras=extras,
project_id=project_id,
+ github_repo=_get_github_repo(pyproject_data),
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.6/sphinx_scrapy/tox_plugin.py
new/sphinx-scrapy-0.8.12/sphinx_scrapy/tox_plugin.py
--- old/sphinx-scrapy-0.8.6/sphinx_scrapy/tox_plugin.py 2026-05-12
09:03:58.000000000 +0200
+++ new/sphinx-scrapy-0.8.12/sphinx_scrapy/tox_plugin.py 2026-08-14
14:28:50.000000000 +0200
@@ -5,7 +5,7 @@
from tox.config.loader.memory import MemoryLoader
from tox.plugin import impl
-from .config import load_project_config
+from .config import LATEST_RTD_PYTHON_VERSION, load_project_config
if TYPE_CHECKING:
from tox.config.sets import ConfigSet
@@ -27,7 +27,11 @@
state.conf.memory_seed_loaders["docs"].append(
MemoryLoader(
description="build documentation",
- base_python=_python_executable(project_config.python_version),
+ base_python=[
+ _python_executable(
+ project_config.python_version or LATEST_RTD_PYTHON_VERSION
+ )
+ ],
deps=["-rdocs/requirements.txt"],
extras=tuple(project_config.extras),
commands=["sphinx-scrapy build"],