Skip to content

Commit bc39471

Browse files
authored
🔨 dev script for listing all (private) unstubbed modules (#706)
2 parents c2a7b18 + e6585b6 commit bc39471

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

‎scripts/unstubbed_modules.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Prints the names of all SciPy modules that are not stubbed.
3+
"""
4+
5+
# ruff: noqa: T201, S101
6+
7+
import types
8+
import warnings
9+
from pathlib import Path
10+
from typing import Any
11+
12+
import scipy
13+
14+
BUNDLED = "scipy._lib.array_api_compat", "scipy._lib.array_api_extra", "scipy.fft._pocketfft"
15+
16+
17+
def modules(mod: types.ModuleType, _seen: set[types.ModuleType] | None = None) -> list[str]:
18+
seen = _seen or set()
19+
out: list[str] = []
20+
21+
assert _seen is not None or mod.__spec__
22+
23+
# the `dir` + `getattr` ensures that lazily loaded modules are included in `vars`
24+
mod_vars: dict[str, Any] = {}
25+
for k in dir(mod):
26+
mod_vars[k] = getattr(mod, k)
27+
28+
mod_vars |= vars(mod)
29+
30+
for k, v in mod_vars.items():
31+
if isinstance(v, types.ModuleType) and v not in seen and v.__name__.startswith("scipy"):
32+
seen.add(v)
33+
fname = v.__spec__.name if v.__spec__ else k
34+
if "." in fname:
35+
out.append(fname)
36+
out.extend(modules(v, _seen=seen))
37+
return out
38+
39+
40+
def is_stubbed(mod: str) -> bool:
41+
if not mod.startswith("scipy."):
42+
return False
43+
44+
stubs_path = Path(__file__).parent.parent / "scipy-stubs"
45+
if not stubs_path.is_dir():
46+
raise FileNotFoundError(stubs_path)
47+
48+
_, *submods = mod.split(".")
49+
if not submods:
50+
return (stubs_path / "__init__.pyi").is_file()
51+
52+
*subpackages, submod = submods
53+
subpackage_path = stubs_path.joinpath(*subpackages)
54+
return (subpackage_path / f"{submod}.pyi").is_file() or (subpackage_path / submod / "__init__.pyi").is_file()
55+
56+
57+
if __name__ == "__main__":
58+
with warnings.catch_warnings():
59+
warnings.simplefilter("ignore", DeprecationWarning)
60+
warnings.simplefilter("ignore", FutureWarning)
61+
module_list = modules(scipy)
62+
63+
module_list.sort()
64+
for name in module_list:
65+
if not any(map(name.startswith, BUNDLED)) and not is_stubbed(name):
66+
print(name)

0 commit comments

Comments
 (0)