forked from isaac-sim/IsaacLab
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathisaaclab_docs.py
More file actions
333 lines (250 loc) · 11.1 KB
/
Copy pathisaaclab_docs.py
File metadata and controls
333 lines (250 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Sphinx helpers for Isaac Lab documentation."""
from __future__ import annotations
import re
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import StringList
from sphinx.util.docutils import SphinxDirective
from sphinx.util.docutils import SphinxRole
from sphinx.util.nodes import split_explicit_title
_UPSTREAM_SOURCE_REF_PATTERN = re.compile(r"^(main|develop|release/.*|v[1-9]\d*\.\d+\.\d+(-[A-Za-z0-9.]+)?)$")
def _branch(config) -> str:
"""Return the branch or tag pinned in installation docs."""
current_version = getattr(config, "smv_current_version", "")
if current_version:
return current_version
return getattr(config, "isaaclab_latest_branch", "main")
def _source_branch(config) -> str:
"""Return a GitHub source ref that exists in the upstream repository."""
branch = _branch(config)
if _UPSTREAM_SOURCE_REF_PATTERN.match(branch):
return branch
return getattr(config, "isaaclab_latest_branch", "develop")
def _parse_rst(directive: SphinxDirective, content: str) -> list[nodes.Node]:
"""Parse nested reST and return the generated document nodes."""
source = directive.env.doc2path(directive.env.docname, base=False)
lines = StringList(content.splitlines(), source=source)
container = nodes.container()
directive.state.nested_parse(lines, 0, container)
return container.children
class IsaacLabCloneCommands(SphinxDirective):
"""Render SSH/HTTPS clone tabs using copy-friendly ``code-block`` directives."""
has_content = False
def run(self) -> list[nodes.Node]:
branch = _branch(self.config)
content = f"""\
.. tab-set::
.. tab-item:: SSH
.. code-block:: bash
git clone git@github.com:isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
.. tab-item:: HTTPS
.. code-block:: bash
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
"""
return _parse_rst(self, content)
class IsaacLabSourceLink(SphinxRole):
"""Link to a source file on the GitHub branch or tag for the current docs version."""
def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]:
branch = _source_branch(self.config)
has_explicit_title, title, target = split_explicit_title(self.text)
if not has_explicit_title:
title = target
target = target.strip("/")
refuri = f"https://github.com/isaac-sim/IsaacLab/blob/{branch}/{target}"
node = nodes.reference(self.rawtext, title, refuri=refuri, **self.options)
return [node], []
class IsaacLabCloneHttps(SphinxDirective):
"""Render an HTTPS clone command as a copy-friendly ``code-block``."""
has_content = False
option_spec = {"platform": directives.unchanged_required}
def run(self) -> list[nodes.Node]:
platform = self.options.get("platform", "linux").strip().lower()
if platform not in {"linux", "windows"}:
raise self.error(f"Unsupported platform '{platform}'. Use 'linux' or 'windows'.")
branch = _branch(self.config)
language = "batch" if platform == "windows" else "bash"
content = f"""\
.. code-block:: {language}
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
"""
return _parse_rst(self, content)
class IsaacLabKitlessInstallSnippet(SphinxDirective):
"""Render the kit-less clone + install commands from the installation index."""
has_content = False
def run(self) -> list[nodes.Node]:
branch = _branch(self.config)
content = f"""\
.. code-block:: bash
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
./isaaclab.sh --install # or ./isaaclab.sh -i
"""
return _parse_rst(self, content)
class IsaacLabQuickstartInstall(SphinxDirective):
"""Render quickstart install snippets with the pinned release branch."""
option_spec = {
"kitless": directives.flag,
"isaacsim": directives.flag,
"platform": directives.unchanged_required,
}
def run(self) -> list[nodes.Node]:
branch = _branch(self.config)
platform = self.options["platform"].strip().lower()
if platform not in {"linux", "windows"}:
raise self.error(f"Unsupported platform '{platform}'. Use 'linux' or 'windows'.")
if "kitless" in self.options and "isaacsim" in self.options:
raise self.error("Specify only one of :kitless: or :isaacsim:.")
if "kitless" in self.options:
content = _quickstart_kitless(branch, platform)
elif "isaacsim" in self.options:
content = _quickstart_isaacsim(
branch,
platform,
self.config.isaacsim_version,
self.config.torch_version,
self.config.torchvision_version,
)
else:
raise self.error("Specify either :kitless: or :isaacsim:.")
return _parse_rst(self, content)
def _quickstart_kitless(branch: str, platform: str) -> str:
"""Return quickstart reST for kit-less installation."""
if platform == "linux":
return f"""\
.. code-block:: bash
# Install uv (https://docs.astral.sh/uv/getting-started/installation/)
curl -LsSf https://astral.sh/uv/install.sh | sh
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
uv venv --python 3.12 --seed env_isaaclab
source env_isaaclab/bin/activate
./isaaclab.sh -i
"""
return f"""\
.. code-block:: batch
:: Install uv: https://docs.astral.sh/uv/getting-started/installation/
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
uv venv --python 3.12 --seed env_isaaclab
env_isaaclab\\Scripts\\activate
isaaclab.bat -i
"""
class IsaacLabIsaacSimInstall(SphinxDirective):
"""Render the ``uv pip install isaacsim`` command pinned to the pyproject version."""
has_content = False
def run(self) -> list[nodes.Node]:
version = self.config.isaacsim_version
content = f"""\
.. code-block:: bash
uv pip install "isaacsim[all,extscache]=={version}" --extra-index-url https://pypi.nvidia.com --index-strategy unsafe-best-match --prerelease=allow
"""
return _parse_rst(self, content)
class IsaacLabUvWheelInstall(SphinxDirective):
"""Render the uv wheel installation command for the current documentation version."""
has_content = False
def run(self) -> list[nodes.Node]:
branch = _source_branch(self.config)
overrides_url = (
f"https://raw.githubusercontent.com/isaac-sim/IsaacLab/{branch}/tools/wheel_builder/uv-overrides.txt"
)
content = f"""\
.. code-block:: bash
uv pip install "isaaclab[all]" \\
--overrides "{overrides_url}" \\
--extra-index-url https://pypi.nvidia.com \\
--index-strategy unsafe-best-match --prerelease=allow
"""
return _parse_rst(self, content)
class IsaacLabTorchInstall(SphinxDirective):
"""Render the pinned ``torch``/``torchvision`` install command for a CUDA build.
Versions come from ``[tool.isaaclab.versions]`` (the single source of truth),
exposed via the ``torch_version`` / ``torchvision_version`` config values.
Usage::
.. isaaclab-torch-install:: cu128
.. isaaclab-torch-install:: cu130 pip
"""
required_arguments = 1 # CUDA build tag, e.g. "cu128"
optional_arguments = 1 # installer: "pip" (default is "uv pip")
def run(self) -> list[nodes.Node]:
cuda_tag = self.arguments[0]
installer = "pip" if len(self.arguments) > 1 and self.arguments[1] == "pip" else "uv pip"
torch_version = self.config.torch_version
torchvision_version = self.config.torchvision_version
content = f"""\
.. code-block:: bash
{installer} install -U torch=={torch_version} torchvision=={torchvision_version} --index-url https://download.pytorch.org/whl/{cuda_tag}
"""
return _parse_rst(self, content)
class IsaacLabOvrtxInstall(SphinxDirective):
"""Render the ``pip install ovrtx`` command pinned to the pyproject spec.
The spec comes from ``[tool.isaaclab.versions].ovrtx``, exposed via the
``ovrtx_spec`` config value.
"""
has_content = False
def run(self) -> list[nodes.Node]:
spec = self.config.ovrtx_spec
content = f"""\
.. code-block:: bash
pip install "ovrtx{spec}"
"""
return _parse_rst(self, content)
def _quickstart_isaacsim(branch: str, platform: str, isaacsim_version: str, torch_version: str, torchvision_version: str) -> str:
"""Return quickstart reST for full Isaac Sim installation."""
if platform == "linux":
return f"""\
.. code-block:: bash
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
uv venv --python 3.12 --seed env_isaaclab
source env_isaaclab/bin/activate
uv pip install --upgrade pip
uv pip install "isaacsim[all,extscache]=={isaacsim_version}" \\
--extra-index-url https://pypi.nvidia.com \\
--index-strategy unsafe-best-match --prerelease=allow
uv pip install -U torch=={torch_version} torchvision=={torchvision_version} \\
--index-url https://download.pytorch.org/whl/cu128
./isaaclab.sh -i
"""
return f"""\
.. code-block:: batch
:: Install uv: https://docs.astral.sh/uv/getting-started/installation/
git clone https://github.com/isaac-sim/IsaacLab.git --branch {branch}
cd IsaacLab
uv venv --python 3.12 --seed env_isaaclab
env_isaaclab\\Scripts\\activate
uv pip install --upgrade pip
uv pip install "isaacsim[all,extscache]=={isaacsim_version}" ^
--extra-index-url https://pypi.nvidia.com ^
--index-strategy unsafe-best-match --prerelease=allow
uv pip install -U torch=={torch_version} torchvision=={torchvision_version} ^
--index-url https://download.pytorch.org/whl/cu128
isaaclab.bat -i
"""
def setup(app):
"""Register Isaac Lab documentation directives."""
app.add_config_value("isaaclab_latest_branch", "develop", "env")
app.add_config_value("isaacsim_version", "", "env")
app.add_config_value("torch_version", "", "env")
app.add_config_value("torchvision_version", "", "env")
app.add_config_value("ovrtx_spec", "", "env")
app.add_role("isaaclab-source", IsaacLabSourceLink())
app.add_directive("isaaclab-clone-commands", IsaacLabCloneCommands)
app.add_directive("isaaclab-clone-https", IsaacLabCloneHttps)
app.add_directive("isaaclab-kitless-install-snippet", IsaacLabKitlessInstallSnippet)
app.add_directive("isaaclab-quickstart-install", IsaacLabQuickstartInstall)
app.add_directive("isaaclab-isaacsim-install", IsaacLabIsaacSimInstall)
app.add_directive("isaaclab-uv-wheel-install", IsaacLabUvWheelInstall)
app.add_directive("isaaclab-torch-install", IsaacLabTorchInstall)
app.add_directive("isaaclab-ovrtx-install", IsaacLabOvrtxInstall)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}