Uncaught error during pretty print
After writing the object to disk, the pretty print functionality triggered by just displaying the sdata blobs object in a notebook runs into this uncaught error.
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/spatialdata/_core/spatialdata.py:1073, in SpatialData.elements_paths_on_disk(self)
1071 if self.path is None:
1072 raise ValueError("The SpatialData object is not backed by a Zarr store.")
-> 1073 store = parse_url(self.path, mode="r").store
1074 root = zarr.group(store=store)
1075 elements_in_zarr = []
AttributeError: 'NoneType' object has no attribute 'store'
The return value of parse_url() is None even though self.path is None didn't trigger.
Full traceback
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/IPython/core/formatters.py:770, in PlainTextFormatter.__call__(self, obj)
763 stream = StringIO()
764 printer = pretty.RepresentationPrinter(stream, self.verbose,
765 self.max_width, self.newline,
766 max_seq_length=self.max_seq_length,
767 singleton_pprinters=self.singleton_printers,
768 type_pprinters=self.type_printers,
769 deferred_pprinters=self.deferred_printers)
--> 770 printer.pretty(obj)
771 printer.flush()
772 return stream.getvalue()
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/IPython/lib/pretty.py:411, in RepresentationPrinter.pretty(self, obj)
400 return meth(obj, self, cycle)
401 if (
402 cls is not object
403 # check if cls defines __repr__
(...) 409 and callable(_safe_getattr(cls, "__repr__", None))
410 ):
--> 411 return _repr_pprint(obj, self, cycle)
413 return _default_pprint(obj, self, cycle)
414 finally:
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/IPython/lib/pretty.py:786, in _repr_pprint(obj, p, cycle)
784 """A pprint that just redirects to the normal repr function."""
785 # Find newlines and replace them with p.break_()
--> 786 output = repr(obj)
787 lines = output.splitlines()
788 with p.group():
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/spatialdata/_core/spatialdata.py:1971, in SpatialData.__repr__(self)
1970 def __repr__(self) -> str:
-> 1971 return self._gen_repr()
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/spatialdata/_core/spatialdata.py:2121, in SpatialData._gen_repr(self)
2118 descr += f"\n ▸ {element_name}: {backing_files}"
2120 if self.path is not None:
-> 2121 elements_only_in_sdata, elements_only_in_zarr = self._symmetric_difference_with_zarr_store()
2122 if len(elements_only_in_sdata) > 0:
2123 descr += "\nwith the following elements not in the Zarr store:"
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/spatialdata/_core/spatialdata.py:1105, in SpatialData._symmetric_difference_with_zarr_store(self)
1088 """
1089 Determine if elements in the SpatialData object are different from elements saved in the Zarr store.
1090
(...) 1102 The paths are relative to the root of the SpatialData object and are in the format "element_type/element_name".
1103 """
1104 elements_in_sdata = self.elements_paths_in_memory()
-> 1105 elements_in_zarr = self.elements_paths_on_disk()
1107 elements_only_in_sdata = list(set(elements_in_sdata).difference(set(elements_in_zarr)))
1108 elements_only_in_zarr = list(set(elements_in_zarr).difference(set(elements_in_sdata)))
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/spatialdata/_core/spatialdata.py:1073, in SpatialData.elements_paths_on_disk(self)
1071 if self.path is None:
1072 raise ValueError("The SpatialData object is not backed by a Zarr store.")
-> 1073 store = parse_url(self.path, mode="r").store
1074 root = zarr.group(store=store)
1075 elements_in_zarr = []
AttributeError: 'NoneType' object has no attribute 'store'
Immediately before this, I get this logging message from spatialdata:
INFO The Zarr backing store has been changed from None the new file path:
/home/runner/.cache/lamindb/l5UsjZhknzRYx1FV0000.zarr
When a SpatialData object is relocated on disk, its __repr__ method fails because it attempts to access files at the original location stored in spatialdata.path. For example in https://github.com/scverse/spatialdata/blob/eb5a20257b2fdb60eb3bad815b1ff43964f941c9/src/spatialdata/_core/spatialdata.py#L2119 it attempts to access data on disk but the spatialdata.path has changed.
A better approach would be to redesign the __repr__ to rely only on in-memory state, avoiding disk access entirely. This would make the representation more robust when objects are moved or when files are inaccessible.
Hi, I cannot reproduce the bug. I have tried with this code
from spatialdata.datasets import blobs
from tempfile import TemporaryDirectory
from pathlib import Path
with TemporaryDirectory() as tmp_dir:
sdata = blobs()
sdata.write(Path(tmp_dir) / "blobs.zarr")
print(sdata)
sdata.write(Path(tmp_dir) / "blobs2.zarr")
print(sdata)
Can you please adjust it to obtain the bug you found?