opendal.__init__ now only re-exports the capability, exceptions, file, layers, services, types, Operator, and AsyncOperator symbols. Imports such as:
from opendal import Metadata, Layerno longer work. Update them to use the dedicated submodules:
from opendal.types import Metadata
from opendal.layers import LayerThe legacy helper module opendal.__base has also been removed together with _Base.
Both Operator.full_capability() and AsyncOperator.full_capability() have been renamed to capability(). Adjust your code accordingly:
-caps = op.full_capability()
+caps = op.capability()The constructors for Operator / AsyncOperator provide overloads that accept opendal.services.Scheme members. While plain strings are still accepted at runtime, type checkers (pyright/mypy) expect the new enum values. Migrate code bases that relied on importing the old Scheme enum from opendal to from opendal import services and use services.Scheme.<NAME>.
OpenDAL has removed the native blocking API in the core. The Python binding's blocking API now uses an async runtime internally. This is a transparent change and should not affect most users, but:
- The blocking API now requires an async runtime to be available
- Performance characteristics may be slightly different
- All blocking operations are now implemented as async operations running in a tokio runtime
The following services have been removed due to lack of maintainers and users:
atomicserver- This service is no longer supportedicloud- This service is no longer supportednebula-graph- This service is no longer supported
If you were using any of these services, you'll need to migrate to an alternative storage backend.
The Chainsafe service has been sunset and is no longer available.
Because of a TLS lib issue, we temporarily disable the services-ftp feature.
Operator and BlockingOperator won't accept layers anymore. Instead, we provide a layer API:
op = opendal.Operator("memory").layer(opendal.layers.RetryLayer())We removed not used layers ConcurrentLimitLayer and ImmutableIndexLayer along with this change.
OpenDAL removes Reader and AsyncReader classes, instead, we provide file-like object File and AsyncFile.
Open a file for reading in blocking way:
with op.open(filename, "rb") as r:
content = r.read()
# With read options
with op.open(filename, "rb", offset=1024, size=2048) as r:
content = r.read()Open a file for reading in async way:
async with await op.open(filename, "rb") as r:
content = await r.read()
# With read options
async with await op.open(filename, "rb", offset=1024, size=2048) as r:
content = await r.read()Open a file for writing:
# Blocking write
with op.open(filename, "wb") as w:
w.write(b"hello world")
# With write options
with op.open(filename, "wb", content_type="text/plain", if_not_exists=True) as w:
w.write(b"hello world")
# Async write
async with await op.open(filename, "wb") as w:
await w.write(b"hello world")We remove the old error classes and provide a couple of Exception based class for the error handling.
opendal.Erroris based class for all the exceptions now.opendal.exceptions.Unexpectedis added.opendal.exceptions.Unsupportedis added.opendal.exceptions.ConfigInvalidis added.opendal.exceptions.NotFoundis added.opendal.exceptions.PermissionDeniedis added.opendal.exceptions.IsADirectoryis added.opendal.exceptions.NotADirectoryis added.opendal.exceptions.AlreadyExistsis added.opendal.exceptions.IsSameFileis added.opendal.exceptions.ConditionNotMatchis added.opendal.exceptions.ContentTruncatedis added.opendal.exceptions.ContentIncompleteis added.opendal.exceptions.InvalidInputis added.