diff --git a/changes/2913.feature.rst b/changes/2913.feature.rst new file mode 100644 index 0000000000..e0bfcba791 --- /dev/null +++ b/changes/2913.feature.rst @@ -0,0 +1 @@ +Added a `print_debug_info` function for bug reports. diff --git a/src/zarr/__init__.py b/src/zarr/__init__.py index 31796601b3..0d58ecf8e8 100644 --- a/src/zarr/__init__.py +++ b/src/zarr/__init__.py @@ -37,6 +37,54 @@ # in case setuptools scm screw up and find version to be 0.0.0 assert not __version__.startswith("0.0.0") + +def print_debug_info() -> None: + """ + Print version info for use in bug reports. + """ + import platform + from importlib.metadata import version + + def print_packages(packages: list[str]) -> None: + not_installed = [] + for package in packages: + try: + print(f"{package}: {version(package)}") + except ModuleNotFoundError: + not_installed.append(package) + if not_installed: + print("\n**Not Installed:**") + for package in not_installed: + print(package) + + required = [ + "packaging", + "numpy", + "numcodecs", + "typing_extensions", + "donfig", + ] + optional = [ + "botocore", + "cupy-cuda12x", + "fsspec", + "numcodecs", + "s3fs", + "gcsfs", + "universal-pathlib", + "rich", + "obstore", + ] + + print(f"platform: {platform.platform()}") + print(f"python: {platform.python_version()}") + print(f"zarr: {__version__}\n") + print("**Required dependencies:**") + print_packages(required) + print("\n**Optional dependencies:**") + print_packages(optional) + + __all__ = [ "Array", "AsyncArray", @@ -67,6 +115,7 @@ "open_consolidated", "open_group", "open_like", + "print_debug_info", "save", "save_array", "save_group", diff --git a/tests/test_zarr.py b/tests/test_zarr.py index 2aa62e4231..f49873132e 100644 --- a/tests/test_zarr.py +++ b/tests/test_zarr.py @@ -1,3 +1,5 @@ +import pytest + import zarr @@ -9,3 +11,19 @@ def test_exports() -> None: for export in __all__: getattr(zarr, export) + + +def test_print_debug_info(capsys: pytest.CaptureFixture[str]) -> None: + """ + Ensure that print_debug_info does not raise an error + """ + from importlib.metadata import version + + from zarr import __version__, print_debug_info + + print_debug_info() + captured = capsys.readouterr() + # test that at least some of what we expect is + # printed out + assert f"zarr: {__version__}" in captured.out + assert f"numpy: {version('numpy')}" in captured.out