Skip to content

from_array silently discards the source array's fill_value and attributes #4287

Description

@paraseba

Zarr version

3.3.1.dev34+gd44f9f92

Numcodecs version

0.16.5

Python Version

3.12

Operating System

Linux

Installation

uv run with zarr installed from git main

Description

zarr.from_array documents both fill_value and attributes as defaulting to the
source array's values, but it discards both, using the dtype's default scalar and {}
instead.

Expected vs. actual

Copying an array created with fill_value=42 and attributes={"units": "K"}:

source from_array copy expected
fill_value 42 0 42
attributes {"units": "K"} {} {"units": "K"}

Every other keep-parameter already defaults to the source
array. These two are the exception.

Affected versions

The fill_value defect is a regression from #3198 (released in 3.1.0), which
introduced the DEFAULT_FILL_VALUE sentinel. The line is unchanged since, so
3.1.0 through main are affected.

The attributes defect is not a regression — it has been present since from_array
was added.

Steps to reproduce

# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "zarr@git+https://github.com/zarr-developers/zarr-python.git@main",
# ]
# ///
#
# This script automatically imports the development branch of zarr to check for issues

import zarr

src = zarr.create_array({}, shape=(4,), dtype="int32", fill_value=42, attributes={"units": "K"})

copy = zarr.from_array({}, data=src)
print(f"fill_value: {copy.fill_value}      expected 42")
print(f"attrs:      {dict(copy.attrs)}     expected {{'units': 'K'}}")

# The fill value is not just metadata: it decides what unwritten regions read.
meta_only = zarr.from_array({}, data=src, write_data=False)
print(f"write_data=False reads: {meta_only[:]}   expected [42 42 42 42]")

# An explicit None *does* keep the source's fill value -- the exact inverse.
explicit_none = zarr.from_array({}, data=src, fill_value=None)
print(f"fill_value=None:  {explicit_none.fill_value}      keeps 42, inverted")

assert copy.fill_value == 42, "BUG: fill_value not kept"

Additional output

fill_value: 0      expected 42
attrs:      {}     expected {'units': 'K'}
write_data=False reads: [0 0 0 0]   expected [42 42 42 42]
fill_value=None:  42      keeps 42, inverted
AssertionError: BUG: fill_value not kept

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugPotential issues with the zarr-python library

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions