Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ members = [
"vortex-flatbuffers",
"vortex-metrics",
"vortex-io",
"vortex-object-store-opendal",
"vortex-proto",
"vortex-array",
"vortex-arrow",
Expand Down
1 change: 1 addition & 0 deletions docs/api/python/store.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Vortex arrays support reading and writing to many object storage systems:
store/http
store/local
store/memory
store/opendal
store/config

.. autofunction:: vortex.store.from_url
87 changes: 87 additions & 0 deletions docs/api/python/store/opendal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
=============
OpenDAL (COS)
=============

Vortex can read from and write to Tencent Cloud COS through
`OpenDAL <https://opendal.apache.org/>`_, which provides native service support.

This store is available only when Vortex is built with the ``opendal`` feature
(e.g. ``maturin develop --features opendal`` or ``cargo build -p vortex-jni --features opendal``).

:class:`vortex.store.CosStore`
==============================

.. py:class:: vortex.store.CosStore(bucket, endpoint, *, secret_id=None, secret_key=None, root=None, disable_config_load=False)

A Tencent Cloud COS object store, backed by OpenDAL. Construct it with explicit
configuration and pass it to
:func:`vortex.io.read_url` / :func:`vortex.io.write` via the ``store=`` argument,
exactly like the built-in S3/Azure/GCS stores.

The class is only available when Vortex is built with the ``opendal`` feature; on
a default build, instantiating it raises :class:`ImportError`.

:param bucket: COS bucket name (e.g. ``"my-bucket"``).
:param endpoint: COS endpoint (e.g. ``"https://cos.ap-guangzhou.myqcloud.com"``).
:param secret_id: Optional Tencent Cloud secret id. Maps to the ``TENCENTCLOUD_SECRET_ID``
environment variable when unset.
:param secret_key: Optional Tencent Cloud secret key. Maps to the
``TENCENTCLOUD_SECRET_KEY`` environment variable when unset.
:param root: Optional key prefix applied to every operation.
:param disable_config_load: When ``True``, disable OpenDAL's automatic config loading
and rely only on the explicit configuration. Defaults to ``False``.

Reading from COS
================

Pass a ``cos://`` URL directly. Credentials and the endpoint are picked up from the environment
variables OpenDAL's COS builder reads (``TENCENTCLOUD_SECRET_ID``, ``TENCENTCLOUD_SECRET_KEY`` and
``COS_ENDPOINT``):

.. code-block:: python

import vortex as vx

a = vx.io.read_url("cos://my-bucket/path/to/dataset.vortex")

Or configure explicitly with :class:`~vortex.store.CosStore` and pass it to
:func:`vortex.io.read_url` via ``store=``:

.. code-block:: python

from vortex.io import read_url
from vortex.store import CosStore

store = CosStore(
bucket="my-bucket",
endpoint="https://cos.ap-guangzhou.myqcloud.com",
secret_id="AKID...",
secret_key="...",
)

# When `store=` is supplied, the path is a key within the store, so the scheme and
# bucket are not part of the path passed to read_url.
a = read_url("path/to/dataset.vortex", store=store)

Passing a store object directly
===============================

``CosStore`` is a concrete store object. You can build one once and pass it
directly to :func:`vortex.io.read_url` / :func:`vortex.io.write` via the ``store=`` argument,
exactly like the built-in S3/Azure/GCS stores:

.. code-block:: python

from vortex.io import read_url
from vortex.store import CosStore

store = CosStore(
bucket="my-bucket",
endpoint="https://cos.ap-guangzhou.myqcloud.com",
secret_id="AKID...",
secret_key="...",
)

# When `store=` is supplied, the path is resolved as a key within the store, so the scheme
# and bucket are not part of the path passed to read_url.
a = read_url("path/to/dataset.vortex", store=store)
7 changes: 6 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@
git_root = Path(__file__).parent.parent

nitpicky = True # ensures all :class:, :obj:, etc. links are valid
nitpick_ignore = []
nitpick_ignore = [
# `vortex.store.CosStore` is re-exported through the private `vortex.store._cos` module,
# and the `ObjectStore` type alias resolves to the private path. The public class is
# fully documented in `opendal.rst`; the private path is intentionally not.
("py:class", "vortex.store._cos.CosStore"),
]

doctest_global_setup = "import pyarrow; import vortex; import vortex as vx; import random; random.seed(a=0)"
doctest_default_flags = (
Expand Down
6 changes: 6 additions & 0 deletions vortex-jni/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,17 @@ url = { workspace = true }
vortex = { workspace = true, features = ["object_store", "files"] }
vortex-arrow = { workspace = true }
vortex-geo = { workspace = true }
vortex-object-store-opendal = { path = "../vortex-object-store-opendal", optional = true }
vortex-parquet-variant = { workspace = true }

[dev-dependencies]
jni = { workspace = true, features = ["invocation"] }

[features]
# Enable OpenDAL-backed object stores (Tencent COS) for `cos://` URLs. This pulls in the
# `opendal` dependency, so it is opt-in.
opendal = ["dep:vortex-object-store-opendal"]

[lib]
crate-type = ["cdylib"]

Expand Down
Loading
Loading