From 12551fdf3859b8a0096769b43372dc78b13f9215 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Wed, 5 Feb 2025 10:00:06 -0500 Subject: [PATCH] Ensure `LocalStore.prefix` is a `pathlib.Path` (#219) * Ensure `LocalStore.prefix` is a `pathlib.Path` * bump to 0.4.0-beta.3 --- Cargo.lock | 2 +- obstore/Cargo.toml | 2 +- obstore/python/obstore/store/__init__.pyi | 3 +++ pyo3-object_store/src/local.rs | 16 ++++++++++++++-- tests/store/test_local.py | 9 +++++++++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d710b7a2..968ae5e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1865,7 +1865,7 @@ dependencies = [ [[package]] name = "obstore" -version = "0.4.0-beta.2" +version = "0.4.0-beta.3" dependencies = [ "arrow", "bytes", diff --git a/obstore/Cargo.toml b/obstore/Cargo.toml index 3f4158ef..9208ef76 100644 --- a/obstore/Cargo.toml +++ b/obstore/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obstore" -version = "0.4.0-beta.2" +version = "0.4.0-beta.3" authors = { workspace = true } edition = { workspace = true } description = "The simplest, highest-throughput interface to Amazon S3, Google Cloud Storage, Azure Blob Storage, and S3-compliant APIs like Cloudflare R2." diff --git a/obstore/python/obstore/store/__init__.pyi b/obstore/python/obstore/store/__init__.pyi index 871c9bd8..6d0c7573 100644 --- a/obstore/python/obstore/store/__init__.pyi +++ b/obstore/python/obstore/store/__init__.pyi @@ -153,6 +153,9 @@ class LocalStore: def __getnewargs_ex__(self): ... def __repr__(self) -> str: ... + @property + def prefix(self) -> Path | None: + """Get the prefix applied to all operations in this store, if any.""" class MemoryStore: """A fully in-memory implementation of ObjectStore. diff --git a/pyo3-object_store/src/local.rs b/pyo3-object_store/src/local.rs index 64eeb4bf..26dcf39e 100644 --- a/pyo3-object_store/src/local.rs +++ b/pyo3-object_store/src/local.rs @@ -113,7 +113,19 @@ impl PyLocalStore { } #[getter] - fn prefix(&self) -> Option<&std::path::PathBuf> { - self.config.prefix.as_ref() + fn prefix(&self, py: Python) -> PyResult { + // Note: returning a std::path::Path or std::path::PathBuf converts back to a Python _str_ + // not a Python _pathlib.Path_. + // So we manually convert to a pathlib.Path + if let Some(prefix) = &self.config.prefix { + let pathlib_mod = py.import(intern!(py, "pathlib"))?; + let path_object = pathlib_mod.call_method1( + intern!(py, "Path"), + PyTuple::new(py, vec![prefix.into_pyobject(py)?])?, + )?; + path_object.into_py_any(py) + } else { + Ok(py.None()) + } } } diff --git a/tests/store/test_local.py b/tests/store/test_local.py index 28712fd0..90f84cab 100644 --- a/tests/store/test_local.py +++ b/tests/store/test_local.py @@ -54,3 +54,12 @@ def test_create_prefix(): # Assert that mkdir=True works even when the dir already exists LocalStore(tmpdir, mkdir=True) assert tmpdir.exists() + + +def test_prefix_property(): + tmpdir = Path(tempfile.gettempdir()) + store = LocalStore(tmpdir) + assert store.prefix == tmpdir + assert isinstance(store.prefix, Path) + # Can pass it back to the store init + LocalStore(store.prefix)