"""Storage registry for ObjectStore backends.
Provides a storage registry that supports URI-first access
pattern with automatic backend detection, ObStore preferred with FSSpec fallback,
scheme-based routing, and named aliases for common configurations.
"""
import logging
import re
from pathlib import Path
from typing import Any, Final, cast
from urllib.parse import unquote, urlparse, urlunparse
from mypy_extensions import mypyc_attr
from sqlspec.exceptions import ImproperConfigurationError, MissingDependencyError
from sqlspec.protocols import ObjectStoreProtocol
from sqlspec.storage._paths import is_file_destination, strip_windows_drive_prefix
from sqlspec.typing import FSSPEC_INSTALLED, OBSTORE_INSTALLED
from sqlspec.utils.logging import get_logger, log_with_context
from sqlspec.utils.type_guards import is_local_path
__all__ = ("StorageRegistry", "storage_registry")
logger = get_logger(__name__)
SCHEME_REGEX: Final = re.compile(r"([a-zA-Z0-9+.-]+)://")
FSSPEC_ONLY_SCHEMES: Final[frozenset[str]] = frozenset({"http", "https", "ftp", "sftp", "ssh"})
@mypyc_attr(allow_interpreted_subclasses=True)
class StorageRegistry:
"""Global storage registry for named backend configurations.
Allows registering named storage backends that can be accessed from anywhere
in your application. Backends are automatically selected based on URI scheme
unless explicitly overridden.
"""
__slots__ = ("_alias_configs", "_instances")
def __init__(self) -> None:
self._alias_configs: dict[str, tuple[type[ObjectStoreProtocol], str, dict[str, Any]]] = {}
self._instances: dict[str | tuple[str, tuple[tuple[str, Any], ...]], ObjectStoreProtocol] = {}