|
1 | 1 | """ |
2 | | -Polystore - Framework-agnostic multi-backend storage abstraction. |
3 | | -
|
4 | | -Provides pluggable storage backends with multi-framework I/O support for |
5 | | -NumPy, PyTorch, JAX, TensorFlow, CuPy, and Zarr. |
| 2 | +Polystore package exports. |
6 | 3 | """ |
7 | 4 |
|
8 | | -__version__ = "0.1.2" |
| 5 | +import os |
9 | 6 |
|
10 | | -# Core abstractions |
| 7 | +from .atomic import file_lock, atomic_write_json, atomic_update_json, FileLockError, FileLockTimeoutError |
| 8 | +from .backend_registry import ( |
| 9 | + get_backend_instance, |
| 10 | + cleanup_backend_connections, |
| 11 | + cleanup_all_backends, |
| 12 | + register_cleanup_callback, |
| 13 | + STORAGE_BACKENDS, |
| 14 | +) |
11 | 15 | from .base import ( |
| 16 | + BackendBase, |
12 | 17 | DataSink, |
13 | 18 | DataSource, |
14 | | - StorageBackend, |
15 | | - VirtualBackend, |
16 | 19 | ReadOnlyBackend, |
| 20 | + StorageBackend, |
| 21 | + storage_registry, |
| 22 | + reset_memory_backend, |
| 23 | + ensure_storage_registry, |
| 24 | + get_backend, |
17 | 25 | ) |
18 | | - |
19 | | -# Concrete backends |
20 | | -from .memory import MemoryBackend |
21 | | -from .disk import DiskBackend |
22 | | - |
23 | | -# Optional backends |
24 | | -# Zarr is a required backend for this project. Import it directly so |
25 | | -# missing dependency errors surface loudly during test/setup. |
26 | | -from .zarr import ZarrBackend |
27 | | - |
28 | | -# File manager |
| 26 | +from .constants import Backend, MemoryType, TransportMode |
| 27 | +from .disk import DiskStorageBackend |
29 | 28 | from .filemanager import FileManager |
30 | | - |
31 | | -# Registry |
32 | | -from .backend_registry import BackendRegistry, create_storage_registry |
33 | | - |
34 | | -# Atomic operations |
35 | | -from .atomic import atomic_write, atomic_write_json |
36 | | - |
37 | | -# Exceptions |
38 | | -from .exceptions import ( |
39 | | - StorageError, |
40 | | - StorageResolutionError, |
41 | | - BackendNotFoundError, |
42 | | - UnsupportedFormatError, |
| 29 | +from .formats import FileFormat, DEFAULT_IMAGE_EXTENSIONS |
| 30 | +from .memory import MemoryStorageBackend |
| 31 | +from .metadata_writer import ( |
| 32 | + AtomicMetadataWriter, |
| 33 | + MetadataWriteError, |
| 34 | + METADATA_CONFIG, |
| 35 | + get_metadata_path, |
| 36 | + get_subdirectory_name, |
| 37 | + resolve_subdirectory_path, |
43 | 38 | ) |
44 | | - |
45 | | -# Streaming (optional and lazy) |
46 | | -# Don't import at module level - streaming is heavy and optional |
47 | | -# Users can import manually if needed: from polystore.streaming import StreamingBackend |
48 | | -try: |
49 | | - from .streaming import StreamingBackend |
50 | | -except ImportError: |
51 | | - StreamingBackend = None |
52 | | -# Streaming (optional and lazy) |
53 | | -# Don't import at module level - streaming is heavy and optional |
54 | | -# Users can import manually if needed: from polystore.streaming import StreamingBackend |
55 | | -StreamingBackend = None |
| 39 | +from .metadata_migration import detect_legacy_format, migrate_legacy_metadata, migrate_plate_metadata |
| 40 | +from .pipeline_migration import detect_legacy_pipeline, migrate_pipeline_file, load_pipeline_with_migration |
| 41 | +from .roi import ( |
| 42 | + ROI, |
| 43 | + PolygonShape, |
| 44 | + PolylineShape, |
| 45 | + MaskShape, |
| 46 | + PointShape, |
| 47 | + EllipseShape, |
| 48 | + extract_rois_from_labeled_mask, |
| 49 | + load_rois_from_json, |
| 50 | + load_rois_from_zip, |
| 51 | + materialize_rois, |
| 52 | +) |
| 53 | +from .streaming import StreamingBackend |
| 54 | +from .streaming_constants import StreamingDataType, NapariShapeType |
56 | 55 |
|
57 | 56 | __all__ = [ |
58 | | - # Version |
59 | | - "__version__", |
60 | | - # Core abstractions |
| 57 | + "Backend", |
| 58 | + "MemoryType", |
| 59 | + "TransportMode", |
| 60 | + "FileFormat", |
| 61 | + "DEFAULT_IMAGE_EXTENSIONS", |
| 62 | + "BackendBase", |
61 | 63 | "DataSink", |
62 | 64 | "DataSource", |
63 | | - "StorageBackend", |
64 | | - "VirtualBackend", |
65 | 65 | "ReadOnlyBackend", |
66 | | - # Backends |
67 | | - "MemoryBackend", |
68 | | - "DiskBackend", |
69 | | - "ZarrBackend", |
70 | | - # File manager |
| 66 | + "StorageBackend", |
| 67 | + "StreamingBackend", |
| 68 | + "storage_registry", |
| 69 | + "reset_memory_backend", |
| 70 | + "ensure_storage_registry", |
| 71 | + "get_backend", |
| 72 | + "get_backend_instance", |
| 73 | + "cleanup_backend_connections", |
| 74 | + "cleanup_all_backends", |
| 75 | + "register_cleanup_callback", |
| 76 | + "STORAGE_BACKENDS", |
| 77 | + "DiskStorageBackend", |
| 78 | + "MemoryStorageBackend", |
71 | 79 | "FileManager", |
72 | | - # Registry |
73 | | - "BackendRegistry", |
74 | | - # Atomic operations |
75 | | - "atomic_write", |
| 80 | + "file_lock", |
76 | 81 | "atomic_write_json", |
77 | | - # Exceptions |
78 | | - "StorageError", |
79 | | - "StorageResolutionError", |
80 | | - "BackendNotFoundError", |
81 | | - "UnsupportedFormatError", |
82 | | - # Streaming (optional) |
83 | | - "StreamingBackend", |
| 82 | + "atomic_update_json", |
| 83 | + "FileLockError", |
| 84 | + "FileLockTimeoutError", |
| 85 | + "AtomicMetadataWriter", |
| 86 | + "MetadataWriteError", |
| 87 | + "METADATA_CONFIG", |
| 88 | + "get_metadata_path", |
| 89 | + "get_subdirectory_name", |
| 90 | + "resolve_subdirectory_path", |
| 91 | + "detect_legacy_format", |
| 92 | + "migrate_legacy_metadata", |
| 93 | + "migrate_plate_metadata", |
| 94 | + "detect_legacy_pipeline", |
| 95 | + "migrate_pipeline_file", |
| 96 | + "load_pipeline_with_migration", |
| 97 | + "ROI", |
| 98 | + "PolygonShape", |
| 99 | + "PolylineShape", |
| 100 | + "MaskShape", |
| 101 | + "PointShape", |
| 102 | + "EllipseShape", |
| 103 | + "extract_rois_from_labeled_mask", |
| 104 | + "load_rois_from_json", |
| 105 | + "load_rois_from_zip", |
| 106 | + "materialize_rois", |
| 107 | + "StreamingDataType", |
| 108 | + "NapariShapeType", |
| 109 | + "NapariStreamingBackend", |
| 110 | + "FijiStreamingBackend", |
| 111 | + "ZarrStorageBackend", |
| 112 | + "OMEROLocalBackend", |
| 113 | + "OMEROFileFormatRegistry", |
84 | 114 | ] |
85 | 115 |
|
| 116 | +_LAZY_BACKEND_REGISTRY = { |
| 117 | + "NapariStreamingBackend": ("polystore.napari_stream", "NapariStreamingBackend"), |
| 118 | + "FijiStreamingBackend": ("polystore.fiji_stream", "FijiStreamingBackend"), |
| 119 | + "ZarrStorageBackend": ("polystore.zarr", "ZarrStorageBackend"), |
| 120 | + "OMEROLocalBackend": ("polystore.omero_local", "OMEROLocalBackend"), |
| 121 | + "OMEROFileFormatRegistry": ("polystore.omero_local", "OMEROFileFormatRegistry"), |
| 122 | +} |
| 123 | + |
| 124 | + |
| 125 | +def __getattr__(name): |
| 126 | + """Lazy import of optional/extra backend classes.""" |
| 127 | + if name not in _LAZY_BACKEND_REGISTRY: |
| 128 | + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") |
| 129 | + |
| 130 | + if os.getenv("POLYSTORE_SUBPROCESS_NO_GPU") == "1": |
| 131 | + class PlaceholderBackend: |
| 132 | + pass |
| 133 | + PlaceholderBackend.__name__ = name |
| 134 | + PlaceholderBackend.__qualname__ = name |
| 135 | + return PlaceholderBackend |
| 136 | + |
| 137 | + module_path, class_name = _LAZY_BACKEND_REGISTRY[name] |
| 138 | + import importlib |
| 139 | + module = importlib.import_module(module_path) |
| 140 | + return getattr(module, class_name) |
0 commit comments