diff --git a/examples/compute_noop.py b/examples/compute_noop.py index 40696635..9da92775 100644 --- a/examples/compute_noop.py +++ b/examples/compute_noop.py @@ -5,7 +5,7 @@ import wgpu import wgpu.backends.rs # Select backend -from wgpu.utils import compute_with_buffers # Convenience function +from wgpu.utils.compute import compute_with_buffers # Convenience function # %% Shader and data diff --git a/tests/test_api.py b/tests/test_api.py index 046da9f8..fa6f990c 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -123,24 +123,30 @@ def get_output_from_subprocess(code): return p.stdout.decode(errors="ignore") -def test_do_not_import_utils_subpackage(): +def test_do_not_import_utils_submodules(): # OK: use something from root package code = "import wgpu; print(wgpu.__version__)" out = get_output_from_subprocess(code) assert "Error" not in out assert wgpu.__version__ in out - # OK: use something from utils if we import it first - code = "import wgpu.utils; print(wgpu.utils.compute_with_buffers)" + # OK: wgpu.utils itself is always there + code = "import wgpu; print(wgpu.utils)" out = get_output_from_subprocess(code) assert "Error" not in out - assert "function compute_with_buffers" in out + assert "module 'wgpu.utils' from " in out - # FAIL: use something from utils if we only import wgpu - code = "import wgpu; print(wgpu.utils.compute_with_buffers)" + # OK: wgpu.utils itself is always there + code = "import wgpu; print(wgpu.utils.get_default_device)" + out = get_output_from_subprocess(code) + assert "Error" not in out + assert "function get_default_device" in out + + # FAIL: use something from utils that's not imported + code = "import wgpu; print(wgpu.utils.compute.compute_with_buffers)" out = get_output_from_subprocess(code) assert "Error" in out - assert "has no attribute" in out and "utils" in out + assert "must be explicitly imported" in out and "utils" in out # Also, no numpy code = "import sys, wgpu.utils; print('numpy' in sys.modules)" diff --git a/tests/test_util_compute.py b/tests/test_util_compute.py index 345dbbff..26325455 100644 --- a/tests/test_util_compute.py +++ b/tests/test_util_compute.py @@ -5,7 +5,7 @@ import sys import wgpu.backends.rs # noqa -from wgpu.utils import compute_with_buffers +from wgpu.utils.compute import compute_with_buffers from pytest import skip, mark, raises from testutils import run_tests, can_use_wgpu_lib, is_ci, iters_equal diff --git a/wgpu/__init__.py b/wgpu/__init__.py index fe5a8b6b..400f0d24 100644 --- a/wgpu/__init__.py +++ b/wgpu/__init__.py @@ -7,6 +7,8 @@ from .enums import * # noqa: F401,F403 from .base import * # noqa: F401,F403 from .gui import WgpuCanvasInterface # noqa: F401,F403 +from . import utils # noqa: F401,F403 + __version__ = "0.11.0" version_info = tuple(map(int, __version__.split("."))) diff --git a/wgpu/utils/__init__.py b/wgpu/utils/__init__.py index a9fae661..faeddbe9 100644 --- a/wgpu/utils/__init__.py +++ b/wgpu/utils/__init__.py @@ -1,5 +1,5 @@ """ -Higher level utility functions. This module is not imported by default. +Higher level utilities. Must be explicitly imported from ``wgpu.utils.xx``. """ # The purpose of wgpu-py is to provide a Pythonic wrapper around @@ -13,5 +13,30 @@ # GPU/wgpu semantics), but without using low level details of the wgpu # API itself. -from ._device import get_default_device # noqa: F401 -from ._compute import compute_with_buffers # noqa: F401 +# The get_default_device() is so small and generally convenient that we import it by default. +from .device import get_default_device # noqa: F401 + + +class _StubModule: + def __init__(self, module): + self._module = module + self.must_be_explicitly_imported = True + + def __getattr__(self, *args, **kwargs): + raise RuntimeError(f"wgpu.utils.{self._module} must be explicitly imported.") + + def __repr__(self): + return f"" + + +# Create stubs + + +def compute_with_buffers(*args, **kwargs): + raise DeprecationWarning( + "wgpu.utils.compute_with_buffers() must now be imported from wgpu.utils.compute" + ) + + +compute = _StubModule("compute") +shadertoy = _StubModule("shadertoy") diff --git a/wgpu/utils/_compute.py b/wgpu/utils/compute.py similarity index 100% rename from wgpu/utils/_compute.py rename to wgpu/utils/compute.py diff --git a/wgpu/utils/_device.py b/wgpu/utils/device.py similarity index 100% rename from wgpu/utils/_device.py rename to wgpu/utils/device.py