Skip to content

Commit 44f7431

Browse files
authored
Add ci job to check whether new APIs have been added to docs (pyodide#5765)
We often accidentally add trash to the docs. This CI job will fail if we do.
1 parent 378521b commit 44f7431

File tree

3 files changed

+265
-0
lines changed

3 files changed

+265
-0
lines changed

.github/workflows/main.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,34 @@ jobs:
2222
id: get_python_version
2323
run: |
2424
echo "PYVERSION=$(git grep 'export PYVERSION ?=' Makefile.envs | cut -d' ' -f4)" >> "$GITHUB_OUTPUT"
25+
26+
check-docs:
27+
runs-on: ubuntu-latest
28+
needs: get_python_version
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
submodules: recursive
33+
- uses: actions/setup-python@v5
34+
with:
35+
python-version: ${{ needs.get_python_version.outputs.PYVERSION }}
36+
- name: Install Python requirements
37+
shell: bash -l {0}
38+
run: |
39+
python3 -m pip install -r docs/requirements-doc.txt
40+
- name: Install node requirements
41+
shell: bash -l {0}
42+
run: |
43+
cd src/js && npm i
44+
- name: Build docs
45+
shell: bash -l {0}
46+
run: |
47+
make -C docs/ html
48+
- name: Check docs
49+
shell: bash -l {0}
50+
run: |
51+
./tools/check_documented_functions.py --check
52+
2553
test-python:
2654
runs-on: ubuntu-latest
2755
needs: get_python_version

docs/expected_js_docs.txt

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
js:module
2+
globalThis
3+
pyodide
4+
pyodide.canvas
5+
pyodide.ffi
6+
js:function
7+
globalThis.loadPyodide
8+
pyodide.calculateInstallBaseUrl
9+
pyodide.canvas.getCanvas2D
10+
pyodide.canvas.getCanvas3D
11+
pyodide.canvas.setCanvas2D
12+
pyodide.canvas.setCanvas3D
13+
pyodide.checkInterrupt
14+
pyodide.ffi.PyAsyncGenerator.return
15+
pyodide.ffi.PyAsyncGenerator.throw
16+
pyodide.ffi.PyAsyncIterable.[Symbol․asyncIterator]
17+
pyodide.ffi.PyAsyncIterator.next
18+
pyodide.ffi.PyAwaitable.catch
19+
pyodide.ffi.PyAwaitable.finally
20+
pyodide.ffi.PyAwaitable.then
21+
pyodide.ffi.PyBuffer.getBuffer
22+
pyodide.ffi.PyBufferView.release
23+
pyodide.ffi.PyCallable.apply
24+
pyodide.ffi.PyCallable.bind
25+
pyodide.ffi.PyCallable.call
26+
pyodide.ffi.PyCallable.callKwargs
27+
pyodide.ffi.PyCallable.callKwargsRelaxed
28+
pyodide.ffi.PyCallable.callPromising
29+
pyodide.ffi.PyCallable.callPromisingKwargs
30+
pyodide.ffi.PyCallable.callRelaxed
31+
pyodide.ffi.PyCallable.callWithOptions
32+
pyodide.ffi.PyCallable.captureThis
33+
pyodide.ffi.PyGenerator.return
34+
pyodide.ffi.PyGenerator.throw
35+
pyodide.ffi.PyIterable.[Symbol․iterator]
36+
pyodide.ffi.PyIterator.next
37+
pyodide.ffi.PyMutableSequence.copyWithin
38+
pyodide.ffi.PyMutableSequence.fill
39+
pyodide.ffi.PyMutableSequence.pop
40+
pyodide.ffi.PyMutableSequence.push
41+
pyodide.ffi.PyMutableSequence.reverse
42+
pyodide.ffi.PyMutableSequence.shift
43+
pyodide.ffi.PyMutableSequence.sort
44+
pyodide.ffi.PyMutableSequence.splice
45+
pyodide.ffi.PyMutableSequence.unshift
46+
pyodide.ffi.PyProxy.copy
47+
pyodide.ffi.PyProxy.destroy
48+
pyodide.ffi.PyProxy.toJs
49+
pyodide.ffi.PyProxy.toString
50+
pyodide.ffi.PyProxyWithGet.asJsJson
51+
pyodide.ffi.PyProxyWithGet.get
52+
pyodide.ffi.PyProxyWithHas.has
53+
pyodide.ffi.PyProxyWithSet.delete
54+
pyodide.ffi.PyProxyWithSet.set
55+
pyodide.ffi.PySequence.asJsJson
56+
pyodide.ffi.PySequence.at
57+
pyodide.ffi.PySequence.concat
58+
pyodide.ffi.PySequence.entries
59+
pyodide.ffi.PySequence.every
60+
pyodide.ffi.PySequence.filter
61+
pyodide.ffi.PySequence.find
62+
pyodide.ffi.PySequence.findIndex
63+
pyodide.ffi.PySequence.forEach
64+
pyodide.ffi.PySequence.includes
65+
pyodide.ffi.PySequence.indexOf
66+
pyodide.ffi.PySequence.join
67+
pyodide.ffi.PySequence.keys
68+
pyodide.ffi.PySequence.lastIndexOf
69+
pyodide.ffi.PySequence.map
70+
pyodide.ffi.PySequence.reduce
71+
pyodide.ffi.PySequence.reduceRight
72+
pyodide.ffi.PySequence.slice
73+
pyodide.ffi.PySequence.some
74+
pyodide.ffi.PySequence.toJSON
75+
pyodide.ffi.PySequence.values
76+
pyodide.loadPackage
77+
pyodide.loadPackagesFromImports
78+
pyodide.mountNativeFS
79+
pyodide.mountNodeFS
80+
pyodide.pyimport
81+
pyodide.registerComlink
82+
pyodide.registerJsModule
83+
pyodide.runPython
84+
pyodide.runPythonAsync
85+
pyodide.scheduleCallback
86+
pyodide.setDebug
87+
pyodide.setInterruptBuffer
88+
pyodide.setStderr
89+
pyodide.setStdin
90+
pyodide.setStdout
91+
pyodide.toPy
92+
pyodide.unpackArchive
93+
pyodide.unregisterJsModule
94+
js:attribute
95+
pyodide.ERRNO_CODES
96+
pyodide.FS
97+
pyodide.PATH
98+
pyodide.PackageData.fileName
99+
pyodide.PackageData.name
100+
pyodide.PackageData.packageType
101+
pyodide.PackageData.version
102+
pyodide.ffi.PyBufferView.c_contiguous
103+
pyodide.ffi.PyBufferView.data
104+
pyodide.ffi.PyBufferView.f_contiguous
105+
pyodide.ffi.PyBufferView.format
106+
pyodide.ffi.PyBufferView.itemsize
107+
pyodide.ffi.PyBufferView.nbytes
108+
pyodide.ffi.PyBufferView.ndim
109+
pyodide.ffi.PyBufferView.offset
110+
pyodide.ffi.PyBufferView.readonly
111+
pyodide.ffi.PyBufferView.shape
112+
pyodide.ffi.PyBufferView.strides
113+
pyodide.ffi.PyProxy.type
114+
pyodide.ffi.PyProxyWithLength.length
115+
pyodide.ffi.PythonError.type
116+
pyodide.globals
117+
pyodide.loadedPackages
118+
pyodide.lockfile
119+
pyodide.lockfileBaseUrl
120+
pyodide.pyodide_py
121+
pyodide.version
122+
js:interface
123+
pyodide.PackageData
124+
js:typealias
125+
pyodide.TypedArray
126+
js:class
127+
pyodide.ffi.PyAsyncGenerator
128+
pyodide.ffi.PyAsyncIterable
129+
pyodide.ffi.PyAsyncIterator
130+
pyodide.ffi.PyAwaitable
131+
pyodide.ffi.PyBuffer
132+
pyodide.ffi.PyBufferView
133+
pyodide.ffi.PyCallable
134+
pyodide.ffi.PyDict
135+
pyodide.ffi.PyGenerator
136+
pyodide.ffi.PyIterable
137+
pyodide.ffi.PyIterator
138+
pyodide.ffi.PyMutableSequence
139+
pyodide.ffi.PyProxy
140+
pyodide.ffi.PyProxyWithGet
141+
pyodide.ffi.PyProxyWithHas
142+
pyodide.ffi.PyProxyWithLength
143+
pyodide.ffi.PyProxyWithSet
144+
pyodide.ffi.PySequence
145+
pyodide.ffi.PythonError
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import difflib
4+
import sys
5+
from pathlib import Path
6+
7+
from sphinx.ext.intersphinx import fetch_inventory
8+
9+
PYODIDE_ROOT = Path(__file__).parents[1]
10+
DOCS_DIR = PYODIDE_ROOT / "docs"
11+
EXPECTED_DOCS_FILE = DOCS_DIR / "expected_js_docs.txt"
12+
13+
14+
class App:
15+
srcdir = DOCS_DIR / "_build/html/"
16+
config = None
17+
18+
19+
def check_list():
20+
inv = fetch_inventory(App, "https://example.com", "objects.inv")
21+
res = []
22+
for category, entries in inv.items():
23+
if entries is None:
24+
continue
25+
if not category.startswith("js"):
26+
continue
27+
res.append(category)
28+
res.extend(f" {key}" for key in entries.keys())
29+
res.append("")
30+
return res
31+
32+
33+
def update_expected_js_docs():
34+
EXPECTED_DOCS_FILE.write_text("\n".join(check_list()))
35+
36+
37+
def check_expected_js_docs():
38+
expected_lines = EXPECTED_DOCS_FILE.read_text().splitlines()
39+
new_lines = check_list()
40+
new_lines.pop()
41+
diffs = list(
42+
difflib.unified_diff(
43+
expected_lines,
44+
new_lines,
45+
fromfile="old expected_js_docs.txt",
46+
tofile="new expected_js_docs.txt",
47+
)
48+
)
49+
if not diffs:
50+
print("No changes")
51+
return 0
52+
print(
53+
"Set of documented APIs changed. If this is intended, run ./tools/check_documented_functions.py --update"
54+
)
55+
for l in diffs:
56+
print(l)
57+
return 1
58+
59+
60+
def parse_args():
61+
parser = argparse.ArgumentParser(
62+
description="Compare the set of documented JS APIs to the expected set or update the expected set"
63+
)
64+
parser.add_argument(
65+
"--check",
66+
action="store_true",
67+
help="Check the set of documented JS APIs",
68+
)
69+
parser.add_argument(
70+
"--update",
71+
action="store_true",
72+
help="Update the expected set of documented JS APIs",
73+
)
74+
return parser.parse_args()
75+
76+
77+
def main():
78+
args = parse_args()
79+
if not (args.update ^ args.check):
80+
print("Expected exactly one of --check and --update")
81+
sys.exit(1)
82+
83+
if args.update:
84+
update_expected_js_docs()
85+
sys.exit(0)
86+
87+
if args.check:
88+
sys.exit(check_expected_js_docs())
89+
90+
91+
if __name__ == "__main__":
92+
main()

0 commit comments

Comments
 (0)