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
1 change: 0 additions & 1 deletion .github/workflows/release_java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ jobs:
run: |
./mvnw org.sonatype.plugins:nexus-staging-maven-plugin:deploy-staged \
-DaltStagingDirectory=$LOCAL_STAGING_DIR \
-DskipStagingRepositoryClose=true \
-DserverId=apache.releases.https \
-DnexusUrl=https://repository.apache.org
env:
Expand Down
6 changes: 6 additions & 0 deletions bindings/python/python/opendal/exceptions.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ class NotFound(builtins.Exception):
class PermissionDenied(builtins.Exception):
r"""Permission denied."""

class RateLimited(builtins.Exception):
r"""Rate limited."""

class RangeNotSatisfied(builtins.Exception):
r"""Range not satisfied."""

class Unexpected(builtins.Exception):
r"""Unexpected errors."""

Expand Down
9 changes: 9 additions & 0 deletions bindings/python/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ create_exception!(
PyException,
"Condition not match"
);
create_exception!(opendal.exceptions, RateLimited, PyException, "Rate limited");
create_exception!(
opendal.exceptions,
RangeNotSatisfied,
PyException,
"Range not satisfied"
);

fn format_pyerr_impl(err: &ocore::Error) -> PyErr {
let e = format!("{err:?}");
Expand All @@ -91,6 +98,8 @@ fn format_pyerr_impl(err: &ocore::Error) -> PyErr {
ocore::ErrorKind::AlreadyExists => AlreadyExists::new_err(e),
ocore::ErrorKind::IsSameFile => IsSameFile::new_err(e),
ocore::ErrorKind::ConditionNotMatch => ConditionNotMatch::new_err(e),
ocore::ErrorKind::RateLimited => RateLimited::new_err(e),
ocore::ErrorKind::RangeNotSatisfied => RangeNotSatisfied::new_err(e),
_ => Unexpected::new_err(e),
}
}
Expand Down
4 changes: 3 additions & 1 deletion bindings/python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ fn _opendal(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
NotADirectory,
AlreadyExists,
IsSameFile,
ConditionNotMatch
ConditionNotMatch,
RateLimited,
RangeNotSatisfied,
]
)?;
Ok(())
Expand Down
48 changes: 48 additions & 0 deletions bindings/python/tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,58 @@
import builtins
import inspect

import pytest

from opendal import exceptions


def test_exceptions():
for _name, obj in inspect.getmembers(exceptions):
if inspect.isclass(obj):
assert issubclass(obj, builtins.Exception)


def test_all_expected_exceptions_present():
"""Verify every expected exception class is present in opendal.exceptions."""
expected = [
"Error",
"Unexpected",
"Unsupported",
"ConfigInvalid",
"NotFound",
"PermissionDenied",
"IsADirectory",
"NotADirectory",
"AlreadyExists",
"IsSameFile",
"ConditionNotMatch",
"RateLimited",
"RangeNotSatisfied",
]
for name in expected:
assert hasattr(exceptions, name), f"exceptions.{name} is missing"
cls = getattr(exceptions, name)
assert inspect.isclass(cls), f"exceptions.{name} is not a class"
assert issubclass(cls, builtins.Exception), (
f"exceptions.{name} does not inherit from Exception"
)


def test_rate_limited_is_catchable():
"""RateLimited can be raised and caught like a standard exception."""
msg = "too many requests"
with pytest.raises(exceptions.RateLimited):
raise exceptions.RateLimited(msg)


def test_range_not_satisfied_is_catchable():
"""RangeNotSatisfied can be raised and caught like a standard exception."""
msg = "requested range not satisfiable"
with pytest.raises(exceptions.RangeNotSatisfied):
raise exceptions.RangeNotSatisfied(msg)


def test_exceptions_are_distinct():
"""RateLimited and RangeNotSatisfied must not accidentally catch each other."""
assert not issubclass(exceptions.RateLimited, exceptions.RangeNotSatisfied)
assert not issubclass(exceptions.RangeNotSatisfied, exceptions.RateLimited)
Loading