This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new d27dc3e67 fix(bindings/python): fix type annotations and improve docs
(#3483)
d27dc3e67 is described below
commit d27dc3e67c9937dca2accd5669eadb5a0d9d5dfa
Author: messense <[email protected]>
AuthorDate: Sat Nov 4 12:02:53 2023 +0800
fix(bindings/python): fix type annotations and improve docs (#3483)
---
bindings/python/python/opendal/__init__.pyi | 22 ++++++-----
bindings/python/python/opendal/layers.pyi | 15 +++++---
bindings/python/src/capability.rs | 60 +++++++++++++++++++++++++++++
bindings/python/tests/test_async_delete.py | 2 +-
bindings/python/tests/test_read.py | 5 +++
5 files changed, 88 insertions(+), 16 deletions(-)
diff --git a/bindings/python/python/opendal/__init__.pyi
b/bindings/python/python/opendal/__init__.pyi
index 65ae74a21..7713e2a3c 100644
--- a/bindings/python/python/opendal/__init__.pyi
+++ b/bindings/python/python/opendal/__init__.pyi
@@ -17,6 +17,8 @@
from typing import AsyncIterable, Iterable, Optional
+from opendal.layers import Layer
+
class Error(Exception): ...
class Operator:
@@ -28,11 +30,11 @@ class Operator:
self,
path: str,
bs: bytes,
- append: bool = None,
- buffer: int = None,
- content_type: str = None,
- content_disposition: str = None,
- cache_control: str = None,
+ append: Optional[bool] = None,
+ buffer: Optional[int] = None,
+ content_type: Optional[str] = None,
+ content_disposition: Optional[str] = None,
+ cache_control: Optional[str] = None,
): ...
def stat(self, path: str) -> Metadata: ...
def create_dir(self, path: str): ...
@@ -53,11 +55,11 @@ class AsyncOperator:
self,
path: str,
bs: bytes,
- append: bool = None,
- buffer: int = None,
- content_type: str = None,
- content_disposition: str = None,
- cache_control: str = None,
+ append: Optional[bool] = None,
+ buffer: Optional[int] = None,
+ content_type: Optional[str] = None,
+ content_disposition: Optional[str] = None,
+ cache_control: Optional[str] = None,
): ...
async def stat(self, path: str) -> Metadata: ...
async def create_dir(self, path: str): ...
diff --git a/bindings/python/python/opendal/layers.pyi
b/bindings/python/python/opendal/layers.pyi
index bd2bc2e02..19a38d586 100644
--- a/bindings/python/python/opendal/layers.pyi
+++ b/bindings/python/python/opendal/layers.pyi
@@ -15,12 +15,17 @@
# specific language governing permissions and limitations
# under the License.
-class RetryLayer:
+from typing import Optional
+
+class Layer:
+ pass
+
+class RetryLayer(Layer):
def __init__(
self,
- max_times: int | None = None,
- factor: float | None = None,
+ max_times: Optional[int] = None,
+ factor: Optional[float] = None,
jitter: bool = False,
- max_delay: float | None = None,
- min_delay: float | None = None,
+ max_delay: Optional[float] = None,
+ min_delay: Optional[float] = None,
) -> None: ...
diff --git a/bindings/python/src/capability.rs
b/bindings/python/src/capability.rs
index f027199aa..373ea9599 100644
--- a/bindings/python/src/capability.rs
+++ b/bindings/python/src/capability.rs
@@ -17,47 +17,107 @@
use pyo3::prelude::*;
+/// Capability is used to describe what operations are supported
+/// by current Operator.
#[pyclass(get_all, module = "opendal")]
pub struct Capability {
+ /// If operator supports stat.
pub stat: bool,
+ /// If operator supports stat with if match.
pub stat_with_if_match: bool,
+ /// If operator supports stat with if none match.
pub stat_with_if_none_match: bool,
+
+ /// If operator supports read.
pub read: bool,
+ /// If operator supports seek on returning reader.
pub read_can_seek: bool,
+ /// If operator supports next on returning reader.
pub read_can_next: bool,
+ /// If operator supports read with range.
pub read_with_range: bool,
+ /// If operator supports read with if match.
pub read_with_if_match: bool,
+ /// If operator supports read with if none match.
pub read_with_if_none_match: bool,
+ /// if operator supports read with override cache control.
pub read_with_override_cache_control: bool,
+ /// if operator supports read with override content disposition.
pub read_with_override_content_disposition: bool,
+ /// if operator supports read with override content type.
pub read_with_override_content_type: bool,
+
+ /// If operator supports write.
pub write: bool,
+ /// If operator supports write can be called in multi times.
pub write_can_multi: bool,
+ /// If operator supports write with empty content.
pub write_can_empty: bool,
+ /// If operator supports write by append.
pub write_can_append: bool,
+ /// If operator supports write with content type.
pub write_with_content_type: bool,
+ /// If operator supports write with content disposition.
pub write_with_content_disposition: bool,
+ /// If operator supports write with cache control.
pub write_with_cache_control: bool,
+ /// write_multi_max_size is the max size that services support in
write_multi.
+ ///
+ /// For example, AWS S3 supports 5GiB as max in write_multi.
pub write_multi_max_size: Option<usize>,
+ /// write_multi_min_size is the min size that services support in
write_multi.
+ ///
+ /// For example, AWS S3 requires at least 5MiB in write_multi expect the
last one.
pub write_multi_min_size: Option<usize>,
+ /// write_multi_align_size is the align size that services required in
write_multi.
+ ///
+ /// For example, Google GCS requires align size to 256KiB in write_multi.
pub write_multi_align_size: Option<usize>,
+ /// write_total_max_size is the max size that services support in
write_total.
+ ///
+ /// For example, Cloudflare D1 supports 1MB as max in write_total.
pub write_total_max_size: Option<usize>,
+
+ /// If operator supports create dir.
pub create_dir: bool,
+
+ /// If operator supports delete.
pub delete: bool,
+
+ /// If operator supports copy.
pub copy: bool,
+
+ /// If operator supports rename.
pub rename: bool,
+
+ /// If operator supports list.
pub list: bool,
+ /// If backend supports list with limit.
pub list_with_limit: bool,
+ /// If backend supports list with start after.
pub list_with_start_after: bool,
+ /// If backend support list with using slash as delimiter.
pub list_with_delimiter_slash: bool,
+ /// If backend supports list without delimiter.
pub list_without_delimiter: bool,
+
+ /// If operator supports presign.
pub presign: bool,
+ /// If operator supports presign read.
pub presign_read: bool,
+ /// If operator supports presign stat.
pub presign_stat: bool,
+ /// If operator supports presign write.
pub presign_write: bool,
+
+ /// If operator supports batch.
pub batch: bool,
+ /// If operator supports batch delete.
pub batch_delete: bool,
+ /// The max operations that operator supports in batch.
pub batch_max_operations: Option<usize>,
+
+ /// If operator supports blocking.
pub blocking: bool,
}
diff --git a/bindings/python/tests/test_async_delete.py
b/bindings/python/tests/test_async_delete.py
index 9b230f0f8..07e94f85e 100644
--- a/bindings/python/tests/test_async_delete.py
+++ b/bindings/python/tests/test_async_delete.py
@@ -45,4 +45,4 @@ async def test_async_remove_all(service_name, operator,
async_operator):
if not path.endswith("/"):
with pytest.raises(FileNotFoundError) as e_info:
await async_operator.read(f"{parent}/{path}")
- await async_operator.remove_all(f"{parent}/")
\ No newline at end of file
+ await async_operator.remove_all(f"{parent}/")
diff --git a/bindings/python/tests/test_read.py
b/bindings/python/tests/test_read.py
index 95cde619e..62a424104 100644
--- a/bindings/python/tests/test_read.py
+++ b/bindings/python/tests/test_read.py
@@ -35,6 +35,7 @@ def test_sync_read(service_name, operator, async_operator):
operator.delete(filename)
+
@pytest.mark.need_capability("read", "write", "delete")
def test_sync_reader(service_name, operator, async_operator):
size = randint(1, 1024)
@@ -49,6 +50,7 @@ def test_sync_reader(service_name, operator, async_operator):
operator.delete(filename)
+
@pytest.mark.asyncio
@pytest.mark.need_capability("read", "write", "delete")
async def test_async_read(service_name, operator, async_operator):
@@ -63,6 +65,7 @@ async def test_async_read(service_name, operator,
async_operator):
await async_operator.delete(filename)
+
@pytest.mark.asyncio
@pytest.mark.need_capability("read", "write", "delete")
async def test_async_reader(service_name, operator, async_operator):
@@ -78,6 +81,7 @@ async def test_async_reader(service_name, operator,
async_operator):
await async_operator.delete(filename)
+
@pytest.mark.asyncio
@pytest.mark.need_capability("read", "write", "delete")
async def test_async_reader_without_context(service_name, operator,
async_operator):
@@ -94,6 +98,7 @@ async def test_async_reader_without_context(service_name,
operator, async_operat
await async_operator.delete(filename)
+
@pytest.mark.need_capability("read", "write", "delete", "stat")
def test_sync_read_stat(service_name, operator, async_operator):
size = randint(1, 1024)