pyo3_object_store/
error.rs1use pyo3::exceptions::{PyFileNotFoundError, PyIOError, PyNotImplementedError, PyValueError};
5use pyo3::prelude::*;
6use pyo3::{create_exception, CastError};
7use thiserror::Error;
8
9create_exception!(
13 pyo3_object_store,
14 BaseError,
15 pyo3::exceptions::PyException,
16 "The base Python-facing exception from which all other errors subclass."
17);
18
19create_exception!(
21 pyo3_object_store,
22 GenericError,
23 BaseError,
24 "A Python-facing exception wrapping [object_store::Error::Generic]."
25);
26create_exception!(
27 pyo3_object_store,
28 NotFoundError,
29 BaseError,
30 "A Python-facing exception wrapping [object_store::Error::NotFound]."
31);
32create_exception!(
33 pyo3_object_store,
34 InvalidPathError,
35 BaseError,
36 "A Python-facing exception wrapping [object_store::Error::InvalidPath]."
37);
38create_exception!(
39 pyo3_object_store,
40 JoinError,
41 BaseError,
42 "A Python-facing exception wrapping [object_store::Error::JoinError]."
43);
44create_exception!(
45 pyo3_object_store,
46 NotSupportedError,
47 BaseError,
48 "A Python-facing exception wrapping [object_store::Error::NotSupported]."
49);
50create_exception!(
51 pyo3_object_store,
52 AlreadyExistsError,
53 BaseError,
54 "A Python-facing exception wrapping [object_store::Error::AlreadyExists]."
55);
56create_exception!(
57 pyo3_object_store,
58 PreconditionError,
59 BaseError,
60 "A Python-facing exception wrapping [object_store::Error::Precondition]."
61);
62create_exception!(
63 pyo3_object_store,
64 NotModifiedError,
65 BaseError,
66 "A Python-facing exception wrapping [object_store::Error::NotModified]."
67);
68create_exception!(
69 pyo3_object_store,
70 PermissionDeniedError,
71 BaseError,
72 "A Python-facing exception wrapping [object_store::Error::PermissionDenied]."
73);
74create_exception!(
75 pyo3_object_store,
76 UnauthenticatedError,
77 BaseError,
78 "A Python-facing exception wrapping [object_store::Error::Unauthenticated]."
79);
80create_exception!(
81 pyo3_object_store,
82 UnknownConfigurationKeyError,
83 BaseError,
84 "A Python-facing exception wrapping [object_store::Error::UnknownConfigurationKey]."
85);
86
87#[derive(Error, Debug)]
89#[non_exhaustive]
90pub enum PyObjectStoreError {
91 #[error(transparent)]
93 ObjectStoreError(#[from] object_store::Error),
94
95 #[error(transparent)]
97 PyErr(#[from] PyErr),
98
99 #[error(transparent)]
101 IOError(#[from] std::io::Error),
102}
103
104impl From<PyObjectStoreError> for PyErr {
105 fn from(error: PyObjectStoreError) -> Self {
106 match error {
107 PyObjectStoreError::PyErr(err) => err,
108 PyObjectStoreError::ObjectStoreError(ref err) => match err {
109 object_store::Error::Generic {
110 store: _,
111 source: _,
112 } => GenericError::new_err(print_with_debug(err)),
113 object_store::Error::NotFound { path: _, source: _ } => {
114 PyFileNotFoundError::new_err(print_with_debug(err))
115 }
116 object_store::Error::InvalidPath { source: _ } => {
117 InvalidPathError::new_err(print_with_debug(err))
118 }
119 object_store::Error::JoinError { source: _ } => {
120 JoinError::new_err(print_with_debug(err))
121 }
122 object_store::Error::NotSupported { source: _ } => {
123 NotSupportedError::new_err(print_with_debug(err))
124 }
125 object_store::Error::AlreadyExists { path: _, source: _ } => {
126 AlreadyExistsError::new_err(print_with_debug(err))
127 }
128 object_store::Error::Precondition { path: _, source: _ } => {
129 PreconditionError::new_err(print_with_debug(err))
130 }
131 object_store::Error::NotModified { path: _, source: _ } => {
132 NotModifiedError::new_err(print_with_debug(err))
133 }
134 object_store::Error::NotImplemented {
135 operation: _,
136 implementer: _,
137 } => PyNotImplementedError::new_err(print_with_debug(err)),
138 object_store::Error::PermissionDenied { path: _, source: _ } => {
139 PermissionDeniedError::new_err(print_with_debug(err))
140 }
141 object_store::Error::Unauthenticated { path: _, source: _ } => {
142 UnauthenticatedError::new_err(print_with_debug(err))
143 }
144 object_store::Error::UnknownConfigurationKey { store: _, key: _ } => {
145 UnknownConfigurationKeyError::new_err(print_with_debug(err))
146 }
147 _ => GenericError::new_err(print_with_debug(err)),
148 },
149 PyObjectStoreError::IOError(err) => PyIOError::new_err(err),
150 }
151 }
152}
153
154fn print_with_debug(err: &object_store::Error) -> String {
155 format!("{err}\n\nDebug source:\n{err:#?}")
158}
159
160impl<'a, 'py> From<CastError<'a, 'py>> for PyObjectStoreError {
161 fn from(other: CastError<'a, 'py>) -> Self {
162 Self::PyErr(PyValueError::new_err(format!(
163 "Could not downcast: {other}",
164 )))
165 }
166}
167
168pub type PyObjectStoreResult<T> = Result<T, PyObjectStoreError>;
170
171#[derive(Debug, thiserror::Error)]
175pub(crate) enum ParseUrlError {
176 #[error(
177 "Unknown url scheme cannot be parsed into storage location: {}",
178 scheme
179 )]
180 UnknownUrlScheme { scheme: String },
181
182 #[error("URL did not match any known pattern for scheme: {}", url)]
183 UrlNotRecognised { url: String },
184}
185
186impl From<ParseUrlError> for object_store::Error {
187 fn from(source: ParseUrlError) -> Self {
188 Self::Generic {
189 store: "S3",
190 source: Box::new(source),
191 }
192 }
193}