Skip to content

Commit 0f2cf55

Browse files
authored
Fix issues with pdoc auto-generated documentation (missing objects, no docstrings for functions) (#443)
1 parent cbcc273 commit 0f2cf55

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

.github/workflows/pdoc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
python-version: 3.12
2727
- name: Build
2828
run: |
29+
echo "PDOC_GENERATE_PYPARTMC_DOCS=True" >> $GITHUB_ENV
2930
pip install pdoc
3031
pip install -e .
3132
PDOC_ALLOW_EXEC=1 python -We -m pdoc -o html PyPartMC

src/PyPartMC/__init__.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
# pylint: disable=invalid-name
66
import importlib.metadata
7+
import inspect
78

89
# pylint: disable=invalid-name,wrong-import-position
910
import os
@@ -79,8 +80,29 @@ def __generate_si():
7980
__versions_of_build_time_dependencies__,
8081
)
8182

83+
# Hacky workaround for missing docs in pdoc auto-generated documentation.
84+
# After the switch to nanobind, the docs became empty despite "__doc__" being
85+
# accessible in all of PyPartMC's objects. The code below manually populates
86+
# the "__all__" atrribute of the package. Additionally, functions in the generated
87+
# docs would be listed as nanobind objects with no additional documentation.
88+
# To solve that, dummy functions of the same name are created, and their "__doc__"
89+
# attribute is manually set to the "original" objects' "__doc__"
90+
if os.getenv("PDOC_GENERATE_PYPARTMC_DOCS") == "True":
91+
all_items = []
92+
for name, obj in inspect.getmembers(
93+
_PyPartMC # pylint: disable=undefined-variable
94+
):
95+
if callable(obj):
96+
if not inspect.isclass(obj):
97+
exec(name + " = lambda : 0") # pylint: disable=exec-used
98+
temp = "_PyPartMC." + name + ".__doc__"
99+
setattr(eval(name), "__doc__", eval(temp)) # pylint: disable=eval-used
100+
all_items.append(name)
101+
102+
__all__ = tuple([*all_items, "si"])
103+
82104
__version__ = importlib.metadata.version(__package__)
83105

84-
# walkaround for MATLAB bindings
106+
# workaround for MATLAB bindings
85107
# pylint: disable=undefined-variable
86108
setattr(nanobind, "nb_type_0", type(_PyPartMC.AeroData))

tests/test_help.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import inspect
2+
import pydoc
3+
4+
import pytest
5+
6+
import PyPartMC as ppmc
7+
8+
9+
@pytest.mark.parametrize(
10+
"obj",
11+
(
12+
ppmc.AeroBinned,
13+
ppmc.AeroData,
14+
ppmc.AeroParticle,
15+
ppmc.AeroState,
16+
ppmc.CampCore,
17+
ppmc.EnvState,
18+
ppmc.GasData,
19+
ppmc.GasState,
20+
ppmc.Photolysis,
21+
ppmc.RunExactOpt,
22+
ppmc.RunPartOpt,
23+
ppmc.RunSectOpt,
24+
ppmc.Scenario,
25+
ppmc.condense_equilib_particle,
26+
ppmc.condense_equilib_particles,
27+
ppmc.diam2rad,
28+
ppmc.histogram_1d,
29+
ppmc.histogram_2d,
30+
ppmc.input_exact,
31+
ppmc.input_sectional,
32+
ppmc.input_state,
33+
ppmc.loss_rate,
34+
ppmc.loss_rate_dry_dep,
35+
ppmc.output_state,
36+
ppmc.pow2_above,
37+
ppmc.rad2diam,
38+
ppmc.rand_init,
39+
ppmc.rand_normal,
40+
ppmc.run_exact,
41+
ppmc.run_part,
42+
ppmc.run_part_timeblock,
43+
ppmc.run_part_timestep,
44+
ppmc.run_sect,
45+
ppmc.sphere_rad2vol,
46+
ppmc.sphere_vol2rad,
47+
),
48+
)
49+
def test_help_output(obj):
50+
help_output = pydoc.render_doc(obj, renderer=pydoc.plaintext)
51+
52+
assert len(obj.__doc__) > 0
53+
54+
# help() output of functions is broken on CI
55+
if inspect.isclass(obj):
56+
# remove whitespace and bars
57+
assert "".join(obj.__doc__.split()) in "".join(
58+
help_output.replace("|", "").split()
59+
)

0 commit comments

Comments
 (0)