Skip to content

Commit dc3264c

Browse files
authored
Merge of #11382
2 parents e6a93b2 + d90837c commit dc3264c

File tree

13 files changed

+568
-107
lines changed

13 files changed

+568
-107
lines changed

.github/workflows/users-guide.yml

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ on:
1414
paths:
1515
- 'doc/Makefile'
1616
- 'doc/pyproject.toml'
17-
- 'doc/requirements.in'
1817
- 'doc/*.inc'
1918
- 'doc/*.py'
2019
- 'doc/*.rst'
@@ -24,7 +23,6 @@ on:
2423
paths:
2524
- 'doc/Makefile'
2625
- 'doc/pyproject.toml'
27-
- 'doc/requirements.in'
2826
- 'doc/*.inc'
2927
- 'doc/*.py'
3028
- 'doc/*.rst'
@@ -56,18 +54,8 @@ jobs:
5654
with:
5755
python-version: ${{ matrix.python-version }}
5856

59-
- name: Install pip-compile
60-
run: |
61-
pip install pip-tools
62-
63-
- name: Create requirements.txt from requirements.in
64-
run: |
65-
make users-guide-requirements
66-
67-
# Subsumed by make users-guide
68-
# - name: Install dependencies
69-
# run: |
70-
# pip install -r doc/requirements.txt
57+
- name: Install the latest version of uv
58+
uses: astral-sh/setup-uv@v7
7159

7260
- name: Build User's Guide in HTML
7361
run: |
@@ -78,7 +66,7 @@ jobs:
7866
name: users-guide-html
7967
path: html/
8068

81-
- name: Check security of requirements.txt
69+
- name: Check security of requirements (dependencies)
8270
env:
8371
SKJOLD_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8472
run: |

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ cabal-testsuite/**/haddocks
9191
venv
9292
.venv
9393
/doc/.skjold_cache/
94-
/doc/requirements.txt
9594

9695
# macOS folder metadata
9796
.DS_Store

.readthedocs.yml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ build:
88
tools:
99
python: "3.13"
1010
jobs:
11-
post_create_environment:
12-
- pip install pip-tools
13-
- make users-guide-requirements
14-
15-
python:
16-
install:
17-
- requirements: doc/requirements.txt
11+
pre_create_environment:
12+
- asdf plugin add uv
13+
- asdf install uv latest
14+
- asdf global uv latest
15+
install:
16+
- uv sync --project doc
17+
build:
18+
html:
19+
- uv run --project doc sphinx-build -n -W --keep-going -E -T -d _build/doctrees -D language=en doc "${READTHEDOCS_OUTPUT}/html"

Makefile

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,6 @@ bootstrap-jsons: $(BOOTSTRAP_GHC_VERSIONS:%=bootstrap-json-%)
286286
users-guide: ## Build the users guide.
287287
$(MAKE) -C doc users-guide
288288

289-
.PHONY: users-guide-requirements
290-
users-guide-requirements: ## Install the requirements for building the users guide.
291-
$(MAKE) -C doc users-guide-requirements
292-
293289
ifeq ($(shell uname), Darwin)
294290
PROCS := $(shell sysctl -n hw.logicalcpu)
295291
else

changelog.d/11382.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
synopsis: Replace pip with uv for building users guide
3+
packages: [cabal-install]
4+
prs: 11382
5+
---
6+
7+
Aside from being faster, by using uv to build the user guide:
8+
9+
* We don't have to explicitly activate a python virtual environment, either in the shell or in our makefile.
10+
* A clean git clone can `make users-guide` without first `make users-guide-requirements`.
11+
* We require fewer variables, targets and recipes in the the makefiles.
12+
* The `make users-guide` recipe output is much shorter as it doesn't include lengthy pip output.

doc/Makefile

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,27 @@
1212
#
1313
#
1414
SKJOLD_GITHUB_API_TOKEN ?= ${GITHUB_TOKEN}
15-
# TODO: when we have sphinx-build2 ?
16-
SPHINXCMD:=sphinx-build
1715
# Flag -n ("nitpick") warns about broken references
1816
# Flag -W turns warnings into errors
1917
# Flag --keep-going continues after errors
2018
SPHINX_FLAGS:=-n -W --keep-going -E
2119
SPHINX_HTML_OUTDIR:=../dist-newstyle/doc/users-guide
2220
USERGUIDE_STAMP:=$(SPHINX_HTML_OUTDIR)/index.html
23-
PYTHON_VIRTUALENV_ACTIVATE:=../.python-sphinx-virtualenv/bin/activate
24-
25-
# Python virtual environment
26-
##############################################################################
27-
28-
# Create a python virtual environment in the root of the cabal repository.
29-
$(PYTHON_VIRTUALENV_ACTIVATE):
30-
python3 -m venv ../.python-sphinx-virtualenv
31-
(. $(PYTHON_VIRTUALENV_ACTIVATE))
3221

3322
# Users guide
3423
##############################################################################
3524

36-
# do pip install every time so we have up to date requirements when we build
37-
users-guide: $(PYTHON_VIRTUALENV_ACTIVATE) $(USERGUIDE_STAMP)
25+
users-guide: $(USERGUIDE_STAMP)
3826
$(USERGUIDE_STAMP) : *.rst
39-
mkdir -p $(SPHINX_HTML_OUTDIR)
40-
(. $(PYTHON_VIRTUALENV_ACTIVATE) && pip install -r requirements.txt && $(SPHINXCMD) $(SPHINX_FLAGS) . $(SPHINX_HTML_OUTDIR))
27+
mkdir -p $(SPHINX_HTML_OUTDIR) \
28+
&& uv sync \
29+
&& uv run sphinx-build $(SPHINX_FLAGS) . $(SPHINX_HTML_OUTDIR)
4130

4231
# Requirements
4332
##############################################################################
4433

45-
##
46-
# This goal is intended for manual invocation, always rebuilds.
47-
.PHONY: users-guide-requirements
48-
users-guide-requirements: requirements.txt
49-
50-
.PHONY: build-and-check-requirements
51-
build-and-check-requirements: requirements.txt check-requirements
52-
53-
# Always rebuild requirements.txt
54-
.PHONY: requirements.txt
55-
# requirements.txt is generated from requirements.in
56-
# via pip-compile included in the pip-tools package.
57-
# See https://modelpredict.com/wht-requirements-txt-is-not-enough
58-
requirements.txt: requirements.in $(PYTHON_VIRTUALENV_ACTIVATE)
59-
. $(PYTHON_VIRTUALENV_ACTIVATE) \
60-
&& pip install --upgrade 'pip!=25.3' \
61-
&& pip install pip-tools \
62-
&& pip-compile requirements.in
34+
requirements.txt:
35+
uv export --frozen --format requirements.txt > requirements.txt
6336

6437
# Check requirements.txt for security violations via skjold,
6538
# configured in pyproject.toml.
@@ -71,10 +44,8 @@ check-requirements:
7144
echo "WARNING: Neither SKJOLD_GITHUB_API_TOKEN nor GITHUB_TOKEN is set." \
7245
; echo "Vulnerability check via skjold might fail when using the GitHub GraphQL API." \
7346
; fi
74-
. $(PYTHON_VIRTUALENV_ACTIVATE) \
75-
&& pip install skjold \
76-
&& skjold audit
77-
# NB: For portability, we use '.' (sh etc.) instead of 'source' (bash).
47+
uvx skjold -c pyproject.toml config \
48+
&& uv pip list --format freeze | uvx skjold -c pyproject.toml audit
7849

7950
# Debug print environment variables
8051
debug:

doc/README.md

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ http://cabal.readthedocs.io/
1111

1212
### How to build it
1313

14-
Building the documentation requires Python 3, PIP, and `pip-tools` (see the second note below for how to install it). Run the following command either from the root of the cabal repository or from the `docs/` subdirectory:
14+
Building the documentation requires uv and Python 3. Run the following command
15+
either from the root of the cabal repository or from the `docs/` subdirectory:
1516

1617
``` console
1718
> make users-guide
@@ -20,25 +21,37 @@ Building the documentation requires Python 3, PIP, and `pip-tools` (see the seco
2021
Note: Python on Mac OS X dislikes `LC_CTYPE=UTF-8`, so unset the variable
2122
and instead set `LC_ALL=en_US.UTF-8`.
2223

23-
Note: You can use a vendor package for `pip-tools`, or run
24-
25-
``` console
26-
> pip install pip-tools
27-
```
28-
29-
Make sure the installation directory (often `$HOME/.local/bin`) is on your `$PATH`.
30-
3124
### How to update dependencies
3225

33-
The list of transitive dependencies (`requirements.txt`) is generated from the list of direct dependencies in `requirements.in`. To perform the generation step, run
26+
The list of transitive dependencies (`requirements.txt`) is generated from the
27+
list of direct dependencies in `pyproject.toml`. Find outdated dependencies with:
3428

3529
```console
36-
> make users-guide-requirements
30+
> cd doc
31+
> uv pip list --outdated
32+
Package Version Latest Type
33+
------------------ ---------- -------- -----
34+
certifi 2025.11.12 2026.1.4 wheel
35+
docutils 0.21.2 0.22.4 wheel
36+
sphinx 8.2.3 9.1.0 wheel
37+
sphinxnotes-strike 1.5 2.0 wheel
38+
urllib3 2.6.2 2.6.3 wheel
3739
```
3840

39-
either from the root of the cabal repository or from the `docs/` subdirectory. You will need to do this before building documentation the first time, but should only need to repeat it after a `git clean` or if the dependencies in `requirements.in` change.
41+
Upgrade the lock file to the latest satisfiable requirements with:
42+
43+
```console
44+
> uv sync --upgrade
45+
...
46+
- certifi==2025.11.12
47+
+ certifi==2026.1.4
48+
- sphinxnotes-strike==1.5
49+
+ sphinxnotes-strike==2.0
50+
- urllib3==2.6.2
51+
+ urllib3==2.6.3
52+
```
4053

41-
In some cases, you may have to add a bound manually to `requirements.in`, e.g. `requests >= 2.31.0`.
54+
In some cases, you may have to add a bound manually to `pyproject.toml`, e.g. `requests >= 2.31.0`.
4255

4356
### How to check spelling
4457

doc/cabaldomain.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
import pygments.lexer as lexer
117117
import pygments.token as token
118118

119-
from distutils.version import StrictVersion
119+
from packaging.version import Version
120120

121121
from sphinx import addnodes
122122
from sphinx.directives import ObjectDescription
@@ -131,7 +131,7 @@ def parse_deprecated(txt):
131131
if txt is None:
132132
return True
133133
try:
134-
return StrictVersion(txt)
134+
return Version(txt)
135135
except ValueError:
136136
return True
137137

@@ -218,8 +218,8 @@ class CabalSection(Directive):
218218
option_spec = {
219219
'name': lambda x: x,
220220
'deprecated': parse_deprecated,
221-
'removed': StrictVersion,
222-
'since' : StrictVersion,
221+
'removed': Version,
222+
'since' : Version,
223223
'synopsis' : lambda x:x,
224224
}
225225
section_key = 'cabal:pkg-section'
@@ -281,8 +281,8 @@ class CabalObject(ObjectDescription):
281281
option_spec = {
282282
'noindex' : directives.flag,
283283
'deprecated': parse_deprecated,
284-
'removed' : StrictVersion,
285-
'since' : StrictVersion,
284+
'removed' : Version,
285+
'since' : Version,
286286
'synopsis' : lambda x:x
287287
}
288288

@@ -408,7 +408,7 @@ def run(self):
408408
if self.cabal_meta.deprecated is not None:
409409
field = nodes.field('')
410410
field_name = nodes.field_name('Deprecated', 'Deprecated')
411-
if isinstance(self.cabal_meta.deprecated, StrictVersion):
411+
if isinstance(self.cabal_meta.deprecated, Version):
412412
since = 'Cabal ' + str(self.cabal_meta.deprecated)
413413
else:
414414
since = ''
@@ -421,7 +421,7 @@ def run(self):
421421
if self.cabal_meta.removed is not None:
422422
field = nodes.field('')
423423
field_name = nodes.field_name('Removed', 'Removed')
424-
if isinstance(self.cabal_meta.removed, StrictVersion):
424+
if isinstance(self.cabal_meta.removed, Version):
425425
since = 'Cabal ' + str(self.cabal_meta.removed)
426426
else:
427427
since = ''
@@ -480,8 +480,8 @@ class CabalField(CabalObject):
480480
option_spec = {
481481
'noindex' : directives.flag,
482482
'deprecated': parse_deprecated,
483-
'removed' : StrictVersion,
484-
'since' : StrictVersion,
483+
'removed' : Version,
484+
'since' : Version,
485485
'synopsis' : lambda x:x
486486
}
487487

@@ -752,13 +752,13 @@ def make_data_keys(typ, target, node):
752752

753753

754754
def render_deprecated(deprecated):
755-
if isinstance(deprecated, StrictVersion):
755+
if isinstance(deprecated, Version):
756756
return 'deprecated since: '+str(deprecated)
757757
else:
758758
return 'deprecated'
759759

760760
def render_removed(deprecated, removed):
761-
if isinstance(deprecated, StrictVersion):
761+
if isinstance(deprecated, Version):
762762
return 'removed in: ' + str(removed) + '; deprecated since: '+str(deprecated)
763763
else:
764764
return 'removed in: ' + str(removed)

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
# List of patterns, relative to source directory, that match files and
5353
# directories to ignore when looking for source files.
54-
exclude_patterns = ['.build', "*.gen.rst"]
54+
exclude_patterns = ['.build', '*.gen.rst', '.venv']
5555

5656
# -- Options for HTML output ---------------------------------------------
5757

doc/pyproject.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,25 @@ verbose = true
99
cache_dir = '.skjold_cache'
1010
cache_expires = 43200 # Cache max. age. (43200 = 12hrs)
1111
ignore_file = '.skjoldignore'
12+
13+
# CVE suggestions
14+
# certifi>=2023.07.22 by CVE-2023-37920
15+
# idna>=3.7 by CVE-2024-3651
16+
# jinja2>=3.1.4 by CVE-2024-34064
17+
# pygments>=2.7.4 by CVE-2021-20270 CVE-2021-27291
18+
# requests>=2.32.0 by CVE-2024-35195
19+
# urllib3>=2.0.7 by CVE-2023-45803
20+
[dependency-groups]
21+
dev = [
22+
"certifi>=2023.7.22",
23+
"idna>=3.7",
24+
"jinja2>=3.1.4",
25+
"packaging>=25.0",
26+
"pygments>=2.7.4",
27+
"requests>=2.32.0",
28+
"sphinx>=8.2.3",
29+
"sphinx-jsonschema>=1.19.2",
30+
"sphinx-rtd-theme>=3.0.2",
31+
"sphinxnotes-strike>=1.5",
32+
"urllib3>=2.0.7",
33+
]

0 commit comments

Comments
 (0)