Coverage for openhcs/io/__init__.py: 46.7%
26 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-04 02:09 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-04 02:09 +0000
1"""
2Storage backends package for openhcs.
4This package contains the storage backend implementations for openhcs.
5"""
7import os
9# Essential imports (always available)
10from .atomic import file_lock, atomic_write_json, atomic_update_json, FileLockError, FileLockTimeoutError
11from .base import BackendBase, DataSink, DataSource, ReadOnlyBackend, StorageBackend, storage_registry, reset_memory_backend, ensure_storage_registry, get_backend
12from .backend_registry import (
13 get_backend_instance,
14 cleanup_backend_connections, cleanup_all_backends, STORAGE_BACKENDS
15)
16from .disk import DiskStorageBackend
17from .filemanager import FileManager
18from .memory import MemoryStorageBackend
19from .metadata_writer import AtomicMetadataWriter, MetadataWriteError, get_metadata_path, get_subdirectory_name
20from .metadata_migration import detect_legacy_format, migrate_legacy_metadata, migrate_plate_metadata
21from .pipeline_migration import detect_legacy_pipeline, migrate_pipeline_file, load_pipeline_with_migration
22from .streaming import StreamingBackend
24# GPU-heavy backend classes are imported lazily via __getattr__ below
25# This prevents blocking imports of zarr (→ ome-zarr → dask → GPU libs)
26# and streaming backends (→ napari/fiji)
28__all__ = [
29 'BackendBase',
30 'DataSink',
31 'DataSource',
32 'ReadOnlyBackend',
33 'StorageBackend',
34 'StreamingBackend',
35 'storage_registry',
36 'reset_memory_backend',
37 'ensure_storage_registry',
38 'get_backend',
39 'get_backend_instance',
40 'cleanup_all_backends',
41 'STORAGE_BACKENDS',
42 'DiskStorageBackend',
43 'MemoryStorageBackend',
44 'NapariStreamingBackend',
45 'FijiStreamingBackend',
46 'ZarrStorageBackend',
47 'FileManager',
48 'file_lock',
49 'atomic_write_json',
50 'atomic_update_json',
51 'FileLockError',
52 'FileLockTimeoutError',
53 'AtomicMetadataWriter',
54 'MetadataWriteError',
55 'get_metadata_path',
56 'get_subdirectory_name',
57 'detect_legacy_format',
58 'migrate_legacy_metadata',
59 'migrate_plate_metadata',
60 'detect_legacy_pipeline',
61 'migrate_pipeline_file',
62 'load_pipeline_with_migration'
63]
66# Registry for lazy-loaded GPU-heavy backends
67_LAZY_BACKEND_REGISTRY = {
68 'NapariStreamingBackend': ('openhcs.io.napari_stream', 'NapariStreamingBackend'),
69 'FijiStreamingBackend': ('openhcs.io.fiji_stream', 'FijiStreamingBackend'),
70 'ZarrStorageBackend': ('openhcs.io.zarr', 'ZarrStorageBackend'),
71}
74def __getattr__(name):
75 """
76 Lazy import of GPU-heavy backend classes.
78 This prevents blocking imports during `import openhcs.io` while
79 still allowing code to import backend classes when needed.
80 """
81 # Check if name is in lazy backend registry
82 if name not in _LAZY_BACKEND_REGISTRY:
83 raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
85 # Subprocess runner mode - create placeholder
86 if os.getenv('OPENHCS_SUBPROCESS_NO_GPU') == '1':
87 class PlaceholderBackend:
88 """Placeholder for subprocess runner mode."""
89 pass
90 PlaceholderBackend.__name__ = name
91 PlaceholderBackend.__qualname__ = name
92 return PlaceholderBackend
94 # Normal mode - lazy import from registry
95 module_path, class_name = _LAZY_BACKEND_REGISTRY[name]
96 import importlib
97 module = importlib.import_module(module_path)
98 return getattr(module, class_name)