This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs-object-store.git


The following commit(s) were added to refs/heads/main by this push:
     new 493a5d0  fix: Add more details on what isn't implemented (#575)
493a5d0 is described below

commit 493a5d07d29b12a5731bf112d3ab5df8d0de9616
Author: Carol (Nichols || Goulding) 
<[email protected]>
AuthorDate: Thu Dec 18 13:09:50 2025 -0500

    fix: Add more details on what isn't implemented (#575)
    
    Fixes #572.
---
 src/aws/mod.rs     | 13 +++++++++++--
 src/http/mod.rs    | 10 ++++++++--
 src/integration.rs |  6 +++---
 src/lib.rs         | 13 +++++++++++--
 src/local.rs       | 15 ++++++++++++---
 5 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/aws/mod.rs b/src/aws/mod.rs
index dd2cf6f..030590a 100644
--- a/src/aws/mod.rs
+++ b/src/aws/mod.rs
@@ -180,7 +180,11 @@ impl ObjectStore for AmazonS3 {
 
         match (mode, &self.client.config.conditional_put) {
             (PutMode::Overwrite, _) => request.idempotent(true).do_put().await,
-            (PutMode::Create, S3ConditionalPut::Disabled) => 
Err(Error::NotImplemented),
+            (PutMode::Create, S3ConditionalPut::Disabled) => 
Err(Error::NotImplemented {
+                operation:
+                    "`put_opts` with mode `PutMode::Create` when conditional 
put is disabled".into(),
+                implementer: self.to_string(),
+            }),
             (PutMode::Create, S3ConditionalPut::ETagMatch) => {
                 match request.header(&IF_NONE_MATCH, "*").do_put().await {
                     // Technically If-None-Match should return NotModified but 
some stores,
@@ -222,7 +226,12 @@ impl ObjectStore for AmazonS3 {
                             r => r,
                         }
                     }
-                    S3ConditionalPut::Disabled => Err(Error::NotImplemented),
+                    S3ConditionalPut::Disabled => Err(Error::NotImplemented {
+                        operation:
+                            "`put_opts` with mode `PutMode::Update` when 
conditional put is disabled"
+                                .into(),
+                        implementer: self.to_string(),
+                    }),
                 }
             }
         }
diff --git a/src/http/mod.rs b/src/http/mod.rs
index e241002..9e5af9a 100644
--- a/src/http/mod.rs
+++ b/src/http/mod.rs
@@ -104,7 +104,10 @@ impl ObjectStore for HttpStore {
     ) -> Result<PutResult> {
         if opts.mode != PutMode::Overwrite {
             // TODO: Add support for If header - 
https://datatracker.ietf.org/doc/html/rfc2518#section-9.4
-            return Err(crate::Error::NotImplemented);
+            return Err(crate::Error::NotImplemented {
+                operation: "`put_opts` with a mode other than 
`PutMode::Overwrite`".into(),
+                implementer: self.to_string(),
+            });
         }
 
         let response = self.client.put(location, payload, 
opts.attributes).await?;
@@ -125,7 +128,10 @@ impl ObjectStore for HttpStore {
         _location: &Path,
         _opts: PutMultipartOptions,
     ) -> Result<Box<dyn MultipartUpload>> {
-        Err(crate::Error::NotImplemented)
+        Err(crate::Error::NotImplemented {
+            operation: "`put_multipart_opts`".into(),
+            implementer: self.to_string(),
+        })
     }
 
     async fn get_opts(&self, location: &Path, options: GetOptions) -> 
Result<GetResult> {
diff --git a/src/integration.rs b/src/integration.rs
index bc79f69..5c601b5 100644
--- a/src/integration.rs
+++ b/src/integration.rs
@@ -478,7 +478,7 @@ pub async fn put_get_attributes(integration: &dyn 
ObjectStore) {
             let r = integration.get(&path).await.unwrap();
             assert_eq!(r.attributes, attributes);
         }
-        Err(Error::NotImplemented) => {}
+        Err(Error::NotImplemented { .. }) => {}
         Err(e) => panic!("{e}"),
     }
 
@@ -491,7 +491,7 @@ pub async fn put_get_attributes(integration: &dyn 
ObjectStore) {
             let r = integration.get(&path).await.unwrap();
             assert_eq!(r.attributes, attributes);
         }
-        Err(Error::NotImplemented) => {}
+        Err(Error::NotImplemented { .. }) => {}
         Err(e) => panic!("{e}"),
     }
 }
@@ -606,7 +606,7 @@ pub async fn put_opts(storage: &dyn ObjectStore, 
supports_update: bool) {
             .put_opts(&path, "c".into(), 
PutMode::Update(v1.clone().into()).into())
             .await
             .unwrap_err();
-        assert!(matches!(err, Error::NotImplemented), "{err}");
+        assert!(matches!(err, Error::NotImplemented { .. }), "{err}");
 
         return;
     }
diff --git a/src/lib.rs b/src/lib.rs
index 3448055..d5c0cb5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2049,8 +2049,17 @@ pub enum Error {
     },
 
     /// Error when an operation is not implemented
-    #[error("Operation not yet implemented.")]
-    NotImplemented,
+    #[error("Operation {operation} not yet implemented by {implementer}.")]
+    NotImplemented {
+        /// What isn't implemented. Should include at least the method
+        /// name that was called; could also include other relevant
+        /// subcontexts.
+        operation: String,
+
+        /// Which driver this is that hasn't implemented this operation,
+        /// to aid debugging in contexts that may be using multiple 
implementations.
+        implementer: String,
+    },
 
     /// Error when the used credentials don't have enough permission
     /// to perform the requested operation
diff --git a/src/local.rs b/src/local.rs
index 003e7d7..8f18aa6 100644
--- a/src/local.rs
+++ b/src/local.rs
@@ -330,11 +330,17 @@ impl ObjectStore for LocalFileSystem {
         opts: PutOptions,
     ) -> Result<PutResult> {
         if matches!(opts.mode, PutMode::Update(_)) {
-            return Err(crate::Error::NotImplemented);
+            return Err(crate::Error::NotImplemented {
+                operation: "`put_opts` with mode `PutMode::Update`".into(),
+                implementer: self.to_string(),
+            });
         }
 
         if !opts.attributes.is_empty() {
-            return Err(crate::Error::NotImplemented);
+            return Err(crate::Error::NotImplemented {
+                operation: "`put_opts` with `opts.attributes` 
specified".into(),
+                implementer: self.to_string(),
+            });
         }
 
         let path = self.path_to_filesystem(location)?;
@@ -397,7 +403,10 @@ impl ObjectStore for LocalFileSystem {
         opts: PutMultipartOptions,
     ) -> Result<Box<dyn MultipartUpload>> {
         if !opts.attributes.is_empty() {
-            return Err(crate::Error::NotImplemented);
+            return Err(crate::Error::NotImplemented {
+                operation: "`put_multipart_opts` with `opts.attributes` 
specified".into(),
+                implementer: self.to_string(),
+            });
         }
 
         let dest = self.path_to_filesystem(location)?;

Reply via email to