Skip to content

Commit

Permalink
Move Domain and Dim Into Pure Python (2/3) (#1327)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenv committed Dec 21, 2022
1 parent 0d04dc9 commit 4394fb3
Show file tree
Hide file tree
Showing 17 changed files with 1,020 additions and 969 deletions.
4 changes: 4 additions & 0 deletions HISTORY.md
@@ -1,5 +1,8 @@
# In Progress

## Improvements
* Move `Dim` and `Domain` from Cython to pure Python [#1327](https://github.com/TileDB-Inc/TileDB-Py/pull/1327)

## Bug Fixes
* Ensure NumPy array matches array schema dimensions for dense writes [#1514](https://github.com/TileDB-Inc/TileDB-Py/pull/1514)

Expand Down Expand Up @@ -104,6 +107,7 @@

## Improvements
* Move `Attr` from Cython to pure Python [#1326](https://github.com/TileDB-Inc/TileDB-Py/pull/1326)
* Move `Domain` and `Dim` from Cython to pure Python [#1327](https://github.com/TileDB-Inc/TileDB-Py/pull/1327)

## API Changes
* Permit true-ASCII attributes in non-from-pandas dataframes [#1337](https://github.com/TileDB-Inc/TileDB-Py/pull/1337)
Expand Down
10 changes: 5 additions & 5 deletions tiledb/cc/attribute.cc
Expand Up @@ -41,14 +41,14 @@ py::array get_fill_value(Attribute &attr) {

void init_attribute(py::module &m) {
py::class_<tiledb::Attribute>(m, "Attribute")
.def(py::init<Context &, std::string &, tiledb_datatype_t>(),
py::keep_alive<1, 2>())
.def(py::init<Attribute>())

.def(py::init<Context &, std::string &, tiledb_datatype_t>())

.def(
py::init<Context &, std::string &, tiledb_datatype_t, FilterList &>(),
py::keep_alive<1, 2>())
py::init<Context &, std::string &, tiledb_datatype_t, FilterList &>())

.def(py::init<const Context &, py::capsule>(), py::keep_alive<1, 2>())
.def(py::init<const Context &, py::capsule>())

.def("__capsule__",
[](Attribute &attr) {
Expand Down
225 changes: 182 additions & 43 deletions tiledb/cc/domain.cc
Expand Up @@ -14,57 +14,196 @@ using namespace tiledbpy::common;
namespace py = pybind11;

void init_domain(py::module &m) {
py::class_<tiledb::Dimension>(m, "Dimension")
.def("create",
[](const Context &ctx, const std::string &name,
tiledb_datatype_t datatype, py::buffer range, py::buffer extent) {
auto range_info = range.request();
auto extent_info = extent.request();
if (datatype != TILEDB_STRING_ASCII) {
if (!expect_buffer_nbytes(range_info, datatype, 2)) {
throw py::value_error(
"Unexpected type/shape for range buffer!");
}
if (!expect_buffer_nbytes(extent_info, datatype, 1)) {
throw py::value_error(
"Unexpected type/shape for range buffer!");
}
py::class_<Dimension>(m, "Dimension")
.def(py::init<Dimension>())

.def(py::init([](const Context &ctx, const std::string &name,
tiledb_datatype_t datatype, py::object domain,
py::object tile_extent) {
void *dim_dom = nullptr;
void *dim_tile = nullptr;

if (!domain.is_none()) {
py::buffer domain_buffer = py::buffer(domain);
py::buffer_info domain_info = domain_buffer.request();
dim_dom = domain_info.ptr;
}

if (!tile_extent.is_none()) {
py::buffer tile_buffer = py::buffer(tile_extent);
py::buffer_info tile_extent_info = tile_buffer.request();
dim_tile = tile_extent_info.ptr;
}

const void *range_data =
(datatype != TILEDB_STRING_ASCII) ? range_info.ptr : nullptr;
const void *extent_data =
(datatype != TILEDB_STRING_ASCII) ? extent_info.ptr : nullptr;
return std::make_unique<Dimension>(
Dimension::create(ctx, name, datatype, dim_dom, dim_tile));
}),
py::keep_alive<1, 2>())

return std::make_unique<Dimension>(Dimension::create(
ctx, name, datatype, range_data, extent_data));
})
.def_property_readonly("name", &Dimension::name)
// .def_property_readonly("domain", &Dimension::domain)
// .def_property_readonly("tile", &Dimension::tile_extent)
.def_property("filters", &Dimension::filter_list,
.def(py::init<const Context &, py::capsule>(), py::keep_alive<1, 2>())

.def_property_readonly("_name", &Dimension::name)

.def_property_readonly(
"_domain",
[](Dimension &dim) {
switch (dim.type()) {
case TILEDB_UINT64: {
auto dom = dim.domain<uint64_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_DATETIME_YEAR:
case TILEDB_DATETIME_MONTH:
case TILEDB_DATETIME_WEEK:
case TILEDB_DATETIME_DAY:
case TILEDB_DATETIME_HR:
case TILEDB_DATETIME_MIN:
case TILEDB_DATETIME_SEC:
case TILEDB_DATETIME_MS:
case TILEDB_DATETIME_US:
case TILEDB_DATETIME_NS:
case TILEDB_DATETIME_PS:
case TILEDB_DATETIME_FS:
case TILEDB_DATETIME_AS:
case TILEDB_INT64: {
auto dom = dim.domain<int64_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_UINT32: {
auto dom = dim.domain<uint32_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_INT32: {
auto dom = dim.domain<int32_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_UINT16: {
auto dom = dim.domain<uint16_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_INT16: {
auto dom = dim.domain<int16_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_UINT8: {
auto dom = dim.domain<uint8_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_INT8: {
auto dom = dim.domain<int8_t>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_FLOAT64: {
auto dom = dim.domain<double>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_FLOAT32: {
auto dom = dim.domain<float>();
return py::make_tuple(dom.first, dom.second);
}
case TILEDB_STRING_ASCII: {
return py::make_tuple("", "");
}
default:
TPY_ERROR_LOC("Unsupported dtype for Dimension's domain");
}
})

.def_property_readonly(
"_tile",
[](Dimension &dim) -> py::object {
switch (dim.type()) {
case TILEDB_UINT64: {
return py::cast(dim.tile_extent<uint64_t>());
}
case TILEDB_DATETIME_YEAR:
case TILEDB_DATETIME_MONTH:
case TILEDB_DATETIME_WEEK:
case TILEDB_DATETIME_DAY:
case TILEDB_DATETIME_HR:
case TILEDB_DATETIME_MIN:
case TILEDB_DATETIME_SEC:
case TILEDB_DATETIME_MS:
case TILEDB_DATETIME_US:
case TILEDB_DATETIME_NS:
case TILEDB_DATETIME_PS:
case TILEDB_DATETIME_FS:
case TILEDB_DATETIME_AS:
case TILEDB_INT64: {
return py::cast(dim.tile_extent<int64_t>());
}
case TILEDB_UINT32: {
return py::cast(dim.tile_extent<uint32_t>());
}
case TILEDB_INT32: {
return py::cast(dim.tile_extent<int32_t>());
}
case TILEDB_UINT16: {
return py::cast(dim.tile_extent<uint16_t>());
}
case TILEDB_INT16: {
return py::cast(dim.tile_extent<int16_t>());
}
case TILEDB_UINT8: {
return py::cast(dim.tile_extent<uint8_t>());
}
case TILEDB_INT8: {
return py::cast(dim.tile_extent<int8_t>());
}
case TILEDB_FLOAT64: {
return py::cast(dim.tile_extent<double>());
}
case TILEDB_FLOAT32: {
return py::cast(dim.tile_extent<float>());
}
case TILEDB_STRING_ASCII: {
return py::none();
}
default:
TPY_ERROR_LOC("Unsupported dtype for Dimension's tile extent");
}
})

.def_property("_filters", &Dimension::filter_list,
&Dimension::set_filter_list)
.def_property("ncell", &Dimension::cell_val_num,

.def_property("_ncell", &Dimension::cell_val_num,
&Dimension::set_cell_val_num)
.def("tiledb_datatype", &Dimension::type)
// TODO needs numpy <> tiledb type and void*+(type,size) -> numpy
// translators
.def("domain_to_str", &Dimension::domain_to_str);

py::class_<tiledb::Domain>(m, "Domain")
.def(py::init<Context &>(),
py::keep_alive<1, 2>() /* ArraySchema keeps Context alive */)
.def_property_readonly("_tiledb_dtype", &Dimension::type)

.def("_domain_to_str", &Dimension::domain_to_str);

py::class_<Domain>(m, "Domain")
.def(py::init<Domain>())

.def_property_readonly("ncell",
.def(py::init<Context &>())

.def(py::init<const Context &, py::capsule>())

.def("__capsule__",
[](Domain &dom) {
return py::capsule(dom.ptr().get(), "dom", nullptr);
})

.def_property_readonly("_ncell",
[](Domain &dom) { return dom.cell_num(); })
.def_property_readonly("dtype", &Domain::type)
.def_property_readonly("ndim", &Domain::ndim)
.def_property_readonly("dims", &Domain::dimensions)

.def("dim", py::overload_cast<unsigned>(&Domain::dimension, py::const_))
.def("dim", py::overload_cast<const std::string &>(&Domain::dimension,
py::const_))
.def("add_dim", &Domain::add_dimension);

.def_property_readonly("_tiledb_dtype", &Domain::type)

.def_property_readonly("_ndim", &Domain::ndim)

.def_property_readonly("_dims", &Domain::dimensions)

.def("_dim", py::overload_cast<unsigned>(&Domain::dimension, py::const_))
.def("_dim", py::overload_cast<const std::string &>(&Domain::dimension,
py::const_))

.def("_has_dim", &Domain::has_dimension)

.def("_add_dim", &Domain::add_dimension, py::keep_alive<1, 2>())

.def("_dump", [](Domain &dom) { dom.dump(); });
}

} // namespace libtiledbcpp
7 changes: 3 additions & 4 deletions tiledb/cc/filter.cc
Expand Up @@ -16,8 +16,7 @@ namespace py = pybind11;

void init_filter(py::module &m) {
py::class_<Filter>(m, "Filter")
.def(py::init<const Context &, tiledb_filter_type_t>(),
py::keep_alive<1, 2>())
.def(py::init<const Context &, tiledb_filter_type_t>())

.def_property_readonly("_type", &Filter::filter_type)

Expand Down Expand Up @@ -111,8 +110,8 @@ void init_filter(py::module &m) {

py::class_<FilterList>(m, "FilterList")
.def(py::init<FilterList>())
.def(py::init<const Context &>(), py::keep_alive<1, 2>())
.def(py::init<const Context &, py::capsule>(), py::keep_alive<1, 2>())
.def(py::init<const Context &>())
.def(py::init<const Context &, py::capsule>())

.def("__capsule__",
[](FilterList &filterlist) {
Expand Down
3 changes: 1 addition & 2 deletions tiledb/core.cc
Expand Up @@ -1628,8 +1628,7 @@ void init_core(py::module &m) {
auto pq =
py::class_<PyQuery>(m, "PyQuery")
.def(py::init<const Context &, py::object, py::iterable, py::iterable,
py::object, py::object>(),
py::keep_alive<1, 2>())
py::object, py::object>())
.def("buffer_dtype", &PyQuery::buffer_dtype)
.def("results", &PyQuery::results)
.def("set_ranges", &PyQuery::set_ranges)
Expand Down

0 comments on commit 4394fb3

Please sign in to comment.