Skip to content

Commit d3d5e49

Browse files
authored
Addition of Filestore API (#1070)
1 parent a91c673 commit d3d5e49

File tree

13 files changed

+611
-9
lines changed

13 files changed

+611
-9
lines changed

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# In Progress
2+
3+
## API Changes
4+
* Addition of Filestore API [#1070](https://github.com/TileDB-Inc/TileDB-Py/pull/1070)
15
# TileDB-Py 0.15.6 Release Notes
26

37
## TileDB Embedded updates:

doc/source/python-api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,14 @@ VFS
211211

212212
.. automethod:: __len__
213213

214+
Filestore
215+
---------
216+
217+
.. autoclass:: tiledb.Filestore
218+
:members:
219+
220+
.. automethod:: __len__
221+
214222
Version
215223
-------
216224

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
### DO NOT USE ON CI
2424

2525
# Target branch: Note that this should be set to the current core release, not `dev`
26-
TILEDB_VERSION = "2.9.5"
26+
TILEDB_VERSION = "2.10.0"
2727
# allow overriding w/ environment variable
2828
TILEDB_VERSION = os.environ.get("TILEDB_VERSION") or TILEDB_VERSION
2929

tiledb/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@
7878
ChecksumSHA256Filter,
7979
)
8080

81+
from .filestore import Filestore
82+
8183
from .fragment import (
8284
FragmentInfoList,
8385
FragmentInfo,

tiledb/cc/enum.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ void init_enums(py::module &m) {
8181
.value("INVALID", Object::Type::Invalid)
8282
.export_values();
8383

84+
#define DMENUM(x) .value(#x, TILEDB_MIME_##x)
85+
py::enum_<tiledb_mime_type_t>(m, "MIMEType") DMENUM(AUTODETECT) DMENUM(TIFF)
86+
DMENUM(PDF);
87+
8488
// test helpers to check enum name against typed value
8589
m.def("_enum_string", &tiledb::impl::type_to_str);
8690
m.def("_enum_string",

tiledb/cc/filestore.cc

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include <tiledb/tiledb>
2+
#include <tiledb/tiledb_experimental>
3+
4+
#include <pybind11/numpy.h>
5+
#include <pybind11/pybind11.h>
6+
#include <pybind11/pytypes.h>
7+
#include <pybind11/stl.h>
8+
9+
#include "common.h"
10+
11+
namespace libtiledbcpp {
12+
13+
using namespace tiledb;
14+
using namespace tiledbpy::common;
15+
namespace py = pybind11;
16+
17+
class Filestore {
18+
public:
19+
// TODO this works, but isn't actually in use at the moment.
20+
// we are still using tiledb.libtiledb.ArraySchema. when we switch to using
21+
// tiledb.cc.ArraySchema, use this function instead.
22+
static ArraySchema schema_create(const Context &ctx, const char *uri) {
23+
tiledb_array_schema_t *schema;
24+
tiledb_filestore_schema_create(ctx.ptr().get(), uri, &schema);
25+
return ArraySchema(ctx, py::capsule(schema));
26+
}
27+
28+
static void uri_import(const Context &ctx, const char *filestore_array_uri,
29+
const char *file_uri, tiledb_mime_type_t mime_type) {
30+
ctx.handle_error(tiledb_filestore_uri_import(
31+
ctx.ptr().get(), filestore_array_uri, file_uri, mime_type));
32+
}
33+
34+
static void uri_export(const Context &ctx, const char *filestore_array_uri,
35+
const char *file_uri) {
36+
ctx.handle_error(tiledb_filestore_uri_export(ctx.ptr().get(), file_uri,
37+
filestore_array_uri));
38+
}
39+
40+
static void buffer_import(const Context &ctx, const char *filestore_array_uri,
41+
py::buffer buf, tiledb_mime_type_t mime_type) {
42+
43+
py::buffer_info buffer = buf.request();
44+
ctx.handle_error(
45+
tiledb_filestore_buffer_import(ctx.ptr().get(), filestore_array_uri,
46+
buffer.ptr, py::len(buf), mime_type));
47+
}
48+
49+
static py::bytes buffer_export(const Context &ctx,
50+
const char *filestore_array_uri, size_t offset,
51+
size_t size) {
52+
py::array data = py::array(py::dtype::of<std::byte>(), size);
53+
py::buffer_info buffer = data.request();
54+
55+
ctx.handle_error(tiledb_filestore_buffer_export(
56+
ctx.ptr().get(), filestore_array_uri, offset, buffer.ptr, size));
57+
58+
auto np = py::module::import("numpy");
59+
auto to_bytes = np.attr("ndarray").attr("tobytes");
60+
61+
return to_bytes(data);
62+
}
63+
64+
static size_t size(const Context &ctx, const char *filestore_array_uri) {
65+
size_t size;
66+
ctx.handle_error(
67+
tiledb_filestore_size(ctx.ptr().get(), filestore_array_uri, &size));
68+
return size;
69+
}
70+
71+
static const char *mime_type_to_str(tiledb_mime_type_t mime_type) {
72+
const char *str;
73+
tiledb_mime_type_to_str(mime_type, &str);
74+
return str;
75+
}
76+
77+
static tiledb_mime_type_t mime_type_from_str(const char *str) {
78+
tiledb_mime_type_t mime_type;
79+
tiledb_mime_type_from_str(str, &mime_type);
80+
return mime_type;
81+
}
82+
};
83+
84+
void init_filestore(py::module &m) {
85+
py::class_<Filestore>(m, "Filestore")
86+
.def_static("_schema_create", &Filestore::schema_create)
87+
.def_static("_uri_import", &Filestore::uri_import)
88+
.def_static("_uri_export", &Filestore::uri_export)
89+
.def_static("_buffer_import", &Filestore::buffer_import)
90+
.def_static("_buffer_export", &Filestore::buffer_export)
91+
.def_static("_size", &Filestore::size)
92+
.def_static("_mime_type_to_str", &Filestore::mime_type_to_str)
93+
.def_static("_mime_type_from_str", &Filestore::mime_type_from_str);
94+
;
95+
};
96+
97+
}; // namespace libtiledbcpp

tiledb/cc/schema.cc

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@ namespace py = pybind11;
1212

1313
void init_schema(py::module &m) {
1414
py::class_<tiledb::ArraySchema>(m, "ArraySchema")
15-
.def(py::init<Context &, tiledb_array_type_t>(),
16-
py::keep_alive<1, 2>() /* ArraySchema keeps Context alive */)
17-
.def(py::init<Context &, std::string &>(),
18-
py::keep_alive<1, 2>() /* ArraySchema keeps Context alive */)
15+
.def(py::init<Context &, tiledb_array_type_t>(), py::keep_alive<1, 2>())
16+
.def(py::init<Context &, std::string &>(), py::keep_alive<1, 2>())
1917
.def(py::init<Context &, std::string &, tiledb_encryption_type_t,
2018
std::string &>(),
21-
py::keep_alive<1, 2>() /* ArraySchema keeps Context alive */)
22-
// TODO .def(py::init<Context, py::capsule>) // tiledb_array_schema_t*
23-
// signature
19+
py::keep_alive<1, 2>())
20+
.def(py::init<Context &, py::capsule>(), py::keep_alive<1, 2>())
2421

2522
.def("dump", &ArraySchema::dump) // TODO add FILE* signature support?
2623
.def("dump",

tiledb/cc/tests/test_filestore.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import os
2+
import pytest
3+
4+
import tiledb
5+
from tiledb import cc as lt
6+
7+
8+
@pytest.fixture
9+
def text_fname(tmp_path):
10+
path = os.path.join(tmp_path, "text_fname")
11+
vfs = tiledb.VFS()
12+
vfs.touch(path)
13+
with vfs.open(path, "wb") as fio:
14+
fio.write(b"Simple text file.\n")
15+
fio.write(b"With two lines.")
16+
return path
17+
18+
19+
def test_lt_schema_create(text_fname):
20+
ctx = lt.Context()
21+
schema = lt.Filestore._schema_create(ctx, text_fname)
22+
assert type(schema) == lt.ArraySchema
23+
24+
25+
def test_libtiledb_schema_create_buffer(tmp_path, text_fname):
26+
ctx = lt.Context()
27+
path = os.path.join(tmp_path, "test_libtiledb_schema_create_buffer")
28+
schema = tiledb.ArraySchema.from_file(text_fname)
29+
tiledb.Array.create(path, schema)
30+
31+
data = b"buffer"
32+
lt.Filestore._buffer_import(ctx, path, data, lt.MIMEType.AUTODETECT)
33+
assert bytes(data) == lt.Filestore._buffer_export(ctx, path, 0, len(data))
34+
assert lt.Filestore._size(ctx, path) == len(data)
35+
36+
output_file = os.path.join(tmp_path, "output_file")
37+
vfs = tiledb.VFS()
38+
vfs.touch(output_file)
39+
lt.Filestore._uri_export(ctx, path, output_file)
40+
with vfs.open(output_file, "rb") as fio:
41+
assert fio.read() == data
42+
43+
44+
def test_libtiledb_schema_create_uri(tmp_path, text_fname):
45+
ctx = lt.Context()
46+
path = os.path.join(tmp_path, "test_libtiledb_schema_create_uri")
47+
schema = tiledb.ArraySchema.from_file(text_fname)
48+
tiledb.Array.create(path, schema)
49+
50+
lt.Filestore._uri_import(ctx, path, text_fname, lt.MIMEType.AUTODETECT)
51+
with open(text_fname, "rb") as text:
52+
data = text.read()
53+
assert data == lt.Filestore._buffer_export(ctx, path, 0, len(data))
54+
assert lt.Filestore._size(ctx, path) == len(data)
55+
56+
57+
def test_mime_type():
58+
to_str = {
59+
lt.MIMEType.AUTODETECT: "AUTODETECT",
60+
lt.MIMEType.TIFF: "image/tiff",
61+
lt.MIMEType.PDF: "application/pdf",
62+
}
63+
64+
for k in to_str:
65+
assert lt.Filestore._mime_type_to_str(k) == to_str[k]
66+
67+
from_str = {
68+
"AUTODETECT": lt.MIMEType.AUTODETECT,
69+
"image/tiff": lt.MIMEType.TIFF,
70+
"application/pdf": lt.MIMEType.PDF,
71+
}
72+
73+
for k in from_str:
74+
assert lt.Filestore._mime_type_from_str(k) == from_str[k]

tiledb/cc/tiledbcpp.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ void init_config(py::module &);
2020
void init_enums(py::module &);
2121
void init_domain(py::module &m);
2222
void init_file_handle(py::module &);
23+
void init_filestore(py::module &m);
2324
void init_filter(py::module &);
2425
void init_group(py::module &);
2526
void init_object(py::module &m);
@@ -36,6 +37,7 @@ PYBIND11_MODULE(cc, m) {
3637
init_domain(m);
3738
init_enums(m);
3839
init_file_handle(m);
40+
init_filestore(m);
3941
init_filter(m);
4042
init_group(m);
4143
init_object(m);

0 commit comments

Comments
 (0)