Skip to content

Commit ed44274

Browse files
feat(bindings/python): add exists (#5637)
* try add exists * try add test * ruff + fix path * check file * fix test
1 parent a7b1c3c commit ed44274

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

bindings/python/python/opendal/__init__.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class Operator(_Base):
4545
def stat(self, path: PathBuf) -> Metadata: ...
4646
def create_dir(self, path: PathBuf) -> None: ...
4747
def delete(self, path: PathBuf) -> None: ...
48+
def exists(self, path: PathBuf) -> bool: ...
4849
def list(self, path: PathBuf) -> Iterable[Entry]: ...
4950
def scan(self, path: PathBuf) -> Iterable[Entry]: ...
5051
def capability(self) -> Capability: ...
@@ -72,6 +73,7 @@ class AsyncOperator(_Base):
7273
async def stat(self, path: PathBuf) -> Metadata: ...
7374
async def create_dir(self, path: PathBuf) -> None: ...
7475
async def delete(self, path: PathBuf) -> None: ...
76+
async def exists(self, path: PathBuf) -> bool: ...
7577
async def list(self, path: PathBuf) -> AsyncIterable[Entry]: ...
7678
async def scan(self, path: PathBuf) -> AsyncIterable[Entry]: ...
7779
async def presign_stat(

bindings/python/src/operator.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,16 @@ impl Operator {
198198
self.core.delete(&path).map_err(format_pyerr)
199199
}
200200

201+
/// Check given path is exists.
202+
///
203+
/// # Notes
204+
///
205+
/// - Check not existing path won't return errors.
206+
pub fn exists(&self, path: PathBuf) -> PyResult<bool> {
207+
let path = path.to_string_lossy().to_string();
208+
self.core.exists(&path).map_err(format_pyerr)
209+
}
210+
201211
/// List current dir path.
202212
pub fn list(&self, path: PathBuf) -> PyResult<BlockingLister> {
203213
let path = path.to_string_lossy().to_string();
@@ -460,6 +470,20 @@ impl AsyncOperator {
460470
)
461471
}
462472

473+
/// Check given path is exists.
474+
///
475+
/// # Notes
476+
///
477+
/// - Check not existing path won't return errors.
478+
pub fn exists<'p>(&'p self, py: Python<'p>, path: PathBuf) -> PyResult<Bound<'p, PyAny>> {
479+
let this = self.core.clone();
480+
let path = path.to_string_lossy().to_string();
481+
future_into_py(
482+
py,
483+
async move { this.exists(&path).await.map_err(format_pyerr) },
484+
)
485+
}
486+
463487
/// List current dir path.
464488
pub fn list<'p>(&'p self, py: Python<'p>, path: PathBuf) -> PyResult<Bound<'p, PyAny>> {
465489
let this = self.core.clone();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
import os
19+
from uuid import uuid4
20+
21+
import pytest
22+
23+
24+
@pytest.mark.asyncio
25+
@pytest.mark.need_capability("read", "write", "delete", "list", "create_dir")
26+
async def test_async_remove_all(service_name, operator, async_operator):
27+
content = os.urandom(1024)
28+
target = f"random_{str(uuid4())}"
29+
await async_operator.write(target, content)
30+
assert await async_operator.exists(target)
31+
assert not await async_operator.exists(target + "1")
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
import os
19+
from uuid import uuid4
20+
21+
import pytest
22+
23+
24+
@pytest.mark.need_capability(
25+
"read", "write", "delete", "list", "blocking", "create_dir"
26+
)
27+
def test_sync_exists(service_name, operator, async_operator):
28+
content = os.urandom(1024)
29+
target = f"random_{str(uuid4())}"
30+
operator.write(target, content)
31+
assert operator.exists(target)
32+
assert not operator.exists(target + "1")

0 commit comments

Comments
 (0)