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-10-26 10:20:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sphinx-scrapy (Old)
and /work/SRC/openSUSE:Factory/.python-sphinx-scrapy.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sphinx-scrapy"
Mon Oct 26 10:20:01 2026 rev:4 rq:1392631 version:0.14.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-sphinx-scrapy/python-sphinx-scrapy.changes
2026-08-22 21:38:29.564261254 +0200
+++
/work/SRC/openSUSE:Factory/.python-sphinx-scrapy.new.2252680/python-sphinx-scrapy.changes
2026-10-26 10:20:11.001467432 +0100
@@ -1,0 +2,75 @@
+Mon Oct 26 07:09:09 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.14.0:
+ * Extended easy Intersphinx configuration to websockets
+ * Intersphinx mappings now point to the documentation of the
+ latest release (/en/stable/) instead of the development
+ version (/en/latest/) for projects that publish it.
+ * The sphinx-scrapy pre-commit hook now also updates Git-based
+ sphinx-scrapy pins, e.g. sphinx-scrapy @
+ git+https://github.com/scrapy/[email protected],
+ turning them into PyPI pins.
+ * sphinx-llm-friendly 0.5.1 or higher is now required.
+ * Enabled sphinx_design and sphinxcontrib.youtube, so their
+ directives, e.g. .. tab-set:: or .. youtube::, work without
+ adding them to extensions, and YouTube videos render as links
+ in the Markdown output.
+ * Extended easy Intersphinx configuration to requests
+ * The sphinx-scrapy pre-commit hook now also updates the
+ sphinx-scrapy pins in :file:`tox.ini` and
+ :file:`docs/requirements.in` to match its rev, so upgrading
+ sphinx-scrapy only takes changing that rev. After
+ :file:`docs/requirements.in` changes, recompile
+ :file:`docs/requirements.txt` with uv pip compile
+ requirements.in -o requirements.txt from the :file:`docs`
+ directory.
+ * Documentation builds now fail on Sphinx warnings. While you
+ fix existing warnings, you can suppress them by type in
+ :file:`docs/conf.py`, or allow all of them in
+ :file:`pyproject.toml` with fail-on-warning = false under
+ [tool.sphinx-scrapy].
+ * Documentation is now built with a regular parallel sphinx-
+ build -b html, which writes the Markdown pages, llms.txt and
+ llms-full.txt next to the HTML pages, in
+ :file:`docs/_build/html` instead of :file:`docs/_build/all`.
+ sphinx-scrapy build and tox -e docs accept an optional output
+ directory, e.g. tox -e docs -- $READTHEDOCS_OUTPUT/html. This
+ is backward-incompatible. To update: Run sphinx-scrapy
+ update-rtd-config to regenerate :file:`.readthedocs.yml`. In
+ app.add_node() calls, drop llm_singlemarkdown= handlers;
+ llm_markdown= handlers cover all Markdown output.
+ * Run sphinx-scrapy update-rtd-config to regenerate
+ :file:`.readthedocs.yml`.
+ * In app.add_node() calls, drop llm_singlemarkdown= handlers;
+ llm_markdown= handlers cover all Markdown output.
+ * Sphinx 8.0.0 or higher is now required, and sphinx-llm-
+ friendly 0.3.0 or higher.
+ * Replaced the Git-based sphinx-llms-txt and sphinx-markdown-
+ builder dependencies with sphinx-llm-friendly, so sphinx-
+ scrapy can be installed from PyPI again, e.g. sphinx-
+ scrapy==0.10.0 in :file:`docs/requirements.txt` and sphinx-
+ scrapy[tox]==0.10.0 in the requires of :file:`tox.ini`. This
+ is backward-incompatible. To update: Rename llms_txt_*
+ settings to their llm_friendly_* counterparts, or drop them
+ where the new defaults cover them, and drop markdown_flavor.
+ Remove "sphinx_llms_txt" from extensions. In app.add_node()
+ calls, rename the markdown= and singlemarkdown= handlers to
+ llm_markdown= and llm_singlemarkdown=. Replace
+ exclude_patterns workarounds that check the builder name with
+ llm_friendly_exclude or llm_friendly_llms_full_txt_exclude.
+ * Rename llms_txt_* settings to their llm_friendly_*
+ counterparts, or drop them where the new defaults cover them,
+ and drop markdown_flavor.
+ * Remove "sphinx_llms_txt" from extensions.
+ * In app.add_node() calls, rename the markdown= and
+ singlemarkdown= handlers to llm_markdown= and
+ llm_singlemarkdown=.
+ * Replace exclude_patterns workarounds that check the builder
+ name with llm_friendly_exclude or
+ llm_friendly_llms_full_txt_exclude.
+ * HTML pages now include an <link rel="alternate"
+ type="text/markdown"> tag pointing to their .md counterpart.
+ * llms-full.txt now includes a Source: line before each page's
+ content.
+
+-------------------------------------------------------------------
Old:
----
sphinx_scrapy-0.8.12.tar.gz
New:
----
sphinx_scrapy-0.14.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-sphinx-scrapy.spec ++++++
--- /var/tmp/diff_new_pack.BgaDSB/_old 2026-10-26 10:20:11.998509190 +0100
+++ /var/tmp/diff_new_pack.BgaDSB/_new 2026-10-26 10:20:12.000509274 +0100
@@ -19,7 +19,7 @@
# Enable libalternatives by default
%bcond_without libalternatives
Name: python-sphinx-scrapy
-Version: 0.8.12
+Version: 0.14.0
Release: 0
Summary: Sphinx extension for documentation in the Scrapy ecosystem
License: BSD-3-Clause
++++++ sphinx_scrapy-0.8.12.tar.gz -> sphinx_scrapy-0.14.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/.github/workflows/publish.yml
new/sphinx-scrapy-0.14.0/.github/workflows/publish.yml
--- old/sphinx-scrapy-0.8.12/.github/workflows/publish.yml 2026-08-14
14:28:50.000000000 +0200
+++ new/sphinx-scrapy-0.14.0/.github/workflows/publish.yml 2026-10-14
12:09:48.000000000 +0200
@@ -14,7 +14,6 @@
jobs:
publish:
- if: false # Cannot be published to PyPI at the moment, see the README.
runs-on: ubuntu-latest
environment:
name: pypi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/CHANGES.rst
new/sphinx-scrapy-0.14.0/CHANGES.rst
--- old/sphinx-scrapy-0.8.12/CHANGES.rst 2026-08-14 14:28:50.000000000
+0200
+++ new/sphinx-scrapy-0.14.0/CHANGES.rst 2026-10-14 12:09:48.000000000
+0200
@@ -2,6 +2,113 @@
Release notes
=============
+0.14.0 (2026-10-14)
+===================
+
+- | Extended easy Intersphinx configuration to
+ | `websockets <https://websockets.readthedocs.io/en/stable/>`_
+
+- Intersphinx mappings now point to the documentation of the latest release
+ (``/en/stable/``) instead of the development version (``/en/latest/``)
+ for projects that publish it.
+
+- The ``sphinx-scrapy`` pre-commit hook now also updates Git-based
+ sphinx-scrapy pins, e.g. ``sphinx-scrapy @
+ git+https://github.com/scrapy/[email protected]``, turning them into
+ PyPI pins.
+
+0.13.0 (2026-09-30)
+===================
+
+- sphinx-llm-friendly 0.5.1 or higher is now required.
+
+- Enabled `sphinx_design <https://sphinx-design.readthedocs.io/en/latest/>`_
+ and `sphinxcontrib.youtube <https://github.com/sphinx-contrib/youtube>`_,
+ so their directives, e.g. ``.. tab-set::`` or ``.. youtube::``, work
+ without adding them to ``extensions``, and YouTube videos render as links
+ in the Markdown output.
+
+- | Extended easy Intersphinx configuration to
+ | `requests <https://docs.python-requests.org/en/stable/>`_
+
+0.12.0 (2026-09-24)
+===================
+
+- The ``sphinx-scrapy`` pre-commit hook now also updates the sphinx-scrapy
+ pins in :file:`tox.ini` and :file:`docs/requirements.in` to match its
+ ``rev``, so upgrading sphinx-scrapy only takes changing that ``rev``.
+
+ After :file:`docs/requirements.in` changes, recompile
+ :file:`docs/requirements.txt` with ``uv pip compile requirements.in -o
+ requirements.txt`` from the :file:`docs` directory.
+
+0.11.0 (2026-09-24)
+===================
+
+- Documentation builds now fail on Sphinx warnings.
+
+ While you fix existing warnings, you can `suppress them by type
+
<https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-suppress_warnings>`_
+ in :file:`docs/conf.py`, or allow all of them in :file:`pyproject.toml`
+ with ``fail-on-warning = false`` under ``[tool.sphinx-scrapy]``.
+
+- Documentation is now built with a regular parallel ``sphinx-build -b
+ html``, which writes the Markdown pages, ``llms.txt`` and
+ ``llms-full.txt`` next to the HTML pages, in :file:`docs/_build/html`
+ instead of :file:`docs/_build/all`.
+
+ ``sphinx-scrapy build`` and ``tox -e docs`` accept an optional output
+ directory, e.g. ``tox -e docs -- $READTHEDOCS_OUTPUT/html``.
+
+ This is backward-incompatible. To update:
+
+ - Run ``sphinx-scrapy update-rtd-config`` to regenerate
+ :file:`.readthedocs.yml`.
+
+ - In ``app.add_node()`` calls, drop ``llm_singlemarkdown=`` handlers;
+ ``llm_markdown=`` handlers cover all Markdown output.
+
+- Sphinx 8.0.0 or higher is now required, and sphinx-llm-friendly 0.3.0 or
+ higher.
+
+0.10.0 (2026-09-24)
+===================
+
+- Replaced the Git-based sphinx-llms-txt and sphinx-markdown-builder
+ dependencies with `sphinx-llm-friendly
+ <https://github.com/scrapy/sphinx-llm-friendly>`_, so sphinx-scrapy can be
+ installed from PyPI again, e.g. ``sphinx-scrapy==0.10.0`` in
+ :file:`docs/requirements.txt` and ``sphinx-scrapy[tox]==0.10.0`` in the
+ ``requires`` of :file:`tox.ini`.
+
+ This is backward-incompatible. To update:
+
+ - Rename ``llms_txt_*`` settings to their ``llm_friendly_*``
+ counterparts, or drop them where the new defaults cover them, and drop
+ ``markdown_flavor``.
+
+ - Remove ``"sphinx_llms_txt"`` from ``extensions``.
+
+ - In ``app.add_node()`` calls, rename the ``markdown=`` and
+ ``singlemarkdown=`` handlers to ``llm_markdown=`` and
+ ``llm_singlemarkdown=``.
+
+ - Replace ``exclude_patterns`` workarounds that check the builder name
+ with ``llm_friendly_exclude`` or
+ ``llm_friendly_llms_full_txt_exclude``.
+
+0.9.0 (2026-08-26)
+==================
+
+- HTML pages now include an ``<link rel="alternate" type="text/markdown">``
+ tag pointing to their ``.md`` counterpart.
+
+0.8.13 (2026-08-25)
+===================
+
+- ``llms-full.txt`` now includes a ``Source:`` line before each page's
+ content.
+
0.8.12 (2026-08-14)
===================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/README.rst
new/sphinx-scrapy-0.14.0/README.rst
--- old/sphinx-scrapy-0.8.12/README.rst 2026-08-14 14:28:50.000000000 +0200
+++ new/sphinx-scrapy-0.14.0/README.rst 2026-10-14 12:09:48.000000000 +0200
@@ -23,6 +23,19 @@
- Generates a `Read the Docs <https://readthedocs.org/>`_ configuration.
+- Keeps the sphinx-scrapy pins of ``tox.ini`` and ``docs/requirements.in``
+ in sync with the pre-commit ``rev``.
+
+- Makes documentation builds fail on Sphinx warnings. While you fix existing
+ warnings, you can either `suppress them by type
+
<https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-suppress_warnings>`_
+ in ``docs/conf.py``, or allow all of them in ``pyproject.toml``:
+
+ .. code-block:: toml
+
+ [tool.sphinx-scrapy]
+ fail-on-warning = false
+
- Enables `commonly-used Sphinx extensions <#sphinx-extensions>`_.
- Configures `sphinx.ext.intersphinx`_ for `Python
@@ -71,12 +84,9 @@
#. Add to ``docs/requirements.txt``:
- Install from Git, because this project currently depends on Git-based
- packages and cannot be published to PyPI:
-
.. code-block:: text
- sphinx-scrapy @ git+https://github.com/scrapy/[email protected]
+ sphinx-scrapy==0.14.0
#. Add to ``docs/conf.py``:
@@ -126,7 +136,7 @@
repos:
- repo: https://github.com/scrapy/sphinx-scrapy
- rev: 0.8.12
+ rev: 0.14.0
hooks:
- id: sphinx-scrapy
@@ -136,7 +146,7 @@
[tox]
requires =
- sphinx-scrapy[tox] @
git+https://github.com/scrapy/[email protected]
+ sphinx-scrapy[tox]==0.14.0
envlist = …,docs
.. note:: ``docs`` in ``envlist`` is required.
@@ -165,7 +175,12 @@
- `sphinx_copybutton <https://sphinx-copybutton.readthedocs.io/en/latest/>`_
-- `sphinx_llms_txt <https://sphinx-llms-txt.readthedocs.io/en/latest/>`_
+- `sphinx_design <https://sphinx-design.readthedocs.io/en/latest/>`_
+
+- `sphinx-llm-friendly <https://github.com/scrapy/sphinx-llm-friendly>`_,
+ which documents the ``llm_friendly_*`` settings
+
+- `sphinxcontrib.youtube <https://github.com/sphinx-contrib/youtube>`_
.. _intersphinx-packages:
@@ -178,43 +193,45 @@
| `attrs <https://www.attrs.org/en/stable/>`_
| `coverage <https://coverage.readthedocs.io/en/latest>`_
| `cryptography <https://cryptography.io/en/latest/>`_
-| `cssselect <https://cssselect.readthedocs.io/en/latest>`_
+| `cssselect <https://cssselect.readthedocs.io/en/stable/>`_
| `curl-cffi <https://curl-cffi.readthedocs.io/en/latest/>`_
-| `dateparser <https://dateparser.readthedocs.io/en/latest/>`_
-| `form2request <https://form2request.readthedocs.io/en/latest/>`_
-| `formasaurus <https://formasaurus.readthedocs.io/en/latest/>`_
-| `itemloaders <https://itemloaders.readthedocs.io/en/latest/>`_
-| `jinja <https://jinja.palletsprojects.com/en/latest/>`_
+| `dateparser <https://dateparser.readthedocs.io/en/stable/>`_
+| `form2request <https://form2request.readthedocs.io/en/stable/>`_
+| `formasaurus <https://formasaurus.readthedocs.io/en/stable/>`_
+| `itemloaders <https://itemloaders.readthedocs.io/en/stable/>`_
+| `jinja <https://jinja.palletsprojects.com/en/stable/>`_
| `lxml <https://lxml.de/apidoc/>`_
-| `multidict <https://multidict.aio-libs.org/en/latest/>`_
+| `multidict <https://multidict.aio-libs.org/en/stable/>`_
| `niquests <https://niquests.readthedocs.io/en/latest/>`_
| `packaging <https://packaging.pypa.io/en/stable/>`_
-| `parsel <https://parsel.readthedocs.io/en/latest/>`_
+| `parsel <https://parsel.readthedocs.io/en/stable/>`_
| `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-scrapinghub <https://python-scrapinghub.readthedocs.io/en/stable/>`_
| `python-zyte-api <https://python-zyte-api.readthedocs.io/en/stable/>`_
+| `requests <https://docs.python-requests.org/en/stable/>`_
| `scrapy-poet <https://scrapy-poet.readthedocs.io/en/stable/>`_
-| `scrapy-spider-metadata
<https://scrapy-spider-metadata.readthedocs.io/en/latest/>`_
-| `scrapy-zyte-api <https://scrapy-zyte-api.readthedocs.io/en/latest/>`_
+| `scrapy-spider-metadata
<https://scrapy-spider-metadata.readthedocs.io/en/stable/>`_
+| `scrapy-zyte-api <https://scrapy-zyte-api.readthedocs.io/en/stable/>`_
| `scrapy-zyte-smartproxy
<https://scrapy-zyte-smartproxy.readthedocs.io/en/latest/>`_
-| `scrapyd <https://scrapyd.readthedocs.io/en/latest/>`_
-| `shub <https://shub.readthedocs.io/en/latest/>`_
-| `shub-image <https://shub-image.readthedocs.io/en/latest/>`_
+| `scrapyd <https://scrapyd.readthedocs.io/en/stable/>`_
+| `shub <https://shub.readthedocs.io/en/stable/>`_
+| `shub-image <https://shub-image.readthedocs.io/en/stable/>`_
| `sphinx <https://www.sphinx-doc.org/en/master>`_
-| `spidermon <https://spidermon.readthedocs.io/en/latest/>`_
+| `spidermon <https://spidermon.readthedocs.io/en/stable/>`_
| `tenacity <https://tenacity.readthedocs.io/en/latest>`_
| `tox <https://tox.wiki/en/latest/>`_
| `twisted <https://docs.twisted.org/en/stable/>`_ (and `twistedapi
<https://docs.twisted.org/en/stable/api/>`_)
| `url-matcher <https://url-matcher.readthedocs.io/en/stable/>`_
-| `w3lib <https://w3lib.readthedocs.io/en/latest/>`_
+| `w3lib <https://w3lib.readthedocs.io/en/stable/>`_
| `web-poet <https://web-poet.readthedocs.io/en/stable/>`_
+| `websockets <https://websockets.readthedocs.io/en/stable/>`_
| `zyte <https://docs.zyte.com>`_
-| `zyte-common-items <https://zyte-common-items.readthedocs.io/en/latest>`_
-| `zyte-parsers <https://zyte-parsers.readthedocs.io/en/latest/>`_
-| `zyte-spider-templates
<https://zyte-spider-templates.readthedocs.io/en/latest>`_
+| `zyte-common-items <https://zyte-common-items.readthedocs.io/en/stable/>`_
+| `zyte-parsers <https://zyte-parsers.readthedocs.io/en/stable/>`_
+| `zyte-spider-templates
<https://zyte-spider-templates.readthedocs.io/en/stable/>`_
Release notes
=============
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/pyproject.toml
new/sphinx-scrapy-0.14.0/pyproject.toml
--- old/sphinx-scrapy-0.8.12/pyproject.toml 2026-08-14 14:28:50.000000000
+0200
+++ new/sphinx-scrapy-0.14.0/pyproject.toml 2026-10-14 12:09:48.000000000
+0200
@@ -4,16 +4,17 @@
[project]
name = "sphinx-scrapy"
-version = "0.8.12"
+version = "0.14.0"
description = "Sphinx extension for documentation in the Scrapy ecosystem"
dependencies = [
"docutils",
"packaging",
- "sphinx",
+ "sphinx>=8.0.0",
"sphinx-copybutton",
- "sphinx-llms-txt @
git+https://github.com/zytedata/sphinx-llms-txt.git@5e8866cb0cc249aa2017ad9050b3b83a7ca16f69",
- "sphinx-markdown-builder @
git+https://github.com/zytedata/sphinx-markdown-builder.git@cfe4c0bfd7b4542f7e6b65a58cdf9ec765829940",
+ "sphinx-design",
+ "sphinx-llm-friendly>=0.5.1",
"sphinx-sitemap",
+ "sphinxcontrib-youtube",
"tomli; python_version < '3.11'",
]
classifiers = [
@@ -53,14 +54,11 @@
[project.optional-dependencies]
tox = ["tox>=4.29.0"]
-[tool.hatch.metadata]
-allow-direct-references = true
-
[tool.mypy]
strict = true
[tool.bumpversion]
-current_version = "0.8.12"
+current_version = "0.14.0"
commit = true
tag = true
tag_name = "{new_version}"
@@ -78,13 +76,13 @@
[[tool.bumpversion.files]]
filename = "README.rst"
-search = "sphinx-scrapy @
git+https://github.com/scrapy/sphinx-scrapy.git@{current_version}"
-replace = "sphinx-scrapy @
git+https://github.com/scrapy/sphinx-scrapy.git@{new_version}"
+search = "sphinx-scrapy=={current_version}"
+replace = "sphinx-scrapy=={new_version}"
[[tool.bumpversion.files]]
filename = "README.rst"
-search = "sphinx-scrapy[tox] @
git+https://github.com/scrapy/sphinx-scrapy.git@{current_version}"
-replace = "sphinx-scrapy[tox] @
git+https://github.com/scrapy/sphinx-scrapy.git@{new_version}"
+search = "sphinx-scrapy[tox]=={current_version}"
+replace = "sphinx-scrapy[tox]=={new_version}"
[tool.ruff.lint]
extend-select = [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/sphinx_scrapy/__init__.py
new/sphinx-scrapy-0.14.0/sphinx_scrapy/__init__.py
--- old/sphinx-scrapy-0.8.12/sphinx_scrapy/__init__.py 2026-08-14
14:28:50.000000000 +0200
+++ new/sphinx-scrapy-0.14.0/sphinx_scrapy/__init__.py 2026-10-14
12:09:48.000000000 +0200
@@ -16,6 +16,7 @@
from sphinx.application import Sphinx
from sphinx.config import Config
+ from sphinx.util.typing import ExtensionMetadata
from .config import ProjectConfig
@@ -26,57 +27,59 @@
"attrs": ("https://www.attrs.org/en/stable/", None),
"coverage": ("https://coverage.readthedocs.io/en/latest/", None),
"cryptography": ("https://cryptography.io/en/latest/", None),
- "cssselect": ("https://cssselect.readthedocs.io/en/latest/", None),
+ "cssselect": ("https://cssselect.readthedocs.io/en/stable/", None),
"curl-cffi": ("https://curl-cffi.readthedocs.io/en/latest/", None),
- "dateparser": ("https://dateparser.readthedocs.io/en/latest/", None),
- "form2request": ("https://form2request.readthedocs.io/en/latest/", None),
- "formasaurus": ("https://formasaurus.readthedocs.io/en/latest/", None),
- "itemloaders": ("https://itemloaders.readthedocs.io/en/latest/", None),
- "jinja": ("https://jinja.palletsprojects.com/en/latest/", None),
+ "dateparser": ("https://dateparser.readthedocs.io/en/stable/", None),
+ "form2request": ("https://form2request.readthedocs.io/en/stable/", None),
+ "formasaurus": ("https://formasaurus.readthedocs.io/en/stable/", None),
+ "itemloaders": ("https://itemloaders.readthedocs.io/en/stable/", None),
+ "jinja": ("https://jinja.palletsprojects.com/en/stable/", None),
"lxml": ("https://lxml.de/apidoc/", None),
- "multidict": ("https://multidict.aio-libs.org/en/latest/", None),
+ "multidict": ("https://multidict.aio-libs.org/en/stable/", None),
"niquests": ("https://niquests.readthedocs.io/en/latest/", None),
"packaging": ("https://packaging.pypa.io/en/stable/", None),
- "parsel": ("https://parsel.readthedocs.io/en/latest/", None),
+ "parsel": ("https://parsel.readthedocs.io/en/stable/", 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": (
- "https://python-scrapinghub.readthedocs.io/en/latest/",
+ "https://python-scrapinghub.readthedocs.io/en/stable/",
None,
),
"python-zyte-api": ("https://python-zyte-api.readthedocs.io/en/stable/",
None),
+ "requests": ("https://docs.python-requests.org/en/stable/", None),
"scrapy": ("https://docs.scrapy.org/en/latest/", None),
- "scrapy-lint": ("https://scrapy-lint.readthedocs.io/en/latest/", None),
+ "scrapy-lint": ("https://scrapy-lint.readthedocs.io/en/stable/", None),
"scrapy-poet": ("https://scrapy-poet.readthedocs.io/en/stable/", None),
"scrapy-spider-metadata": (
- "https://scrapy-spider-metadata.readthedocs.io/en/latest/",
+ "https://scrapy-spider-metadata.readthedocs.io/en/stable/",
None,
),
- "scrapy-zyte-api": ("https://scrapy-zyte-api.readthedocs.io/en/latest/",
None),
+ "scrapy-zyte-api": ("https://scrapy-zyte-api.readthedocs.io/en/stable/",
None),
"scrapy-zyte-smartproxy": (
"https://scrapy-zyte-smartproxy.readthedocs.io/en/latest/",
None,
),
- "scrapyd": ("https://scrapyd.readthedocs.io/en/latest/", None),
- "shub": ("https://shub.readthedocs.io/en/latest/", None),
- "shub-image": ("https://shub-image.readthedocs.io/en/latest/", None),
+ "scrapyd": ("https://scrapyd.readthedocs.io/en/stable/", None),
+ "shub": ("https://shub.readthedocs.io/en/stable/", None),
+ "shub-image": ("https://shub-image.readthedocs.io/en/stable/", None),
"sphinx": ("https://www.sphinx-doc.org/en/master/", None),
- "spidermon": ("https://spidermon.readthedocs.io/en/latest/", None),
+ "spidermon": ("https://spidermon.readthedocs.io/en/stable/", None),
"tenacity": ("https://tenacity.readthedocs.io/en/latest/", None),
"tox": ("https://tox.wiki/en/latest/", None),
"twisted": ("https://docs.twisted.org/en/stable/", None),
"twistedapi": ("https://docs.twisted.org/en/stable/api/", None),
- "url-matcher": ("https://url-matcher.readthedocs.io/en/latest/", None),
- "w3lib": ("https://w3lib.readthedocs.io/en/latest/", None),
+ "url-matcher": ("https://url-matcher.readthedocs.io/en/stable/", None),
+ "w3lib": ("https://w3lib.readthedocs.io/en/stable/", None),
"web-poet": ("https://web-poet.readthedocs.io/en/stable/", None),
+ "websockets": ("https://websockets.readthedocs.io/en/stable/", None),
"zyte": ("https://docs.zyte.com/", None),
- "zyte-common-items":
("https://zyte-common-items.readthedocs.io/en/latest/", None),
- "zyte-parsers": ("https://zyte-parsers.readthedocs.io/en/latest/", None),
+ "zyte-common-items":
("https://zyte-common-items.readthedocs.io/en/stable/", None),
+ "zyte-parsers": ("https://zyte-parsers.readthedocs.io/en/stable/", None),
"zyte-spider-templates": (
- "https://zyte-spider-templates.readthedocs.io/en/latest/",
+ "https://zyte-spider-templates.readthedocs.io/en/stable/",
None,
),
}
@@ -146,148 +149,7 @@
)
-COPY_AS_MARKDOWN_BUTTON_JS = """
-(function () {
- var DEFAULT_LABEL = 'M\u2193';
- var SUCCESS_LABEL = 'Copied';
- var ERROR_LABEL = 'Error';
-
- function markdownPathFromCurrentPage(pathname) {
- if (pathname.endsWith('.html')) {
- return pathname.slice(0, -5) + '.md';
- }
- if (pathname.endsWith('/')) {
- return pathname + 'index.md';
- }
- var lastPart = pathname.split('/').pop() || '';
- if (!lastPart.includes('.')) {
- return pathname + '.md';
- }
- return pathname + '.md';
- }
-
- async function copyToClipboard(text) {
- if (navigator.clipboard && window.isSecureContext) {
- await navigator.clipboard.writeText(text);
- return;
- }
- var textarea = document.createElement('textarea');
- textarea.value = text;
- textarea.setAttribute('readonly', 'readonly');
- textarea.style.position = 'fixed';
- textarea.style.left = '-9999px';
- document.body.appendChild(textarea);
- textarea.select();
- document.execCommand('copy');
- document.body.removeChild(textarea);
- }
-
- function setTemporaryLabel(button, label, previousLabel) {
- var prev = typeof previousLabel !== 'undefined' ? previousLabel :
button.textContent;
- button.textContent = label;
- window.setTimeout(function () {
- button.textContent = prev;
- button.disabled = false;
- }, 1000);
- }
-
- async function onButtonClick(button) {
- var previousLabel = button.textContent;
- button.disabled = true;
- button.textContent = '...';
- try {
- var mdPath = markdownPathFromCurrentPage(window.location.pathname);
- var response = await fetch(mdPath, { credentials: 'same-origin' });
- if (!response.ok) {
- throw new Error('Unable to fetch markdown source');
- }
- var markdown = await response.text();
- await copyToClipboard(markdown);
- setTemporaryLabel(button, SUCCESS_LABEL, previousLabel);
- } catch (_error) {
- setTemporaryLabel(button, ERROR_LABEL, previousLabel);
- }
- }
-
- function addStyles() {
- var style = document.createElement('style');
- style.textContent = [
- '.scrapy-copy-as-markdown {',
- ' display: inline-block;',
- ' margin-left: 0.25rem;',
- ' border: 1px solid #c9d4de;',
- ' border-radius: 0.45rem;',
- ' background: #ffffff;',
- ' color: #233a50;',
- ' font: inherit;',
- ' font-size: 0.875rem;',
- ' line-height: 1;',
- ' padding: 0.25rem 0.25rem;',
- ' box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);',
- ' cursor: pointer;',
- '}',
- '.scrapy-copy-as-markdown:hover {',
- ' background: #f3f7fb;',
- '}',
- '.scrapy-copy-as-markdown:disabled {',
- ' opacity: 0.75;',
- ' cursor: default;',
- '}',
- '.scrapy-copy-as-markdown-title-wrapper {',
- ' display: flex;',
- ' align-items: center;',
- ' justify-content: space-between;',
- ' gap: 1rem;',
- ' width: 100%;',
- '}',
- '.scrapy-copy-as-markdown-title-wrapper h1 {',
- ' margin: 0;',
- '}',
- ].join('\\n');
- document.head.appendChild(style);
- }
-
- function addButton() {
- if (!document.body ||
document.querySelector('.scrapy-copy-as-markdown')) {
- return;
- }
-
- addStyles();
- var button = document.createElement('button');
- button.type = 'button';
- button.className = 'scrapy-copy-as-markdown';
- button.title = 'Copy this page as Markdown';
- button.setAttribute('aria-label', 'Copy this page as Markdown');
- button.textContent = DEFAULT_LABEL;
- button.addEventListener('click', function () {
- onButtonClick(button);
- });
-
- var h1 = document.querySelector('#main h1') ||
document.querySelector('h1');
- if (h1 && h1.parentNode) {
- var parent = h1.parentNode;
- var wrapper = document.createElement('div');
- wrapper.className = 'scrapy-copy-as-markdown-title-wrapper';
- parent.replaceChild(wrapper, h1);
- wrapper.appendChild(h1);
- wrapper.appendChild(button);
- } else {
- // fallback: insert at top of body but keep within the first
container
- var container = document.body.firstElementChild || document.body;
- container.insertBefore(button, container.firstChild);
- }
- }
-
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', addButton);
- } else {
- addButton();
- }
-})();
-"""
-
-
-def setup(app: Sphinx) -> None:
+def setup(app: Sphinx) -> ExtensionMetadata:
app.add_config_value(
"scrapy_intersphinx_enable", [], "env", types=frozenset({list})
)
@@ -303,14 +165,15 @@
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
"sphinx_copybutton",
- "sphinx_llms_txt",
+ "sphinx_design",
+ "sphinx_llm_friendly",
"sphinx_sitemap",
+ "sphinxcontrib.youtube",
):
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)
@@ -322,11 +185,7 @@
indextemplate=f"pair: %s; {crossref_type}",
)
-
-def add_copy_as_markdown_button(app: Sphinx) -> None:
- if app.builder.format != "html":
- return
- app.add_js_file(None, body=COPY_AS_MARKDOWN_BUTTON_JS)
+ return {"parallel_read_safe": True}
class _GitHubRole(SphinxRole):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/sphinx_scrapy/cli.py
new/sphinx-scrapy-0.14.0/sphinx_scrapy/cli.py
--- old/sphinx-scrapy-0.8.12/sphinx_scrapy/cli.py 2026-08-14
14:28:50.000000000 +0200
+++ new/sphinx-scrapy-0.14.0/sphinx_scrapy/cli.py 2026-10-14
12:09:48.000000000 +0200
@@ -1,324 +1,37 @@
from __future__ import annotations
import argparse
-import concurrent.futures
import re
-import shutil
import sys
-from http import HTTPStatus
-from typing import TYPE_CHECKING
-from urllib.error import HTTPError, URLError
-from urllib.parse import urlsplit, urlunsplit
-from urllib.request import Request, urlopen
+from importlib.metadata import version
+from pathlib import Path
from packaging.version import InvalidVersion, Version
-from sphinx.cmd.build import main as sphinx_build_main
+from sphinx.cmd.build import main as sphinx_build
-from . import INTERSPHINX_MAPPING
-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
-
-
-URL_PATTERN = re.compile(r"https?://[^\s<>()\[\]{}\"']+")
-MARKDOWN_LINK_PATTERN = re.compile(
- r"(?P<prefix>!?\[[^\]]*\]\()"
- r"(?P<target>[^)\s]+)"
- r"(?P<title>\s+\"[^\"]*\")?"
- r"(?P<suffix>\))"
-)
-
-
-def _intersphinx_base_urls() -> tuple[str, ...]:
- bases = {url for url, _inventory in INTERSPHINX_MAPPING.values()}
- return tuple(sorted(bases, key=len, reverse=True))
-
-
-def _project_docs_base_url(project_id: str | None) -> str | None:
- if not project_id:
- return None
- normalized_project_id = normalize_project_id(project_id)
- if not normalized_project_id:
- return None
- if normalized_project_id in INTERSPHINX_MAPPING:
- return INTERSPHINX_MAPPING[normalized_project_id][0]
- return f"https://{normalized_project_id}.readthedocs.io/en/latest/"
-
-
-def _split_wrapped_markdown_target(target: str) -> tuple[str, str, str]:
- if target.startswith("<") and target.endswith(">"):
- return "<", target[1:-1], ">"
- return "", target, ""
-
-
-def _rewrite_markdown_links(
- content: str,
- rewrite_target: Callable[[str], str],
-) -> str:
- in_fence = False
- fence_char = ""
- rewritten_lines: list[str] = []
-
- def replacement(match: re.Match[str]) -> str:
- target = match.group("target")
- rewritten_target = rewrite_target(target)
- if rewritten_target == target:
- return match.group(0)
-
- title = match.group("title") or ""
- return (
-
f"{match.group('prefix')}{rewritten_target}{title}{match.group('suffix')}"
- )
-
- for line in content.splitlines(keepends=True):
- stripped = line.lstrip()
- if stripped.startswith(("```", "~~~")):
- marker = stripped[0]
- if not in_fence:
- in_fence = True
- fence_char = marker
- elif marker == fence_char:
- in_fence = False
- fence_char = ""
- rewritten_lines.append(line)
- continue
-
- if in_fence:
- rewritten_lines.append(line)
- continue
-
- rewritten_lines.append(MARKDOWN_LINK_PATTERN.sub(replacement, line))
-
- return "".join(rewritten_lines)
-
-
-def _rewrite_llms_link_target(
- target: str,
- docs_host: str,
- docs_path_prefix: str,
-) -> str:
- wrapper_prefix, wrapped_target, wrapper_suffix =
_split_wrapped_markdown_target(
- target
- )
- parts = urlsplit(wrapped_target)
-
- if parts.scheme or parts.netloc:
- if parts.scheme not in {"http", "https"}:
- return target
- if parts.netloc.lower() != docs_host:
- return target
-
- if not parts.path.endswith(".md"):
- return target
-
- clean_path = parts.path.lstrip("/")
- while clean_path.startswith("./"):
- clean_path = clean_path[2:]
- if clean_path.startswith("../"):
- return target
-
- if docs_path_prefix and not clean_path.startswith(docs_path_prefix):
- clean_path = f"{docs_path_prefix}{clean_path}"
-
- rewritten_target = urlunsplit(("", "", clean_path, parts.query,
parts.fragment))
- return f"{wrapper_prefix}{rewritten_target}{wrapper_suffix}"
-
-
-def _rewrite_llms_links_to_docs_path(
- output_dir: Path,
- docs_base_url: str | None,
-) -> None:
- llms_path = output_dir / "llms.txt"
- if docs_base_url is None or not llms_path.is_file():
- return
-
- docs_parts = urlsplit(docs_base_url)
- docs_host = docs_parts.netloc.lower()
- docs_path = docs_parts.path.strip("/")
- docs_path_prefix = f"{docs_path}/" if docs_path else ""
-
- content = llms_path.read_text(encoding="utf-8")
- rewritten = _rewrite_markdown_links(
- content,
- lambda target: _rewrite_llms_link_target(target, docs_host,
docs_path_prefix),
- )
- if rewritten != content:
- llms_path.write_text(rewritten, encoding="utf-8")
-
-
-def _iter_markdown_outputs(output_dir: Path) -> list[Path]:
- files = sorted(output_dir.rglob("*.md"))
- for filename in ("llms.txt", "llms-full.txt"):
- path = output_dir / filename
- if path.is_file():
- files.append(path)
- return files
-
-
-def _matching_base_url(url: str, base_urls: tuple[str, ...]) -> str | None:
- for base_url in base_urls:
- if url.startswith(base_url):
- return base_url
- return None
-
-
-def _supports_markdown(base_url: str) -> bool:
- probe_url = f"{base_url.rstrip('/')}/index.md"
- headers = {"User-Agent": "sphinx-scrapy"}
- for method in ("HEAD", "GET"):
- request = Request(probe_url, headers=headers, method=method) # noqa:
S310
- try:
- with urlopen(request, timeout=5) as response: # noqa: S310
- 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,
- HTTPStatus.NOT_IMPLEMENTED,
- }:
- continue
- return False
- except URLError:
- return False
- return False
-
-
-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
-
- parts = urlsplit(url)
- path = parts.path
- if not path.endswith(".html"):
- return url
- new_path = f"{path[:-5]}.md"
-
- return urlunsplit(
- (parts.scheme, parts.netloc, new_path, parts.query, parts.fragment)
- )
-
-
-def _rewrite_intersphinx_links_to_markdown(output_dir: Path) -> None:
- target_files = _iter_markdown_outputs(output_dir)
- if not target_files:
- return
-
- base_urls = _intersphinx_base_urls()
- file_contents: dict[Path, str] = {}
- candidate_base_urls: set[str] = set()
-
- for file in target_files:
- content = file.read_text(encoding="utf-8")
- file_contents[file] = content
- for match in URL_PATTERN.finditer(content):
- url = match.group(0)
- if ".html" not in url:
- continue
- base_url = _matching_base_url(url, base_urls)
- if base_url is not None:
- candidate_base_urls.add(base_url)
-
- if not candidate_base_urls:
- return
-
- with concurrent.futures.ThreadPoolExecutor(
- max_workers=min(8, len(candidate_base_urls))
- ) as executor:
- availability = {
- base_url: executor.submit(_supports_markdown, base_url)
- for base_url in candidate_base_urls
- }
- enabled_base_urls = {
- base_url for base_url, future in availability.items() if
future.result()
- }
-
- if not enabled_base_urls:
- return
-
- for file, content in file_contents.items():
- rewritten = URL_PATTERN.sub(
- lambda match: _rewrite_url_to_markdown(
- match.group(0),
- enabled_base_urls,
- base_urls,
- ),
- content,
- )
- if rewritten != content:
- file.write_text(rewritten, encoding="utf-8")
+from .config import LATEST_RTD_PYTHON_VERSION, load_project_config
-def _builder_settings(builder: str) -> list[str]:
- if builder == "html":
- return ["-D", "llms_txt_uri_template={docname}.md"]
- if builder == "singlemarkdown":
- return [
- "-D",
- "llms_txt_uri_template={docname}.md",
- "-D",
- "singlemarkdown_flavor=llm",
- ]
- return []
-
-
-def _run_builder(builder: str, source_dir: Path, build_dir: Path) -> None:
- args = [
- "-b",
- builder,
- *_builder_settings(builder),
- str(source_dir),
- str(build_dir / builder),
- ]
- exit_code = sphinx_build_main(args)
- if exit_code != 0:
- msg = f"sphinx builder failed for '{builder}' with exit code
{exit_code}"
- raise RuntimeError(msg)
-
-
-def build_docs() -> int:
+def build_docs(output_dir: Path | None) -> int:
config = load_project_config()
- docs_base_url = _project_docs_base_url(config.project_id)
docs_dir = config.root / "docs"
if not docs_dir.is_dir():
print("docs directory not found", file=sys.stderr)
return 1
-
- sphinx_build_dir = docs_dir / "_build"
- sphinx_build_dir.mkdir(parents=True, exist_ok=True)
-
- builders = ["html", "markdown", "singlemarkdown"]
-
- with concurrent.futures.ProcessPoolExecutor(max_workers=len(builders)) as
executor:
- futures = [
- executor.submit(
- _run_builder,
- builder,
- docs_dir,
- sphinx_build_dir,
- )
- for builder in builders
- ]
- for future in concurrent.futures.as_completed(futures):
- future.result()
-
- all_dir = sphinx_build_dir / "all"
- all_dir.mkdir(parents=True, exist_ok=True)
-
- 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"
- )
- _rewrite_intersphinx_links_to_markdown(all_dir)
- _rewrite_llms_links_to_docs_path(all_dir, docs_base_url)
-
- print("\nDocumentation generated in docs/_build/all.")
- return 0
+ build_dir = docs_dir / "_build"
+ args = [
+ "-b",
+ "html",
+ "-d",
+ str(build_dir / "doctrees"),
+ "-j",
+ "auto",
+ str(docs_dir),
+ str(output_dir or build_dir / "html"),
+ ]
+ if config.fail_on_warning:
+ args += ["-W", "--keep-going"]
+ return sphinx_build(args)
def update_rtd_config() -> int:
@@ -353,22 +66,39 @@
f' python: "{config.python_version}"',
" commands:",
" - pip install tox",
- " - tox -e docs",
- " - mkdir -p $READTHEDOCS_OUTPUT/html",
- " - cp -a docs/_build/all/. $READTHEDOCS_OUTPUT/html/",
+ " - tox -e docs -- $READTHEDOCS_OUTPUT/html",
"",
]
),
encoding="utf-8",
)
print("Updated .readthedocs.yml")
+
+ pin = rf"\g<1>=={version('sphinx-scrapy')}"
+ for path in ("tox.ini", "docs/requirements.in"):
+ file = config.root / path
+ if not file.is_file():
+ continue
+ text = file.read_text(encoding="utf-8")
+ new_text = re.sub(
+ r"(sphinx-scrapy(?:\[tox\])?)(?:==\S+|\s*@\s*git\+\S+)", pin, text
+ )
+ if new_text != text:
+ file.write_text(new_text, encoding="utf-8")
+ print(f"Updated {path}")
+ if path == "docs/requirements.in":
+ print(
+ "Run `uv pip compile requirements.in -o requirements.txt` "
+ "from docs/"
+ )
return 0
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="sphinx-scrapy")
subparsers = parser.add_subparsers(dest="command", required=True)
- subparsers.add_parser("build")
+ build_parser = subparsers.add_parser("build")
+ build_parser.add_argument("output_dir", nargs="?", type=Path)
subparsers.add_parser("update-rtd-config")
return parser
@@ -377,7 +107,7 @@
parser = build_parser()
args = parser.parse_args(argv)
if args.command == "build":
- return build_docs()
+ return build_docs(args.output_dir)
if args.command == "update-rtd-config":
return update_rtd_config()
parser.error(f"Unknown command: {args.command}")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/sphinx_scrapy/config.py
new/sphinx-scrapy-0.14.0/sphinx_scrapy/config.py
--- old/sphinx-scrapy-0.8.12/sphinx_scrapy/config.py 2026-08-14
14:28:50.000000000 +0200
+++ new/sphinx-scrapy-0.14.0/sphinx_scrapy/config.py 2026-10-14
12:09:48.000000000 +0200
@@ -25,6 +25,7 @@
extras: set[str] = field(default_factory=set)
project_id: str | None = None
github_repo: str | None = None
+ fail_on_warning: bool = True
def find_project_root(start: Path | None = None) -> Path:
@@ -78,6 +79,7 @@
tool_data = pyproject_data.get("tool", {})
scrapy_data = tool_data.get("sphinx-scrapy", {})
python_version = scrapy_data.get("python-version",
LATEST_RTD_PYTHON_VERSION)
+ fail_on_warning = bool(scrapy_data.get("fail-on-warning", True))
extras = get_extras(pyproject_data)
raw_project_id = pyproject_data.get("project", {}).get("name")
project_id = None
@@ -91,4 +93,5 @@
extras=extras,
project_id=project_id,
github_repo=_get_github_repo(pyproject_data),
+ fail_on_warning=fail_on_warning,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sphinx-scrapy-0.8.12/sphinx_scrapy/tox_plugin.py
new/sphinx-scrapy-0.14.0/sphinx_scrapy/tox_plugin.py
--- old/sphinx-scrapy-0.8.12/sphinx_scrapy/tox_plugin.py 2026-08-14
14:28:50.000000000 +0200
+++ new/sphinx-scrapy-0.14.0/sphinx_scrapy/tox_plugin.py 2026-10-14
12:09:48.000000000 +0200
@@ -3,6 +3,7 @@
from typing import TYPE_CHECKING
from tox.config.loader.memory import MemoryLoader
+from tox.config.types import Command
from tox.plugin import impl
from .config import LATEST_RTD_PYTHON_VERSION, load_project_config
@@ -34,6 +35,8 @@
],
deps=["-rdocs/requirements.txt"],
extras=tuple(project_config.extras),
- commands=["sphinx-scrapy build"],
+ commands=[
+ Command(["sphinx-scrapy", "build", *(state.conf.pos_args(None)
or ())])
+ ],
)
)