Skip to content

Commit 692e6d1

Browse files
authored
Docs improvements (#411)
* Remove awkward "This class does xyz" immediately followed by "Constructs an instance of..." stemming from the concatenation by Sphinx's autoclass of class and constructor dosctrings. For a more detailed explanation of the issues, see the comment in `.flake8` about D205 and D400. * Added a target to make web docs locally rather than through sphinx-multiversion * When building web docs, also build a dev version, which is treated as latest in the version comparison. However, the version selected by default is not dev, but the latest numeric one, unless dev is the only version present. * Render attributes more like properties. * Some doc styling fixes: - smaller margin at the top of the definition in a definition list - bigger margin at the top of a chapter - code block caption larger and closer to code block - darker text color for method parameters * Added queue_name and project_name to testing config and execparams as well as the appropriate rendering in docs. * Added a custom generator for the API doc, since sphinx autodoc lacks the flexibility to produce nice results and manually doing the full api doc is tedious and error prone. This generator takes a file that represents a toc tree and outputs an api doc that results in (roughly) the same toc tree, but with proper class, module, and function docs. It also procudes a list of executors and launchers, as well as their respective class docs, by querying the appropriate psij executor/launcher list functions. Last, it produces an index of all classes and functions. * Clean output directory before building web docs, since leftovers may interfere with the result. * Needef for some CSS selectors. * Show base class in class docs. * Fix multiple targets for cross reference in method signature types. * Pin spinx-tabs to 3.2.0 * This fixes a number of conceptual issues with executor registration: - allows for aliases (e.g., "pbs" -> "pbspro") - adds a "nice name" to executor descriptors (e.g., "rp" -> "Radical Pilot") - makes "pbs" the default rather than "pbspro"; "pbs" much predates the latter. - ensures that executor/launcher names are always stored and looked up in lower case * Many docstring fixes * Reformatting to be more in line with the rest of the code * Unfortunately, sphinx gets confused when defining type aliases, so revert to explicit types for the frankenpaths. * Small ref fix * Ref fix and use include for code example. * Fix refs in add exec tutorial * Updated arch and state diagram to be more in-line with the rest of the styling as well as added a vector version that can be edited in, e.g., inkscape * Updated user guide. * Fixed spelling * Turns out the adding and executor tutorial wasn't rendering at all. * Another spelling fix * Added docstrings for new props. * Added a module loading example using pre_launch to the user guide * Fixed odd spaces * Fixed test function names * Don't assume tests are run in the same directory as their source files. * Fixed test * Get output from subprocess * This patch is not done on top of the new wait() semantics * `join()` will ignore the first part if the last starts with a '/' * It's `--utc` not `-utc` * added readthedocs config file, which seems to be required now * Fixed broken comments * Spelling fixes * Fixed readthedocs conf again * Added requirements to rtd conf file * Fixed missing import * Removed unused import * Updated `Job.wait` documentation to reflect the current semantics
1 parent 79309dc commit 692e6d1

File tree

84 files changed

+2448
-820
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2448
-820
lines changed

.flake8

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,33 @@ max-line-length = 100
3636
# See https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator
3737
# for a discussion about the issue and why we disable this.
3838

39-
ignore = B902, D401, D100, W503
39+
# D205 - "1 blank line required between summary line and description"
40+
# D400 - "First line should end with a period"
41+
#
42+
# Sphinx (autoclass) has three modes of operation when it comes to
43+
# documenting classes: 'class', 'init', and 'both'. This pertains to how
44+
# docstrings for the class and init method are handled. Autoclass does
45+
# not produce a separate text for the class and init methods, but the
46+
# options above describe where the constructor documentation comes from.
47+
# This can be either the class docstring (autoclass_content = 'class')
48+
# or the __init__ docstring or both concatenated. The 'class' options
49+
# results in empty decriptions for the __init__ parameters. The
50+
# 'init' option ignores the class docstring, so, in order to get that
51+
# part into the output, it would need to be duplicated in the __init__
52+
# docstring. The better option is 'both'. However saying something like
53+
# "This class..." in the class docstring and "Initializes..." in the
54+
# __init__ docstring results in awkward phrasing when put together.
55+
# One can omit the description on the __init__ docstring and simply
56+
# document the parameters, but then flake8 complains about the
57+
# structure of the __init__ doctsring. The D205 and D400 errors are
58+
# precisely those complains. We disable these in order to have a
59+
# sane way of documenting classes with Sphinx' autoclass.
60+
61+
62+
ignore = B902, D205, D400, D401, D100, W503
4063

4164
# D103 - Missing docstring in public function
4265
#
4366
# Ignore docstrings requirement in tests
4467

4568
per-file-ignores = tests/*:D103
46-

.readthedocs.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Read the Docs configuration file for Sphinx projects
2+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3+
4+
# Required
5+
version: 2
6+
7+
# Set the OS, Python version and other tools you might need
8+
build:
9+
os: ubuntu-22.04
10+
tools:
11+
python: "3.11"
12+
13+
python:
14+
install:
15+
- requirements: requirements-docs.txt
16+
17+
18+
# Build documentation in the "docs/" directory with Sphinx
19+
sphinx:
20+
configuration: docs/conf.py
21+
fail_on_warning: true

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,15 @@ docs:
5757
web-docs:
5858
rm -rf docs/.generated
5959
rm -rf docs/.web-build
60+
git fetch --all --tags
6061
PSIJ_WEB_DOCS=1 sphinx-multiversion docs docs/.web-build
62+
PSIJ_WEB_DOCS=1 sphinx-build --keep-going -n -W -b html docs docs/.web-build/v/dev
63+
64+
.PHONY: web-docs-dev
65+
web-docs-dev:
66+
rm -rf docs/.generated
67+
rm -rf docs/.web-build
68+
PSIJ_WEB_DOCS=1 sphinx-build --keep-going -n -W -b html docs docs/.web-build/v/dev
6169

6270
.PHONY: style
6371
style:

docs/_static/extras.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ $(document).ready(function() {
3535

3636
initializeSelectors(selectorType, value);
3737
});
38+
// Sphinx renders attributes differently from properties in that properties
39+
// come with a nice "property" prefix in the heading, whereas attributes just
40+
// have the name. This hacks the attribute headers to add a "attribute" text
41+
// before the attribute name
42+
$("dl.attribute > dt.sig").each(function() {
43+
$(this).prepend("<em class=\"attribute\"><span class=\"pre\">attribute</span><span class=\"w\"></span></em>");
44+
});
3845
});
3946

4047
function detectAll(selectorType) {
@@ -70,12 +77,19 @@ function detectAll(selectorType) {
7077
if (text == '"<&' + selectorType + '>"') {
7178
$(this).addClass(selectorType + "-item").addClass("psij-selector-value");
7279
}
73-
if (text == "executor" && prevSpans.length == 2
74-
&& prevSpans[0].text() == "execparams" && prevSpans[1].text() == '.') {
80+
if (prevSpans.length == 2 && prevSpans[0].text() == "execparams" && prevSpans[1].text() == '.') {
7581
// remove <span>execparams</span> and <span>.</span>
7682
prevSpans[0].remove();
7783
prevSpans[1].remove();
78-
$(this).addClass(selectorType + "-item").addClass("psij-selector-value");
84+
if (text == "executor") {
85+
$(this).addClass(selectorType + "-item").addClass("psij-selector-value");
86+
}
87+
else if (text == "queue_name") {
88+
$(this).text("QUEUE_NAME");
89+
}
90+
else if (text == "project_name") {
91+
$(this).text("PROJECT_NAME");
92+
}
7993
}
8094
prevSpans.push($(this));
8195
if (prevSpans.length > 2) {

docs/_templates/layout.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
{% endblock %}
1212

1313
{% block header %}
14-
<v-app id="psij-app">
14+
<v-app id="psij-app" class="psij-docs">
1515
{% include "../../web/_includes/menu.html" %}
1616
{{ super() }}
1717
{% endblock %}
1818

1919
{% block rootrellink %}
20-
<li><a href="{{ pathto(theme_roottarget) }}">{{shorttitle|e}}</a>{% if versions %}{% include "../../web/_includes/versionselect.html" %}{% endif %}{{reldelim1}}</li>
20+
<li><a href="{{ pathto(theme_roottarget) }}">{{shorttitle|e}}</a>{% include "../../web/_includes/versionselect.html" %}{{reldelim1}}</li>
2121
{% endblock %}
2222

2323

docs/api.rst

Lines changed: 3 additions & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -1,230 +1,6 @@
1-
The PSI/J API
1+
API Reference
22
=============
33

4-
The most important classes in this library are ``Job`` and ``JobExecutor``,
5-
followed by ``Launcher``.
6-
7-
The Job Class and Its Modifiers
8-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9-
10-
The Job-related classes listed in this section (``Job``, ``JobSpec``,
11-
``ResourceSpec``, and ``JobAttributes``) are independent of
12-
executor implementations. The authors strongly recommend that users
13-
program against these classes rather than adding executor-specific
14-
configuration options.
15-
16-
.. autoclass:: psij.Job
17-
:members:
18-
:noindex:
19-
20-
.. autoclass:: psij.JobStatus
21-
:members:
22-
:noindex:
23-
24-
.. autoclass:: psij.JobState
25-
:members:
26-
:noindex:
27-
28-
Job Modifiers
29-
^^^^^^^^^^^^^
30-
31-
There can be a lot of configuration information that goes into each
32-
resource manager job, including its walltime, partition/queue, the number of nodes
33-
it needs, what kind of nodes, what quality of service the job requires, and
34-
so on.
35-
36-
PSI/J splits those attributes into three groups: one for generic
37-
POSIX information, one for resource information, and one for resource manager
38-
scheduling policies.
39-
40-
.. autoclass:: psij.JobSpec
41-
:members:
42-
:noindex:
43-
44-
.. autoclass:: psij.ResourceSpec
45-
:members:
46-
:noindex:
47-
48-
.. autoclass:: psij.JobAttributes
49-
:members:
50-
:noindex:
51-
52-
53-
.. _executors:
54-
55-
Executors
56-
~~~~~~~~~
57-
58-
Executors are concrete implementations of mechanisms that execute jobs.
59-
To get an instance of a specific executor, call
60-
:meth:`JobExecutor.get_instance(name) <psij.job_executor.JobExecutor.get_instance>`,
61-
with ``name`` being one of the installed executor names. Alternatively, directly
62-
instantiate the executor, e.g.:
63-
64-
.. code-block:: python
65-
66-
from psij.executors.flux import FluxJobExecutor
67-
68-
ex = FluxJobExecutor()
69-
70-
Rather than:
71-
72-
.. code-block:: python
73-
74-
import psij
75-
76-
ex = psij.JobExecutor.get_instance('flux')
77-
78-
Executors can be
79-
installed from multiple sources, so the precise list of executors
80-
available to a specific installation of the PSI/J Python library can vary.
81-
To get a list of available executors, run the following in a
82-
terminal:
83-
84-
.. code-block:: shell
85-
86-
$ python -m psij plugins
87-
88-
89-
JobExecutor Base Class
90-
^^^^^^^^^^^^^^^^^^^^^^
91-
92-
The ``psij.JobExecutor`` class is abstract, but offers concrete static methods
93-
for registering, fetching, and listing subclasses of itself.
94-
95-
.. autoclass:: psij.job_executor.JobExecutor
96-
:noindex:
97-
98-
The concrete executor implementations provided by this version of PSI/J Python
99-
are:
100-
101-
Cobalt
102-
""""""""""""""""""""""
103-
104-
.. autoclass:: psij.executors.batch.cobalt.CobaltJobExecutor
105-
:noindex:
106-
107-
Flux
108-
""""""""""""""""""""""
109-
110-
.. autoclass:: psij.executors.flux.FluxJobExecutor
111-
:noindex:
112-
113-
LSF
114-
""""""""""""""""""""""
115-
116-
.. autoclass:: psij.executors.batch.lsf.LsfJobExecutor
117-
:noindex:
118-
119-
PBS
120-
""""""""""""""""""""""
121-
122-
.. autoclass:: psij.executors.batch.pbspro.PBSProJobExecutor
123-
:noindex:
124-
125-
Slurm
126-
""""""""""""""""""""""
127-
128-
.. autoclass:: psij.executors.batch.slurm.SlurmJobExecutor
129-
:noindex:
130-
131-
Local
132-
""""""""""""""""""""""
133-
134-
.. autoclass:: psij.executors.local.LocalJobExecutor
135-
:noindex:
136-
137-
Radical Pilot
138-
""""""""""""""""""""""
139-
140-
.. autoclass:: psij.executors.rp.RPJobExecutor
141-
:noindex:
142-
143-
.. _launchers:
144-
145-
146-
Launchers
147-
----------------
148-
149-
Launchers are mechanisms to start the actual jobs on batch schedulers
150-
once a set of nodes has been allocated for the job. In essence, launchers
151-
are wrappers around the job executable which can provide additional
152-
features, such as setting up an MPI environment, starting a copy of the
153-
job executable on each allocated node, etc.
154-
155-
To get a launcher instance,
156-
call :meth:`Launcher.get_instance(name) <psij.launcher.Launcher.get_instance>`
157-
with ``name`` being the name of a launcher. Like job executors,
158-
launchers are plugins and can come from various places. To obtain a list
159-
of launchers, you can run:
160-
161-
.. code-block:: shell
162-
163-
$ python -m psij plugins
164-
165-
Launcher Base Class
166-
^^^^^^^^^^^^^^^^^^^
167-
168-
Like the executor, the ``Launcher`` base class is abstract, but offers
169-
concrete static methods for registering and fetching subclasses of itself.
170-
171-
.. autoclass:: psij.Launcher
172-
:noindex:
173-
174-
The PSI/J Python library comes with a core set of launchers, which are:
175-
176-
aprun
177-
""""""""""""""""""""""
178-
179-
.. autoclass:: psij.launchers.aprun.AprunLauncher
180-
:members:
181-
:noindex:
182-
183-
jsrun
184-
""""""""""""""""""""""
185-
186-
.. autoclass:: psij.launchers.jsrun.JsrunLauncher
187-
:members:
188-
:noindex:
189-
190-
srun
191-
""""""""""""""""""""""
192-
193-
.. autoclass:: psij.launchers.srun.SrunLauncher
194-
:members:
195-
:noindex:
196-
197-
mpirun
198-
""""""""""""""""""""""
199-
200-
.. autoclass:: psij.launchers.mpirun.MPILauncher
201-
:members:
202-
:noindex:
203-
204-
single
205-
""""""""""""""""""""""
206-
207-
.. autoclass:: psij.launchers.single.SingleLauncher
208-
:members:
209-
:noindex:
210-
211-
multiple
212-
""""""""""""""""""""""
213-
214-
.. autoclass:: psij.launchers.multiple.MultipleLauncher
215-
:members:
216-
:noindex:
217-
218-
Other Package Contents
219-
----------------------
220-
221-
.. automodule:: psij.exceptions
222-
:members:
223-
:noindex:
224-
225-
226-
API Reference
227-
----------------
2284
.. toctree::
229-
230-
.generated/modules
5+
.generated/tree
6+
.generated/index

0 commit comments

Comments
 (0)