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 PyNotImplementedError::new_err(print_with_debug(err))
136 }
137 object_store::Error::PermissionDenied { path: _, source: _ } => {
138 PermissionDeniedError::new_err(print_with_debug(err))
139 }
140 object_store::Error::Unauthenticated { path: _, source: _ } => {
141 UnauthenticatedError::new_err(print_with_debug(err))
142 }
143 object_store::Error::UnknownConfigurationKey { store: _, key: _ } => {
144 UnknownConfigurationKeyError::new_err(print_with_debug(err))
145 }
146 _ => GenericError::new_err(print_with_debug(err)),
147 },
148 PyObjectStoreError::IOError(err) => PyIOError::new_err(err),
149 }
150 }
151}
152
153fn print_with_debug(err: &object_store::Error) -> String {
154 format!("{err}\n\nDebug source:\n{err:#?}")
157}
158
159impl<'a, 'py> From<CastError<'a, 'py>> for PyObjectStoreError {
160 fn from(other: CastError<'a, 'py>) -> Self {
161 Self::PyErr(PyValueError::new_err(format!(
162 "Could not downcast: {other}",
163 )))
164 }
165}
166
167pub type PyObjectStoreResult<T> = Result<T, PyObjectStoreError>;
169
170#[derive(Debug, thiserror::Error)]
174pub(crate) enum ParseUrlError {
175 #[error(
176 "Unknown url scheme cannot be parsed into storage location: {}",
177 scheme
178 )]
179 UnknownUrlScheme { scheme: String },
180
181 #[error("URL did not match any known pattern for scheme: {}", url)]
182 UrlNotRecognised { url: String },
183}
184
185impl From<ParseUrlError> for object_store::Error {
186 fn from(source: ParseUrlError) -> Self {
187 Self::Generic {
188 store: "S3",
189 source: Box::new(source),
190 }
191 }
192}