Skip to content

Commit f8021ae

Browse files
committed
Fancier CTable.info printed representation
1 parent efbba8a commit f8021ae

3 files changed

Lines changed: 77 additions & 10 deletions

File tree

src/blosc2/ctable.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,40 +3099,39 @@ def info_items(self) -> list[tuple[str, object]]:
30993099
if stats is None:
31003100
suffix = "size=n/a (sidecars not directly addressable)"
31013101
else:
3102-
nbytes, cbytes, cratio = stats
3103-
suffix = (
3104-
f"nbytes={format_nbytes_info(nbytes)}, "
3105-
f"cbytes={format_nbytes_info(cbytes)}, cratio={cratio:.2f}x"
3106-
)
3102+
_, cbytes, _ = stats
3103+
suffix = f"cbytes={format_nbytes_info(cbytes)}"
31073104
index_summary[idx.col_name] = f"[{idx.kind}{stale}{label}] {suffix}"
31083105

31093106
items = [
31103107
("type", self.__class__.__name__),
31113108
("storage", storage_type),
31123109
("rows", self.nrows),
31133110
("columns", self.ncols),
3114-
("capacity", len(self._valid_rows)),
31153111
("view", self.base is not None),
3116-
("read_only", self._read_only),
31173112
("nbytes", format_nbytes_info(self.nbytes)),
31183113
("cbytes", format_nbytes_info(self.cbytes)),
3119-
("cratio", f"{self.cratio:.2f}"),
3114+
("cratio", f"{self.cratio:.1f}x"),
31203115
("schema", schema_summary),
31213116
(
31223117
"valid_rows_mask",
3123-
f"nbytes={format_nbytes_info(self._valid_rows.nbytes)}, cbytes={format_nbytes_info(self._valid_rows.cbytes)}",
3118+
f"cbytes={format_nbytes_info(self._valid_rows.cbytes)}",
31243119
),
31253120
("indexes", index_summary if index_summary else "none"),
31263121
]
31273122
if urlpath is not None:
31283123
items.insert(2, ("urlpath", urlpath))
3124+
open_mode = self._storage.open_mode()
3125+
if open_mode is not None:
3126+
items.insert(3, ("open_mode", open_mode))
31293127
return items
31303128

31313129
@staticmethod
31323130
def _dtype_info_label(dtype: np.dtype) -> str:
31333131
"""Return a compact dtype label for info reports."""
31343132
if dtype.kind == "U":
3135-
return f"U{dtype.itemsize // 4}"
3133+
nchars = dtype.itemsize // 4
3134+
return f"U{nchars} (Unicode, max {nchars} chars)"
31363135
if dtype.kind == "S":
31373136
return f"S{dtype.itemsize}"
31383137
return str(dtype)

src/blosc2/ctable_storage.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ def table_exists(self) -> bool:
8080
def is_read_only(self) -> bool:
8181
raise NotImplementedError
8282

83+
def open_mode(self) -> str | None:
84+
raise NotImplementedError
85+
8386
def delete_column(self, name: str) -> None:
8487
raise NotImplementedError
8588

@@ -162,6 +165,9 @@ def table_exists(self):
162165
def is_read_only(self):
163166
return False
164167

168+
def open_mode(self) -> str | None:
169+
return None
170+
165171
def delete_column(self, name):
166172
raise RuntimeError("In-memory tables have no on-disk representation to mutate.")
167173

@@ -269,6 +275,9 @@ def table_exists(self) -> bool:
269275
def is_read_only(self) -> bool:
270276
return self._mode == "r"
271277

278+
def open_mode(self) -> str | None:
279+
return self._mode
280+
272281
def create_column(self, name, *, dtype, shape, chunks, blocks, cparams, dparams):
273282
kwargs: dict[str, Any] = {
274283
"chunks": chunks,

tests/ctable/test_column.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,5 +685,64 @@ def test_column_repr_shows_preview_values():
685685
assert "..." in r
686686

687687

688+
def test_info_omits_capacity_and_read_only_for_in_memory_table():
689+
t = CTable(Row, new_data=DATA20)
690+
info = repr(t.info)
691+
assert "capacity" not in info
692+
assert "read_only" not in info
693+
assert "open_mode" not in info
694+
695+
696+
def test_info_shows_open_mode_for_persistent_table(tmp_path):
697+
path = str(tmp_path / "table.b2d")
698+
t = CTable(Row, new_data=DATA20, urlpath=path, mode="w")
699+
t.close()
700+
701+
opened = CTable.open(path)
702+
info = repr(opened.info)
703+
assert "capacity" not in info
704+
assert "read_only" not in info
705+
assert "open_mode : r" in info
706+
opened.close()
707+
708+
709+
def test_info_schema_expands_unicode_dtype_labels():
710+
t = CTable(StrRow, new_data=[("alpha",), ("beta",)])
711+
info = repr(t.info)
712+
assert "U16 (Unicode, max 16 chars)" in info
713+
714+
715+
def test_info_valid_rows_mask_only_reports_cbytes():
716+
t = CTable(Row, new_data=DATA20)
717+
info = repr(t.info)
718+
assert "valid_rows_mask : cbytes=" in info
719+
assert "valid_rows_mask : nbytes=" not in info
720+
721+
722+
def test_info_indexes_only_report_cbytes(tmp_path):
723+
@dataclass
724+
class IndexedRow:
725+
id: int = blosc2.field(blosc2.int32())
726+
active: bool = blosc2.field(blosc2.bool(), default=True)
727+
728+
data = [(i, i % 2 == 0) for i in range(32)]
729+
path = str(tmp_path / "indexed.b2d")
730+
t = CTable(IndexedRow, new_data=data, urlpath=path, mode="w")
731+
t.create_index("id", kind=blosc2.IndexKind.FULL)
732+
733+
info = repr(t.info)
734+
index_block = info.split("indexes :", 1)[1]
735+
assert "cbytes=" in index_block
736+
assert "nbytes=" not in index_block
737+
assert "cratio=" not in index_block
738+
739+
740+
def test_info_cratio_uses_one_decimal_with_suffix():
741+
t = CTable(Row, new_data=DATA20)
742+
info = repr(t.info)
743+
assert "cratio :" in info
744+
assert "x" in next(line for line in info.splitlines() if line.startswith("cratio"))
745+
746+
688747
if __name__ == "__main__":
689748
pytest.main(["-v", __file__])

0 commit comments

Comments
 (0)