multicloud.common¶
Cross-service base infrastructure — the SubstrateSdkException hierarchy
and the Provider / ProviderRegistry primitives every service builds
on.
Exceptions¶
Cloud-agnostic exception hierarchy.
Providers translate their native errors into one of these types so
client code can write a single except clause that works across
substrates.
SubstrateSdkException
¶
Bases: Exception
Root of all SDK exceptions — catch this to handle any SDK error generically.
InvalidArgumentException
¶
Bases: SubstrateSdkException
Caller provided invalid input (empty key, bad type, failed validation).
ResourceNotFoundException
¶
Bases: SubstrateSdkException
Target resource (bucket, object, role) does not exist.
ResourceExistsException
¶
Bases: SubstrateSdkException
Attempted to create a resource that already exists (e.g., duplicate bucket).
ResourceConflictException
¶
Bases: SubstrateSdkException
Resource state conflicts with the requested operation (e.g., delete role with attached policies).
Also raised when a concurrent write races a conditional write: the precondition may never have been evaluated and the write may not have happened, so this is a retry signal, distinct from the terminal ResourceExistsException / FailedPreconditionException. Retry the write.
UnAuthorizedException
¶
Bases: SubstrateSdkException
Credentials missing, expired, or lack required permissions.
FailedPreconditionException
¶
Bases: SubstrateSdkException
Operation rejected because a precondition wasn't met (e.g., non-empty bucket delete).
UnsupportedOperationException
¶
Bases: SubstrateSdkException
The requested operation is not supported by this provider.
ResourceExhaustedException
¶
Bases: SubstrateSdkException
Rate limit exceeded, quota exhausted, or throttling applied.
DeadlineExceededException
¶
Bases: SubstrateSdkException
Operation timed out or deadline exceeded.
TransactionFailedException
¶
Bases: SubstrateSdkException
Internal service failure during transaction.
ResourceAlreadyExistsException
¶
Bases: SubstrateSdkException
Attempted to create a resource that already exists.
UnknownException
¶
Bases: SubstrateSdkException
Catch-all for errors that don't map to a more specific type.
Provider registry¶
Provider discovery registry.
A small in-process registry keyed by provider id (e.g. "aws",
"gcp"). Provider classes register themselves with the
@registry.register("aws") decorator at import time; the user-facing
client (e.g. BucketClient) looks up the right class by id at
construction time.
This is a service-locator pattern — it emerges when a single API must dispatch to multiple backend implementations at runtime.
Provider modules in this SDK are loaded lazily from setuptools entry
points. Each provider distribution declares an entry point in the
multicloud.<svc>.providers group; :meth:ProviderRegistry.discover
imports those modules on the first :meth:ProviderRegistry.get call so
the @register decorators run and the providers become resolvable.
Provider
¶
Bases: ABC
Base class for all provider implementations across all services.
Every provider (for blob, STS, or any other service) must implement error translation to map provider-specific exceptions to the common SubstrateSdkException hierarchy.
get_provider_id
¶
Return the provider identifier (e.g., 'aws', 'gcp', 'ali'). Read from the class attribute stamped by the registry decorator.
translate_error
abstractmethod
¶
Translate provider-specific exceptions to the common hierarchy.
Each provider maps its native SDK errors into SubstrateSdkException subtypes. This normalizes diverse error shapes into a single hierarchy that client code can catch uniformly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc
|
Exception
|
The provider-specific exception to translate. |
required |
Returns:
| Type | Description |
|---|---|
SubstrateSdkException
|
A SubstrateSdkException subclass instance. |
ProviderRegistry
¶
A per-service registry that maps provider_id → provider class.
Each service (blob, sts, docstore, ...) owns its own registry instance so the namespaces don't collide. A lightweight service-locator that avoids hard imports of optional dependencies.
Provider discovery is via setuptools entry points. The registry is
constructed with an entry_point_group (e.g. "multicloud.blob.providers")
that provider distributions advertise themselves under. The registry
imports those modules lazily on the first :meth:get call; each
provider module's import side-effect is to call
@registry.register(...) on its class.
register
¶
Class decorator that registers a provider implementation. Stamps provider_id on the class and adds it to the lookup table.
record_import_error
¶
Stash an ImportError for deferred reporting (lazy-import pattern).
The error surfaces with a helpful "pip install" hint when the user first tries to use that provider.
discover
¶
Import every provider module advertised in our entry-point group.
Idempotent. Safe to call multiple times. Each provider module's
import side-effect (the @registry.register("aws") decorator)
populates the registry. Missing optional dependencies surface as
ImportError and are recorded under the entry-point name so a
later get(...) call yields a clear "pip install" hint.
get
¶
Look up a provider class by id — the core dispatch mechanism. Raises ValueError with actionable guidance if not found or import failed.