Source code for terracotta.drivers

"""drivers/__init__.py

Define an interface to retrieve Terracotta drivers.
"""

import os
from typing import Optional, Union, Tuple, Dict, Type
import urllib.parse as urlparse
from pathlib import Path

from terracotta.drivers.base_classes import MetaStore
from terracotta.drivers.terracotta_driver import TerracottaDriver
from terracotta.drivers.geotiff_raster_store import GeoTiffRasterStore

URLOrPathType = Union[str, Path]


def load_driver(provider: str) -> Type[MetaStore]:
    if provider == "sqlite-remote":
        from terracotta.drivers.sqlite_remote_meta_store import RemoteSQLiteMetaStore

        return RemoteSQLiteMetaStore

    if provider == "mysql":
        from terracotta.drivers.mysql_meta_store import MySQLMetaStore

        return MySQLMetaStore

    if provider == "postgresql":
        from terracotta.drivers.postgresql_meta_store import PostgreSQLMetaStore

        return PostgreSQLMetaStore

    if provider == "sqlite":
        from terracotta.drivers.sqlite_meta_store import SQLiteMetaStore

        return SQLiteMetaStore

    raise ValueError(f"Unknown database provider {provider}")


def auto_detect_provider(url_or_path: str) -> str:
    parsed_path = urlparse.urlparse(url_or_path)

    scheme = parsed_path.scheme
    if scheme == "s3":
        return "sqlite-remote"

    if scheme == "mysql":
        return "mysql"

    if scheme == "postgresql":
        return "postgresql"

    return "sqlite"


_DRIVER_CACHE: Dict[Tuple[URLOrPathType, str, int], TerracottaDriver] = {}


[docs] def get_driver( url_or_path: URLOrPathType, provider: Optional[str] = None ) -> TerracottaDriver: """Retrieve Terracotta driver instance for the given path. This function always returns the same instance for identical inputs. Warning: Always retrieve Driver instances through this function instead of instantiating them directly to prevent caching issues. Arguments: url_or_path: A path identifying the database to connect to. The expected format depends on the driver provider. provider: Driver provider to use (one of sqlite, sqlite-remote, mysql, postgresql; default: auto-detect). Example: >>> import terracotta as tc >>> tc.get_driver('tc.sqlite') TerracottaDriver( meta_store=SQLiteDriver('/home/terracotta/tc.sqlite'), raster_store=GeoTiffRasterStore() ) >>> tc.get_driver('mysql://root@localhost/tc') TerracottaDriver( meta_store=MySQLDriver('mysql+pymysql://localhost:3306/tc'), raster_store=GeoTiffRasterStore() ) >>> # pass provider if path is given in a non-standard way >>> tc.get_driver('root@localhost/tc', provider='mysql') TerracottaDriver( meta_store=MySQLDriver('mysql+pymysql://localhost:3306/tc'), raster_store=GeoTiffRasterStore() ) """ url_or_path = str(url_or_path) if provider is None: # try and auto-detect provider = auto_detect_provider(url_or_path) DriverClass = load_driver(provider) normalized_path = DriverClass._normalize_path(url_or_path) cache_key = (normalized_path, provider, os.getpid()) if cache_key not in _DRIVER_CACHE: driver = TerracottaDriver( meta_store=DriverClass(url_or_path), raster_store=GeoTiffRasterStore() ) _DRIVER_CACHE[cache_key] = driver return _DRIVER_CACHE[cache_key]