Skip to content

Commit

Permalink
feat: introduced a ColumnNotFoundError exception
Browse files Browse the repository at this point in the history
Signed-off-by: Luka Peschke <[email protected]>
  • Loading branch information
lukapeschke committed Feb 25, 2024
1 parent e280782 commit 35bb5a6
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 13 deletions.
2 changes: 2 additions & 0 deletions python/fastexcel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
CalamineCellError,
CalamineError,
CannotRetrieveCellDataError,
ColumnNotFoundError,
FastExcelError,
InvalidParametersError,
SheetNotFoundError,
Expand Down Expand Up @@ -224,6 +225,7 @@ def read_excel(path: Path | str) -> ExcelReader:
"CalamineCellError",
"CalamineError",
"SheetNotFoundError",
"ColumnNotFoundError",
"ArrowError",
"InvalidParametersError",
"UnsupportedColumnTypeCombinationError",
Expand Down
1 change: 1 addition & 0 deletions python/fastexcel/_fastexcel.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ class CannotRetrieveCellDataError(FastExcelError): ...
class CalamineCellError(FastExcelError): ...
class CalamineError(FastExcelError): ...
class SheetNotFoundError(FastExcelError): ...
class ColumnNotFoundError(FastExcelError): ...
class ArrowError(FastExcelError): ...
class InvalidParametersError(FastExcelError): ...
1 change: 1 addition & 0 deletions python/tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def test_sheet_not_found_error() -> None:
"calamine returned an error regarding the content of the cell",
),
(fastexcel.CalamineError, "Generic calamine error"),
(fastexcel.ColumnNotFoundError, "Column was not found"),
(fastexcel.SheetNotFoundError, "Sheet was not found"),
(fastexcel.ArrowError, "Generic arrow error"),
(fastexcel.InvalidParametersError, "Provided parameters are invalid"),
Expand Down
41 changes: 31 additions & 10 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
use std::{error::Error, fmt::Display};

#[derive(Debug)]
pub(crate) enum SheetIdxOrName {
pub(crate) enum IdxOrName {
Idx(usize),
// Leaving this variant if someday we want to check if a name exists before calling worksheet_range
#[allow(dead_code)]
Name(String),
}

impl IdxOrName {
pub(super) fn format_message(&self) -> String {
match self {
Self::Idx(idx) => format!("at index {idx}"),
Self::Name(name) => format!("with name \"{name}\" not found"),
}
}
}

#[derive(Debug)]
pub(crate) enum FastExcelErrorKind {
UnsupportedColumnTypeCombination(String),
CannotRetrieveCellData(usize, usize),
CalamineCellError(calamine::CellErrorType),
CalamineError(calamine::Error),
SheetNotFound(SheetIdxOrName),
SheetNotFound(IdxOrName),
ColumnNotFound(IdxOrName),
// Arrow errors can be of several different types (arrow::error::Error, PyError), and having
// the actual type has not much value for us, so we just store a string context
ArrowError(String),
Expand All @@ -37,14 +45,13 @@ impl Display for FastExcelErrorKind {
write!(f, "calamine error: {calamine_error}")
}
FastExcelErrorKind::SheetNotFound(idx_or_name) => {
let message = {
match idx_or_name {
SheetIdxOrName::Idx(idx) => format!("at index {idx}"),
SheetIdxOrName::Name(name) => format!("with name \"{name}\" not found"),
}
};
let message = idx_or_name.format_message();
write!(f, "sheet {message} not found")
}
FastExcelErrorKind::ColumnNotFound(idx_or_name) => {
let message = idx_or_name.format_message();
write!(f, "column {message} not found")
}
FastExcelErrorKind::ArrowError(err) => write!(f, "arrow error: {err}"),
FastExcelErrorKind::InvalidParameters(err) => write!(f, "invalid parameters: {err}"),
}
Expand All @@ -70,6 +77,10 @@ impl FastExcelError {
context: vec![],
}
}

pub(crate) fn kind(&self) -> &FastExcelErrorKind {
&self.kind
}
}

impl Display for FastExcelError {
Expand Down Expand Up @@ -166,6 +177,13 @@ pub(crate) mod py_errors {
FastExcelError,
"Sheet was not found"
);
// Sheet not found
create_exception!(
_fastexcel,
ColumnNotFoundError,
FastExcelError,
"Column was not found"
);
// Arrow error
create_exception!(
_fastexcel,
Expand Down Expand Up @@ -209,6 +227,9 @@ pub(crate) mod py_errors {
FastExcelErrorKind::SheetNotFound(_) => {
SheetNotFoundError::new_err(message)
}
FastExcelErrorKind::ColumnNotFound(_) => {
ColumnNotFoundError::new_err(message)
}
FastExcelErrorKind::ArrowError(_) => ArrowError::new_err(message),
FastExcelErrorKind::InvalidParameters(_) => {
InvalidParametersError::new_err(message)
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ fn _fastexcel(py: Python, m: &PyModule) -> PyResult<()> {
"SheetNotFoundError",
py.get_type::<py_errors::SheetNotFoundError>(),
),
(
"ColumnNotFoundError",
py.get_type::<py_errors::ColumnNotFoundError>(),
),
("ArrowError", py.get_type::<py_errors::ArrowError>()),
(
"InvalidParametersError",
Expand Down
6 changes: 3 additions & 3 deletions src/types/excelreader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use calamine::{open_workbook_auto, Reader, Sheets};
use pyo3::{pyclass, pymethods, PyResult};

use crate::error::{
py_errors::IntoPyResult, ErrorContext, FastExcelErrorKind, FastExcelResult, SheetIdxOrName,
py_errors::IntoPyResult, ErrorContext, FastExcelErrorKind, FastExcelResult, IdxOrName,
};

use super::{
Expand Down Expand Up @@ -99,7 +99,7 @@ impl ExcelReader {
let name = self
.sheet_names
.get(idx)
.ok_or_else(|| FastExcelErrorKind::SheetNotFound(SheetIdxOrName::Idx(idx)).into())
.ok_or_else(|| FastExcelErrorKind::SheetNotFound(IdxOrName::Idx(idx)).into())
.with_context(|| {
format!(
"Sheet index {idx} is out of range. File has {} sheets",
Expand All @@ -114,7 +114,7 @@ impl ExcelReader {
.worksheet_range_at(idx)
// Returns Option<Result<Range<Data>, Self::Error>>, so we convert the Option into a
// SheetNotFoundError and unwrap it
.ok_or_else(|| FastExcelErrorKind::SheetNotFound(SheetIdxOrName::Idx(idx)).into())
.ok_or_else(|| FastExcelErrorKind::SheetNotFound(IdxOrName::Idx(idx)).into())
.into_pyresult()?
// And here, we convert the calamine error in an owned error and unwrap it
.map_err(|err| FastExcelErrorKind::CalamineError(err).into())
Expand Down

0 comments on commit 35bb5a6

Please sign in to comment.