diff --git a/tiledb/array_schema.py b/tiledb/array_schema.py index 55fcd0c70d..260a0f337f 100644 --- a/tiledb/array_schema.py +++ b/tiledb/array_schema.py @@ -13,6 +13,25 @@ from .domain import Domain from .filter import Filter, FilterList +_tiledb_order_to_string = { + lt.LayoutType.ROW_MAJOR: "row-major", + lt.LayoutType.COL_MAJOR: "col-major", + lt.LayoutType.GLOBAL_ORDER: "global", + lt.LayoutType.UNORDERED: "unordered", + lt.LayoutType.HILBERT: "hilbert", +} + +_string_to_tiledb_order = {v: k for k, v in _tiledb_order_to_string.items()} +_string_to_tiledb_order.update( + { + "C": lt.LayoutType.ROW_MAJOR, + "R": lt.LayoutType.COL_MAJOR, + "H": lt.LayoutType.HILBERT, + "U": lt.LayoutType.UNORDERED, + None: lt.LayoutType.ROW_MAJOR, # default (fixed in SC-27374) + } +) + class ArraySchema(CtxMixin, lt.ArraySchema): """ @@ -68,12 +87,14 @@ def __init__( ) self._add_attr(att) - self._cell_order = _string_to_tiledb_order.get(cell_order) - if self._cell_order is None: + try: + self._cell_order = _string_to_tiledb_order.get(cell_order) + except (TypeError, ValueError): raise ValueError(f"unknown tiledb layout: {cell_order}") - self._tile_order = _string_to_tiledb_order.get(tile_order) - if self._tile_order is None: + try: + self._tile_order = _string_to_tiledb_order.get(tile_order) + except (TypeError, ValueError): raise ValueError(f"unknown tiledb layout: {tile_order}") if capacity > 0: @@ -384,6 +405,16 @@ def dump(self): print(self._dump(), "\n") def __repr__(self): + # use safe repr if pybind11 constructor failed or the array schema did + # not construct properly + try: + self._check() + except lt.TileDBError: + return object.__repr__(self) + + if self._ctx is None: + return object.__repr__(self) + # TODO support/use __qualname__ output = io.StringIO() output.write("ArraySchema(\n") @@ -454,23 +485,3 @@ def _repr_html_(self): output.write("") return output.getvalue() - - -_tiledb_order_to_string = { - lt.LayoutType.ROW_MAJOR: "row-major", - lt.LayoutType.COL_MAJOR: "col-major", - lt.LayoutType.GLOBAL_ORDER: "global", - lt.LayoutType.UNORDERED: "unordered", - lt.LayoutType.HILBERT: "hilbert", -} - -_string_to_tiledb_order = {v: k for k, v in _tiledb_order_to_string.items()} -_string_to_tiledb_order.update( - { - "C": lt.LayoutType.ROW_MAJOR, - "R": lt.LayoutType.COL_MAJOR, - "H": lt.LayoutType.HILBERT, - "U": lt.LayoutType.UNORDERED, - None: lt.LayoutType.ROW_MAJOR, # default (fixed in SC-27374) - } -) diff --git a/tiledb/attribute.py b/tiledb/attribute.py index 94c510615b..3b0d2dc975 100644 --- a/tiledb/attribute.py +++ b/tiledb/attribute.py @@ -259,6 +259,10 @@ def enum_label(self): return self._get_enumeration_name(self._ctx) def __repr__(self): + # use safe repr if pybind11 constructor failed + if self._ctx is None: + return object.__repr__(self) + filters_str = "" if self.filters: filters_str = ", filters=FilterList([" diff --git a/tiledb/dimension.py b/tiledb/dimension.py index f29bbefe9c..1e5eb35279 100644 --- a/tiledb/dimension.py +++ b/tiledb/dimension.py @@ -85,6 +85,10 @@ def __init__( self._filters = FilterList(filters) def __repr__(self) -> str: + # use safe repr if pybind11 constructor failed + if self._ctx is None: + return object.__repr__(self) + filters_str = "" if self.filters: filters_str = ", filters=FilterList([" diff --git a/tiledb/domain.py b/tiledb/domain.py index 8f341af13f..a5f4271cd6 100644 --- a/tiledb/domain.py +++ b/tiledb/domain.py @@ -64,6 +64,10 @@ def clone_dim_with_name(dim, name): self._add_dim(d) def __repr__(self): + # use safe repr if pybind11 constructor failed + if self._ctx is None: + return object.__repr__(self) + dims = ",\n ".join(repr(self.dim(i)) for i in range(self.ndim)) return "Domain({0!s})".format(dims) diff --git a/tiledb/enumeration.py b/tiledb/enumeration.py index bb63a12c0c..2f6a3b9cc9 100644 --- a/tiledb/enumeration.py +++ b/tiledb/enumeration.py @@ -127,6 +127,10 @@ def __eq__(self, other): ) def __repr__(self): + # use safe repr if pybind11 constructor failed + if self._ctx is None: + return object.__repr__(self) + return f"Enumeration(name='{self.name}', cell_val_num={self.cell_val_num}, ordered={self.ordered}, values={list(self.values())})" def _repr_html_(self): diff --git a/tiledb/filter.py b/tiledb/filter.py index 0ef2fc6947..871a8cf0a5 100644 --- a/tiledb/filter.py +++ b/tiledb/filter.py @@ -18,6 +18,10 @@ def __init__(self, type: lt.FilterOption, ctx: Optional[Ctx] = None): super().__init__(ctx, type) def __repr__(self) -> str: + # use safe repr if pybind11 constructor failed + if self._ctx is None: + return object.__repr__(self) + output = io.StringIO() output.write(f"{type(self).__name__}(") if hasattr(self, "_attrs_"): diff --git a/tiledb/group.py b/tiledb/group.py index a3435565e2..37c8447070 100644 --- a/tiledb/group.py +++ b/tiledb/group.py @@ -230,6 +230,10 @@ def __iter__(self): yield key def __repr__(self): + # use safe repr if pybind11 constructor failed + if self._ctx is None: + return object.__repr__(self) + return str(dict(self._iter(keys_only=False))) def setdefault(self, key, default=None): diff --git a/tiledb/tests/test_array_schema.py b/tiledb/tests/test_array_schema.py index 6375778f75..d8bff6bc2b 100644 --- a/tiledb/tests/test_array_schema.py +++ b/tiledb/tests/test_array_schema.py @@ -75,6 +75,16 @@ def test_dense_array_schema_fp_domain_error(self): with self.assertRaises(tiledb.TileDBError): tiledb.ArraySchema(domain=dom, attrs=(att,)) + def test_dense_array_schema_invalid_cell_and_tile_order(self): + dom = tiledb.Domain(tiledb.Dim(domain=(1, 8), tile=2, dtype=np.float64)) + att = tiledb.Attr("val", dtype=np.float64) + + with self.assertRaises(ValueError): + tiledb.ArraySchema(domain=dom, attrs=(att,), cell_order="invalid") + + with self.assertRaises(ValueError): + tiledb.ArraySchema(domain=dom, attrs=(att,), tile_order="invalid") + def test_sparse_schema(self): # create dimensions d1 = tiledb.Dim("d1", domain=(1, 1000), tile=10, dtype="uint64")