Source code for scitex_app.sdk

#!/usr/bin/env python3
# Timestamp: 2026-03-13
# File: scitex_app/sdk/__init__.py

"""App SDK — write-once interface for local + cloud SciTeX apps.

Usage (standalone / local):
    from scitex_app.sdk import get_files

    files = get_files("./my_project")
    content = files.read("recipes/my_recipe.yaml")
    files.write("output/result.png", png_bytes)

Usage (cloud, auto-detected via SCITEX_API_TOKEN):
    files = get_files()  # routes through cloud REST API

Usage (remote local, via SCITEX_API_URL):
    import os
    os.environ["SCITEX_API_TOKEN"] = "your-token"
    os.environ["SCITEX_API_URL"] = "https://scitex.ai"
    files = get_files()  # routes to remote cloud
"""

from __future__ import annotations

import os
from pathlib import Path
from typing import Any, Callable, Dict, Optional, Union

from ._protocol import FilesBackend
from ._tree import build_tree

# Backend registry: name -> factory callable
_registry: Dict[str, Callable[..., FilesBackend]] = {}


[docs] def register_backend(name: str, factory: Callable[..., FilesBackend]) -> None: """Register a files backend factory. Parameters ---------- name : str Backend identifier (e.g., "cloud", "s3"). factory : callable Callable(root, ``**kwargs``) -> ``FilesBackend`` instance. """ _registry[name] = factory
[docs] def get_files( root: Optional[Union[str, Path]] = None, *, backend: Optional[str] = None, **kwargs: Any, ) -> FilesBackend: """Get a files backend instance. Auto-detection logic: 1. If ``backend`` is specified, use that. 2. If ``SCITEX_API_TOKEN`` env var is set and "cloud" backend is registered, use cloud. 3. Otherwise, use filesystem (default). Parameters ---------- root : str or Path, optional Root directory for filesystem backend. Defaults to cwd. backend : str, optional Explicit backend name. If None, auto-detected. Returns ------- FilesBackend A backend instance. Raises ------ KeyError If the requested backend is not registered. """ if backend: if backend not in _registry: raise KeyError( f"Backend {backend!r} not registered. " f"Available: {list(_registry.keys())}" ) return _registry[backend](root, **kwargs) if os.environ.get("SCITEX_API_TOKEN"): if "cloud" not in _registry: # Auto-register cloud backend when token is available from ._cloud_files import cloud_files_factory _registry["cloud"] = cloud_files_factory return _registry["cloud"](root, **kwargs) from ._filesystem import FileSystemBackend return FileSystemBackend(root or Path.cwd())
__all__ = [ "FilesBackend", "get_files", "register_backend", "build_tree", ] # Internal cloud modules — accessible via scitex_app.sdk._client etc. # but NOT part of the public API contract. Use scitex_hub.sdk for # cloud service access (data, files, jobs, scitex, external). def __getattr__(name: str) -> Any: """Lazy-load cloud internals on demand (not in __all__).""" _lazy = { "PlatformClient": ("._client", "PlatformClient"), "get_client": ("._client", "get_client"), "reset_client": ("._client", "reset_client"), "CloudFilesBackend": ("._cloud_files", "CloudFilesBackend"), "data": (".", "_cloud_data"), "files": (".", "_cloud_files"), "jobs": (".", "_cloud_jobs"), "scitex": (".", "_cloud_scitex"), "external": (".", "_cloud_external"), } if name in _lazy: import importlib mod_path, attr = _lazy[name] if mod_path == ".": return importlib.import_module(f".{attr}", __package__) mod = importlib.import_module(mod_path, __package__) return getattr(mod, attr) raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # EOF