diff --git a/docs/source/input_preparation_installed_20261001.rst b/docs/source/input_preparation_installed_20261001.rst deleted file mode 100644 index 6cefac4..0000000 --- a/docs/source/input_preparation_installed_20261001.rst +++ /dev/null @@ -1,31 +0,0 @@ -Paired installed namespace checkpoint -===================================== - -PR16 parent production91fd7e854 includes namespace PR20 through normal -fast-forward. MetadataConfig owns path and managed-path operations; -VirtualWorkspaceBackend retains the exact declaration in its existing native -FileManager connection state. The application owns its filename through a -MetadataConfig subclass rather than changing the dependency singleton or globals. -BOUND-2/IMPL-12: one shared owner, no alternate metadata reader or mirror. - -Application PR206 production5ce9e3087 binds that application declaration at the -microscope registration boundary. Current application29 checks pass in both -import orders; five namespace checks pass with independent custom filenames. -Worker child11 controls and unchanged child structural guard remain evidence -at this identical production source. Earlier failures are not erased or counted -as current passes. No full-context NRA/native-proof claim. - -The paired PolyStore0.3.0 wheel is installed with OpenHCS0.8.7 in an isolated -candidate, no index/dependency/Fiji/environment downloads or global modification. -Actual installed MCP reopening and bounded samples succeed with the dependency -configured generic-private.json independently of OpenHCS metadata. Real raw -ImageXpress workspace initialization through source artifact-plan inspection -then persisted virtual sampling succeeds. Empty processing steps test only -initialization/compile, not analysis or a ZMQ job. Actual Java/CZI/native execution -and raw singleton Opera grid initialization remain explicit follow-ups; the -Opera structured failure is preserved and assigned under OpenHCS issue172. - -Canonical application receipt: docs/validation/input_preparation_installed_20261001.rst. -Exact wheel and original MCP/build/source evidence are retained in the durable -OpenHCS parent namespace-installed-20261001 ledger. This is local paired-wheel -acceptance, not public registry availability or an installed global release. diff --git a/docs/source/input_preparation_parent_20261001.rst b/docs/source/input_preparation_parent_20261001.rst deleted file mode 100644 index 25a16e1..0000000 --- a/docs/source/input_preparation_parent_20261001.rst +++ /dev/null @@ -1,32 +0,0 @@ -Parent paired source checkpoint -=============================== - -Existing PR16 is normally integrated with the OpenHCS-recorded PolyStore -dc3417392cef19083a907c8c9b88a15466f81df4 at -cb12a2acd91061d60cb6ec65981a9f5c01e18963. Parent is the integration owner; -the original worker worktree remains unchanged. Existing ROI/context owners and -external formats are retained without a parallel implementation. - -Forty-eight standalone dependency tests pass in0.82s, including existing/new ROI -geometry/work-count and Java-context lifetime controls. The source-qualified -process checks its generic metadata namespace before collection. Separate real -application-entrypoint bootstrap passes163 source workspace/selection/materialization -and generator controls in19.12s. These use independent processes and real typed -owners, no filename patch/fallback. The original141-pass/26-failure combined run -is not overwritten or relabeled. - -Intentional dependency-first application embedding still reproduces the metadata -namespace defect:1 failure in3.34s. Parent owns the application/dependency boundary -follow-up; no cached singleton mutation or second file reader is introduced here. -The initial control's missing scratch-parent setup error is retained separately. - -Existing bounded128x128 profile now observes one bbox scan rather than the older -two, with parents7/42/188 and902 fragments/native ZIP members unchanged. This is -a bounded work-count witness, not a general latency or biological claim. Polygon -ring preservation does not prove hole subtraction/raster-viewer equivalence. - -Full source commands/raw XML/logs/profile are preserved in -/home/ts/wt/openhcs-issue-batch-20260929/input-parent-20261001 and the paired -OpenHCS docs/validation/input_preparation_parent_20261001.rst. Actual installed -MCP/Java acceptance and the complete ZIP/NRA review remain open. No package, -Fiji download, JVM, scientific worker or frozen installation is modified. diff --git a/docs/source/metadata_namespace_327.rst b/docs/source/metadata_namespace_327.rst deleted file mode 100644 index 9197bc6..0000000 --- a/docs/source/metadata_namespace_327.rst +++ /dev/null @@ -1,108 +0,0 @@ -Issue327: workspace-owned metadata namespace -=========================================== - -SOURCE-ONLY implementation owner; parent remains integration owner. -Audited dependency: PR16 at4939979978439a6f38145788df9aac3bce65bc70. -Paired application: PR206 ata3179b214b888308133e55682e964f77c2781879. -This is a dependency-stack extension, not another input-preparation implementation. - -Boundary, witnesses and ownership --------------------------------- - -Before: metadata_writer.py:54 declares frozen MetadataConfig, but -virtual_workspace.py:242 resolves metadata through the module-global helper. -Its connection parameters at218-238 carry only plate_root. OpenHCS's richer -OpenHCSMetadataConfig declares its own filename, paths and lock ownership in -openhcs/core/virtual_workspace_metadata.py:39-59, while openhcs/__init__.py:20 -projects the application filename into the dependency's environment. A dependency -import before that projection leaves its decoded config unchanged. - -BOUND-2: the consumer bypassed the richer application's existing config owner. -IMPL-13: application path/lock behavior was repeated rather than inherited. -TIME-7: bootstrap supplied another component's ambient default. No application -namespace is added to PolyStore; the application declares that specialization. - -After: MetadataConfig owns metadata_path and managed_paths. VirtualWorkspaceBackend -retains the exact MetadataConfig instance, resolves through its method, and carries -the owner through the existing PicklableBackend connection-parameter contract. -FileManager's existing registry and native reconstruction remain unchanged. -Its frozen generic default remains the same object used by get_metadata_path. -Explicit custom configurations are not overwritten by another importing consumer. -OpenHCSMetadataConfig inherits shared behavior and declares only its application -filename. Parent must bind this owner at microscope backend registration. - -Durable state and new-case experiment ------------------------------------- - -Metadata remains durable JSON at its declared path, with the existing structured -SourcePixelRef mapping. No new store, copy, rename, alternate reader or converter. -The runtime FileManager handoff carries the config object along with plate_root. -Constructor keyword binding decodes the native dictionary into the owning -backend; no key-rewriting, version conversion or alternate metadata reader. - -Before, embedding a new namespace required coordinating an environment projection, -dependency import timing and application producer declaration. After, one frozen -MetadataConfig declaration/value is passed to the workspace constructor. The -new-case test changes filename and SUBDIRECTORIES_KEY to collections and loads -exact pixels without changing workspace/registry/consumer code. The native test -uses actual FileManager pickle reconstruction in a fresh Python process, not a -mock registry or serialization replacement. - -Source evidence and guards --------------------------- - -Final dependency sourceee1e5438d64cb7d37e2641c2d9b3ee8870663adf passes eleven -checks in4.42s, peak combined process RSS294.78 MiB, one CPU. This includes -three unchanged existing FileManager workspace/pickle preservation controls. -They cover generic/custom namespace, explicit environment config with no mutation -of the generic snapshot, real persisted reopen, connection replacement and cache -refresh, absence of alternate-filename readers, source axes, exact pixels, -sample provenance and native handoff. Site-specific AST guard requires the path -call to use self.metadata_config and the handoff methods to use constructor -keyword binding rather than raw params subscripts. Constructor binding rejects -unknown fields. Reconnection preserves the existing execution-local registry. -No guard exceptions or assertion weakening. - -The unchanged original structural ratchet at agent-comms3b03785f45df2ef5dc62ba6aed99294192ecbb01 -passes against PR16 for the final committed source: StringSubscript delta-2, -all other deltas zero. The first draft48621c1 had delta+2 and failed; this is -retained as failed evidence, not waived. The fix removed duplicated dictionary -decoding through actual constructor/open-workspace contracts, not constant -substitutions or detector changes. Original tool SHA256 is -e323c94d49c2b72d9524a5169f123e64b4a6e46a41035ca9fb4497e49b6ca562. -The tool's package import fails under Python3.12 with NameError: InputDocument; -original CI uses3.14, and the existing system Python3.14.7 runs the unchanged -tool from a pinned own local Git worktree. No interpreter/package download or -tool source change. Product tests and native handoffs remain on Python3.12. -An initial site guard counted typing annotations as raw subscripts; its failure -is retained and the corrected guard targets params accesses specifically. - -Lightweight full-package AST census at pinned HEAD completes in1.06s with12,209 -code lines; it is not a global semantic audit. The original application failure -was separately reproduced unchanged in4.35s at275.77 MiB RSS. Original XML/logs -and the earlier native-extension collection error are retained in the paired -application receipt's source archive. Own native extensions were built normally -from source, not copied from the installation. - -This is a hand-authored semantic patch based on the fully read NRA/refactor-audit -rules, pattern catalog and inspected owners. No NRA transaction, completed R1 -raw-findings scan, native-equivalence certificate or global architecture approval -is claimed. Uncompleted heavy scans do not block these bounded source checks; -their missing proof remains missing, not waived. - -Resource and acceptance boundary -------------------------------- - -Own persistent source worktree: /home/ts/wt/polystore-metadata-namespace-327-20261001. -Disposable output owner: this agent; path -/home/ts/.cache/agent-scratch/metadata-namespace-327, maximum256 MiB. -Every source shard is bounded60s and512 MiB combined RSS. Resource guard reports -the owner's warning-only20 GiB disk threshold; actual8.4-8.5 GiB free and more -than15 GiB RAM available provide room for these explicit bounds. -No installed packages, parent/foreign sources, UI/MCP, scientific datasets, -science-runtime locks, Fiji/environments/interpreter downloads are changed. - -Working source contract is ready for parent review. Complete microscope startup, -application-first/dependency-first entrypoints, installed native/MCP and affected -installed acceptance require parent binding and paired integration. Neither this -receipt nor passing source checks closes issue327 or certifies live readiness. diff --git a/pyproject.toml b/pyproject.toml index c2ad530..c16d8df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "polystore" -version = "0.6.0" +version = "0.6.1" description = "Framework-agnostic multi-backend storage abstraction for ML and scientific computing" readme = "README.md" requires-python = ">=3.11" diff --git a/src/polystore/omero_local.py b/src/polystore/omero_local.py index 5264b66..0d8bf80 100644 --- a/src/polystore/omero_local.py +++ b/src/polystore/omero_local.py @@ -1130,6 +1130,18 @@ def exists(self, path: str | Path) -> bool: except (ValueError, IndexError): return False + def is_dir(self, path: str | Path) -> bool: + """A valid OMERO path without a file suffix names a virtual directory. + + Plates and their derived output groups are directories; planes and + tables are files named with their format's suffix. + """ + return self.exists(path) and not PurePosixPath(str(path).replace("\\", "/")).suffix + + def is_file(self, path: str | Path) -> bool: + """A valid OMERO path with a file suffix names a virtual file.""" + return self.exists(path) and bool(PurePosixPath(str(path).replace("\\", "/")).suffix) + def ensure_directory(self, directory: str | Path) -> None: """ Ensure directory exists (no-op for OMERO virtual backend). diff --git a/tests/test_omero_virtual_paths.py b/tests/test_omero_virtual_paths.py new file mode 100644 index 0000000..3c70ad6 --- /dev/null +++ b/tests/test_omero_virtual_paths.py @@ -0,0 +1,26 @@ +"""OMERO virtual paths answer the storage directory and file queries.""" + +import pytest + +from polystore.omero_local import OMEROLocalBackend + + +@pytest.mark.parametrize( + ("path", "is_dir", "is_file"), + ( + ("/omero/plate_1", True, False), + ("/omero/plate_1_outputs/images", True, False), + ("/omero/plate_1_outputs/images/A01_s001_w1_z001_t001.tif", False, True), + ("/omero/plate_1_outputs/images_results/A01_measurements.csv", False, True), + ("/data/plate_1", False, False), + ("/omero/not_a_plate", False, False), + ), +) +def test_omero_paths_are_directories_unless_they_name_a_file( + path: str, is_dir: bool, is_file: bool +) -> None: + # The path queries need no server connection. + backend = object.__new__(OMEROLocalBackend) + + assert backend.is_dir(path) is is_dir + assert backend.is_file(path) is is_file diff --git a/uv.lock b/uv.lock index f4e2c3e..5837d74 100644 --- a/uv.lock +++ b/uv.lock @@ -2905,7 +2905,7 @@ wheels = [ [[package]] name = "polystore" -version = "0.6.0" +version = "0.6.1" source = { editable = "." } dependencies = [ { name = "arraybridge" },