Skip to content

Commit 4ea16c0

Browse files
committed
Create MaybePaginatedListStore
1 parent ee43329 commit 4ea16c0

File tree

1 file changed

+55
-3
lines changed

1 file changed

+55
-3
lines changed

obstore/src/list.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,69 @@ use arrow::datatypes::{DataType, Field, Schema, SchemaRef, TimeUnit};
88
use futures::stream::{BoxStream, Fuse};
99
use futures::StreamExt;
1010
use indexmap::IndexMap;
11+
use object_store::list::PaginatedListStore;
1112
use object_store::path::Path;
1213
use object_store::{ListResult, ObjectMeta, ObjectStore};
13-
use pyo3::exceptions::{PyImportError, PyStopAsyncIteration, PyStopIteration};
14+
use pyo3::exceptions::{PyImportError, PyStopAsyncIteration, PyStopIteration, PyValueError};
1415
use pyo3::prelude::*;
16+
use pyo3::pybacked::PyBackedStr;
1517
use pyo3::types::PyDict;
16-
use pyo3::{intern, IntoPyObjectExt};
18+
use pyo3::{intern, IntoPyObjectExt, PyTypeInfo};
1719
use pyo3_arrow::{PyRecordBatch, PyTable};
1820
use pyo3_async_runtimes::tokio::get_runtime;
19-
use pyo3_object_store::{PyObjectStore, PyObjectStoreError, PyObjectStoreResult};
21+
use pyo3_object_store::{
22+
PyAzureStore, PyGCSStore, PyHttpStore, PyLocalStore, PyMemoryStore, PyObjectStore,
23+
PyObjectStoreError, PyObjectStoreResult, PyS3Store,
24+
};
2025
use tokio::sync::Mutex;
2126

27+
enum MaybePaginatedListStore {
28+
SupportsPagination(Arc<dyn PaginatedListStore>),
29+
NoPagination(Arc<dyn ObjectStore>),
30+
}
31+
32+
impl<'py> FromPyObject<'py> for MaybePaginatedListStore {
33+
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
34+
if let Ok(store) = ob.downcast::<PyS3Store>() {
35+
Ok(Self::SupportsPagination(store.get().as_ref().clone()))
36+
} else if let Ok(store) = ob.downcast::<PyAzureStore>() {
37+
Ok(Self::SupportsPagination(store.get().as_ref().clone()))
38+
} else if let Ok(store) = ob.downcast::<PyGCSStore>() {
39+
Ok(Self::SupportsPagination(store.get().as_ref().clone()))
40+
} else if let Ok(store) = ob.downcast::<PyHttpStore>() {
41+
Ok(Self::NoPagination(store.get().as_ref().clone()))
42+
} else if let Ok(store) = ob.downcast::<PyLocalStore>() {
43+
Ok(Self::NoPagination(store.get().as_ref().clone()))
44+
} else if let Ok(store) = ob.downcast::<PyMemoryStore>() {
45+
Ok(Self::NoPagination(store.get().as_ref().clone()))
46+
} else {
47+
let py = ob.py();
48+
// Check for object-store instance from other library
49+
let cls_name = ob
50+
.getattr(intern!(py, "__class__"))?
51+
.getattr(intern!(py, "__name__"))?
52+
.extract::<PyBackedStr>()?;
53+
if [
54+
PyAzureStore::NAME,
55+
PyGCSStore::NAME,
56+
PyHttpStore::NAME,
57+
PyLocalStore::NAME,
58+
PyMemoryStore::NAME,
59+
PyS3Store::NAME,
60+
]
61+
.contains(&cls_name.as_ref())
62+
{
63+
return Err(PyValueError::new_err("You must use an object store instance exported from **the same library** as this function. They cannot be used across libraries.\nThis is because object store instances are compiled with a specific version of Rust and Python." ));
64+
}
65+
66+
Err(PyValueError::new_err(format!(
67+
"Expected an object store instance, got {}",
68+
ob.repr()?
69+
)))
70+
}
71+
}
72+
}
73+
2274
pub(crate) struct PyObjectMeta(ObjectMeta);
2375

2476
impl PyObjectMeta {

0 commit comments

Comments
 (0)