diff --git a/pyproject.toml b/pyproject.toml index f86dae4..c519bfd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ "setuptools", "wheel" ] [project] name = "cunumpy" -version = "0.1" +version = "0.1.1" description = "Simple wrapper for numpy and cupy. Replace `import numpy as np` with `import cunumpy as xp`." readme = "README.md" keywords = [ "python" ] @@ -48,3 +48,6 @@ urls."Source" = "https://github.com/max-models/cunumpy" [tool.setuptools.packages.find] where = [ "src" ] + +[tool.setuptools.package-data] +cunumpy = [ "py.typed", "*.pyi" ] diff --git a/src/cunumpy/__init__.pyi b/src/cunumpy/__init__.pyi new file mode 100644 index 0000000..b5fe885 --- /dev/null +++ b/src/cunumpy/__init__.pyi @@ -0,0 +1,7 @@ +# Stub file for Pylance/mypy: exposes all numpy symbols so that +# `import cunumpy as xp` followed by `xp.` shows numpy completions. +# At runtime the real __init__.py dispatches to numpy or cupy via __getattr__. +from numpy import * +from numpy import __config__, __version__ + +from . import xp diff --git a/src/cunumpy/py.typed b/src/cunumpy/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/test_app.py b/tests/unit/test_app.py index ccb4e6d..ce6b9d0 100644 --- a/tests/unit/test_app.py +++ b/tests/unit/test_app.py @@ -1,3 +1,5 @@ +import numpy as np + import cunumpy as xp @@ -9,5 +11,16 @@ def test_xp_array(): print(f"{arr = } {type(arr) = }") +def test_numpy_symbols_accessible(): + """All public numpy symbols must be reachable via cunumpy. + + This validates the runtime behaviour that the stub file (__init__.pyi) + declares to Pylance so that `xp.` shows numpy completions in VS Code. + """ + missing = [name for name in np.__all__ if not hasattr(xp, name)] + assert missing == [], f"Symbols not accessible via cunumpy: {missing}" + + if __name__ == "__main__": test_xp_array() + test_numpy_symbols_accessible()