Skip to content
Merged
45 changes: 15 additions & 30 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,21 @@ body:
attributes:
value: |
Please provide the following information.
- type: input
id: Zarr-version
attributes:
label: Zarr version
description: Value of ``zarr.__version__``
placeholder: v2.10.2, v2.11.3, v2.12.0, etc.
validations:
required: true
- type: input
id: Numcodecs-version
attributes:
label: Numcodecs version
description: Value of ``numcodecs.__version__``
placeholder: v0.8.1, v0.9.0, v0.10.0, etc.
validations:
required: true
- type: input
id: Python-version
attributes:
label: Python Version
description: Version of Python interpreter
placeholder: 3.10, 3.11, 3.12 etc.
validations:
required: true
- type: input
id: OS
attributes:
label: Operating System
description: Operating System
placeholder: (Linux/Windows/Mac)
- type: textarea
id: version-info
attributes:
label: Versions
description: Output of ``zarr.print_debug_info()``. This will automatically be rendered as code, no need for backticks.
render: shell
placeholder: |
platform: macOS-15.3-arm64-arm-64bit-Mach-O
python: 3.13.2

zarr: 3.0.5

numcodecs: 0.15.1
numpy: 2.2.3
fsspec: 2025.3.0
validations:
required: true
- type: input
Expand Down
1 change: 1 addition & 0 deletions changes/2913.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a `print_debug_info` function for bug reports.
45 changes: 45 additions & 0 deletions src/zarr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,50 @@
# 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:
for package in packages:
try:
print(f"{package}: {version(package)}")
except ModuleNotFoundError:
continue

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()}\n")

print(f"zarr: {__version__}\n")
print("Required dependencies:")
print_packages(required)
print("Optional dependencies:")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print("Optional dependencies:")
print("Optional dependencies")
print("---------------------")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trouble with this is that it can render as a pagebreak in github markdown and turns the text above into an H2 text which I find a bit confusing for the flow of the isssue

How does using asterisks feel to you?

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't think about the "putting this into markdown on GitHub stage" 🤦 . In that case either asterisks or no change is fine by me 👍

print_packages(optional)


__all__ = [
"Array",
"AsyncArray",
Expand Down Expand Up @@ -65,6 +109,7 @@
"open_consolidated",
"open_group",
"open_like",
"print_debug_info",
"save",
"save_array",
"save_group",
Expand Down
18 changes: 18 additions & 0 deletions tests/test_zarr.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import pytest

import zarr


Expand All @@ -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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to make this test a bit more meaningful, let's capture the output and assert that it matches our basic expectations. https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html#accessing-captured-output-from-a-test-function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested two outputs that should always be there. I didn't test every output because at some point that just becomes rewriting the fucntion

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