Adapters & types¶
Bridges between the synchronous and asynchronous backend worlds, plus the
async content type alias. The adapters let a sync backend run under
AsyncStore and an async backend run under the synchronous
Store. See Async-sync bridges
for when to reach for each.
SyncBackendAdapter¶
Wraps any synchronous Backend as an AsyncBackend by dispatching each
blocking call to the default executor via asyncio.to_thread. AsyncStore
auto-wraps sync backends on construction; explicit construction is only
required when you want to introspect the adapter.
SyncBackendAdapter
¶
SyncBackendAdapter(backend: Backend)
Wraps a synchronous Backend as an AsyncBackend.
Every blocking call is dispatched to the default executor via
asyncio.to_thread, keeping the event loop responsive.
Parameters:
-
backend(Backend) –The synchronous backend instance to wrap.
capabilities
property
¶
capabilities: CapabilitySet
Capability set, forwarded from the wrapped backend.
read_bytes
async
¶
Read the full content of a file as bytes.
Raises:
-
InvalidPath–If
pathnames an existing directory. -
NotFound–If the file does not exist.
get_file_info
async
¶
get_file_info(path: str) -> FileInfo
Get metadata for a file.
Raises:
-
InvalidPath–If
pathnames an existing directory. -
NotFound–If the file does not exist.
get_folder_info
async
¶
get_folder_info(path: str) -> FolderInfo
Get metadata for a folder.
Raises:
-
InvalidPath–If
pathnames an existing file. -
NotFound–If the folder does not exist.
move
async
¶
Move or rename a file.
Raises:
-
InvalidPath–If
srcnames a directory ordstnames an existing directory. -
NotFound–If
srcdoes not exist. -
AlreadyExists–If
dstexists,src != dst, andoverwriteisFalse.
copy
async
¶
Copy a file.
Raises:
-
InvalidPath–If
srcnames a directory ordstnames an existing directory. -
NotFound–If
srcdoes not exist. -
AlreadyExists–If
dstexists,src != dst, andoverwriteisFalse.
delete
async
¶
Delete a file.
Raises:
-
NotFound–If the file is missing and
missing_okisFalse. -
InvalidPath–If the path is empty, or if
pathnames a directory (regardless ofmissing_ok).
delete_folder
async
¶
Delete a folder.
Raises:
-
InvalidPath–If
pathnames an existing file (regardless ofmissing_ok— a type mismatch is not a missing file). -
NotFound–If the folder is missing and
missing_okisFalse. -
DirectoryNotEmpty–If non-empty and
recursiveisFalse.
read
async
¶
Open a file for reading and yield chunks asynchronously.
Raises:
-
InvalidPath–If
pathnames an existing directory. -
NotFound–If the file does not exist.
write
async
¶
write(
path: str,
content: AsyncWritableContent,
*,
overwrite: bool = False,
metadata: Mapping[str, str] | None = None,
) -> WriteResult
Write content to a file.
Raises:
-
AlreadyExists–If the file exists and
overwriteisFalse. -
InvalidPath–If
pathnames a directory.
write_atomic
async
¶
write_atomic(
path: str,
content: AsyncWritableContent,
*,
overwrite: bool = False,
metadata: Mapping[str, str] | None = None,
) -> WriteResult
Write content atomically via temp file + rename.
Raises:
-
CapabilityNotSupported–If backend lacks
ATOMIC_WRITE. -
AlreadyExists–If the file exists and
overwriteisFalse. -
InvalidPath–If
pathnames a directory.
list_files
async
¶
list_files(
path: str,
*,
recursive: bool = False,
max_depth: int | None = None,
) -> AsyncIterator[FileInfo]
List files under path.
list_folders
async
¶
list_folders(path: str) -> AsyncIterator[FolderEntry]
List immediate subfolders under path.
iter_children
async
¶
iter_children(
path: str,
) -> AsyncIterator[FileInfo | FolderEntry]
Yield both files and folders under path.
AsyncBackendSyncAdapter¶
Wraps any AsyncBackend as a synchronous Backend by running a private
event loop on a dedicated daemon thread for the adapter's lifetime. See
Async-sync bridges for the full
behaviour contract and the async-to-sync adapter decision record
for the design rationale.
AsyncBackendSyncAdapter
¶
AsyncBackendSyncAdapter(async_backend: AsyncBackend)
Wraps an AsyncBackend as a synchronous Backend.
One private asyncio event loop per adapter instance, running on
a dedicated daemon thread for the adapter's lifetime. Sync methods
submit coroutines via asyncio.run_coroutine_threadsafe and
block on the returned concurrent.futures.Future.
Construction does not enter the wrapped backend's async context
manager -- callers that need __aenter__ semantics should use
AsyncStore directly.
Parameters:
-
async_backend(AsyncBackend) –The async backend instance to wrap.
capabilities
cached
property
¶
capabilities: CapabilitySet
Capabilities reported by the wrapped backend, with stream-shape translation applied.
SEEKABLE_READ is masked off unconditionally — the chunk-pull
stream this adapter returns is forward-only. USER_METADATA
and WRITE_RESULT_NATIVE are forwarded from the inner async
backend unchanged; the write*() methods accept and forward
metadata=.
unwrap
¶
Return a sync-safe native handle if the wrapped backend provides one.
By default raises CapabilityNotSupported
because async-SDK handles are bound to the adapter's private event loop
and cannot be used safely from the caller's thread.
Wrapped backends that can expose a sync-safe handle should implement
_SyncSafeHandleProvider and return it from
_SyncSafeHandleProvider.sync_safe_unwrap.
Parameters:
-
type_hint(type[T]) –The type of handle to retrieve; passed through to
_SyncSafeHandleProvider.sync_safe_unwrapfor backends that support the exemption.
Returns:
-
T–A sync-safe handle of the type requested via type_hint.
Raises:
-
CapabilityNotSupported–If the wrapped backend does not implement
_SyncSafeHandleProvider.
check_health
¶
Submit a connectivity probe to the wrapped async backend.
Not a no-op: the probe is forwarded to the wrapped
AsyncBackend, and any connectivity error
it raises reaches the sync caller unchanged.
Returns:
-
None–Noneon success.
Raises:
-
BackendUnavailable–Or another backend-specific error if the wrapped backend's health check fails.
-
RuntimeError–If the adapter is closed or called from a running event loop.
read
¶
Open path for reading and return a forward-only chunk-pull stream.
The returned stream pulls one async chunk per read() call; the
file is never fully materialised in memory. At most one
__anext__ is in-flight at a time.
The stream is forward-only: seekable() returns False and no
seek / tell / fileno methods are exposed. Closing via
the context manager or close() submits aclose() on the
underlying async iterator so backend resources are released promptly.
Parameters:
-
path(str) –Backend-relative key of the file to read.
Returns:
-
BinaryIO–A forward-only
io.RawIOBasestream over the file -
BinaryIO–contents.
Raises:
-
RuntimeError–If the adapter is closed or called from a running event loop.
-
NotFound–If path does not exist (propagated verbatim from the wrapped backend).
close
¶
Drain in-flight work, stop the loop, and join the daemon thread.
Drain order: submit aclose on the wrapped backend → loop-drain
in-flight tasks (repeating while new tasks appear, see below) → stop
the private loop → join the daemon thread.
The drain step repeats _drain_tasks until the private loop is
quiet, narrowing (not eliminating) the window where a caller that
passed _guard before the closed flag was set can still submit
a coroutine. Each pass snapshots outstanding tasks and waits for them;
new tasks that arrive between snapshot and completion trigger another
pass. A residual TOCTOU gap remains: a thread that passes
_guard after the final empty-snapshot check but before the loop
is stopped will have its coroutine silently discarded when the loop
stops — eliminating this gap would require serialising all submits
against a shutdown lock.
If timeout expires before the loop is drained, a single WARNING
record is emitted (message stem
"AsyncBackendSyncAdapter close timed out") and the daemon thread
is left for process-exit reaping. Idempotent: subsequent calls are
no-ops.
Parameters:
-
timeout(float | None, default:30.0) –Maximum seconds to wait for in-flight work to finish and the background thread to join.
Nonemeans wait indefinitely. Defaults to30.0.
AsyncWritableContent¶
See also¶
- AsyncStore — the async Store the adapters plug into
- AsyncBackend — the async backend protocol
- Async-sync bridges — choosing a direction