Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor error handling of the repository #233

Merged
merged 27 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Collate:
'parquet.R'
'pkg-knitr.R'
'pkg-nanoarrow.R'
'rerr.R'
'rlang.R'
'rust_result.R'
's3_methods.R'
Expand Down
5 changes: 5 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ S3method("$",ProtoExprArray)
S3method("$",RField)
S3method("$",RNullValues)
S3method("$",RPolarsDataType)
S3method("$",Rerr)
S3method("$",Series)
S3method("$",VecDataFrame)
S3method("$",When)
Expand Down Expand Up @@ -64,6 +65,7 @@ S3method("[[",ProtoExprArray)
S3method("[[",RField)
S3method("[[",RNullValues)
S3method("[[",RPolarsDataType)
S3method("[[",Rerr)
S3method("[[",Series)
S3method("[[",VecDataFrame)
S3method("[[",When)
Expand All @@ -77,13 +79,15 @@ S3method(.DollarNames,GroupBy)
S3method(.DollarNames,LazyFrame)
S3method(.DollarNames,PolarsBackgroundHandle)
S3method(.DollarNames,RField)
S3method(.DollarNames,Rerr)
S3method(.DollarNames,Series)
S3method(.DollarNames,VecDataFrame)
S3method(.DollarNames,When)
S3method(.DollarNames,WhenThen)
S3method(.DollarNames,WhenThenThen)
S3method(.DollarNames,method_environment)
S3method(.DollarNames,polars_option_list)
S3method(as.character,Rerr)
S3method(as.character,Series)
S3method(as.data.frame,DataFrame)
S3method(as.data.frame,LazyFrame)
Expand Down Expand Up @@ -120,6 +124,7 @@ S3method(print,PTime)
S3method(print,PolarsBackgroundHandle)
S3method(print,RField)
S3method(print,RPolarsDataType)
S3method(print,Rerr)
S3method(print,Series)
S3method(print,When)
S3method(print,WhenThen)
Expand Down
18 changes: 18 additions & 0 deletions R/extendr-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#' @useDynLib polars, .registration = TRUE
NULL

test_rerr <- function() .Call(wrap__test_rerr)

rlazy_csv_reader <- function(path, sep, has_header, ignore_errors, skip_rows, n_rows, cache, overwrite_dtype, low_memory, comment_char, quote_char, null_values, infer_schema_length, skip_rows_after_header, encoding, row_count_name, row_count_offset, parse_dates) .Call(wrap__rlazy_csv_reader, path, sep, has_header, ignore_errors, skip_rows, n_rows, cache, overwrite_dtype, low_memory, comment_char, quote_char, null_values, infer_schema_length, skip_rows_after_header, encoding, row_count_name, row_count_offset, parse_dates)

import_arrow_ipc <- function(path, n_rows, cache, rechunk, row_name, row_count, memmap) .Call(wrap__import_arrow_ipc, path, n_rows, cache, rechunk, row_name, row_count, memmap)
Expand Down Expand Up @@ -53,6 +55,20 @@ test_robj_to_i64 <- function(robj) .Call(wrap__test_robj_to_i64, robj)

test_robj_to_u32 <- function(robj) .Call(wrap__test_robj_to_u32, robj)

Rerr <- new.env(parent = emptyenv())

Rerr$new <- function() .Call(wrap__Rerr__new)

Rerr$info <- function() .Call(wrap__Rerr__info, self)

Rerr$contexts <- function() .Call(wrap__Rerr__contexts, self)

#' @export
`$.Rerr` <- function (self, name) { func <- Rerr[[name]]; environment(func) <- environment(); func }

#' @export
`[[.Rerr` <- `$.Rerr`

DataFrame <- new.env(parent = emptyenv())

DataFrame$shape <- function() .Call(wrap__DataFrame__shape, self)
Expand Down Expand Up @@ -829,6 +845,8 @@ LazyFrame$collect_background <- function() .Call(wrap__LazyFrame__collect_backgr

LazyFrame$collect <- function() .Call(wrap__LazyFrame__collect, self)

LazyFrame$collect_handled <- function() .Call(wrap__LazyFrame__collect_handled, self)

LazyFrame$first <- function() .Call(wrap__LazyFrame__first, self)

LazyFrame$last <- function() .Call(wrap__LazyFrame__last, self)
Expand Down
17 changes: 17 additions & 0 deletions R/rerr.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#' @title auto complete $-access into a polars object
#' @description called by the interactive R session internally
#' @param x Rerr
#' @param pattern code-stump as string to auto-complete
#' @export
#' @keywords internal
.DollarNames.Rerr = function(x, pattern = "") {
get_method_usages(Rerr, pattern = pattern)
}

#' @export
#' @noRd
as.character.Rerr = function(x) x$info()

#' @export
#' @noRd
print.Rerr = function(x) writeLines(x$info())
17 changes: 17 additions & 0 deletions man/dot-DollarNames.Rerr.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/rust/src/lazy/dataframe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ impl LazyFrame {
})
}

pub fn collect_handled(&self) -> crate::rerr::RResult<crate::rdataframe::DataFrame> {
use crate::rerr::WithRctx;
handle_thread_r_requests(self.clone().0).when("calling $collect() on LazyFrame")
}

fn first(&self) -> Self {
self.0.clone().first().into()
}
Expand Down
2 changes: 2 additions & 0 deletions src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod conversion_r_to_s;
pub mod conversion_s_to_r;
pub mod rdataframe;
pub mod rdatatype;
pub mod rerr;
pub mod rlib;
pub mod series;
pub mod utils;
Expand All @@ -37,6 +38,7 @@ static CONFIG: ThreadComStorage = Storage::new();
// Macro to generate exports
extendr_module! {
mod polars;
use rerr;
use rdataframe;
use lazy;
use series;
Expand Down
10 changes: 5 additions & 5 deletions src/rust/src/rdataframe/read_ipc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::lazy::dataframe::LazyFrame as RLazyFrame;
use crate::{robj_to, Error::Other, Result};
use crate::rerr::RResult;
use crate::robj_to;
use extendr_api::prelude::*;
use polars::io::RowCount;
use polars::prelude::{LazyFrame, ScanArgsIpc};
Expand All @@ -13,7 +14,7 @@ pub fn import_arrow_ipc(
row_name: Robj,
row_count: Robj,
memmap: Robj,
) -> Result<RLazyFrame> {
) -> RResult<RLazyFrame> {
let args = ScanArgsIpc {
n_rows: robj_to!(Option, usize, n_rows)?,
cache: robj_to!(bool, cache)?,
Expand All @@ -23,9 +24,8 @@ pub fn import_arrow_ipc(
.transpose()?,
memmap: robj_to!(bool, memmap)?,
};
LazyFrame::scan_ipc(robj_to!(String, path)?, args)
.map_err(|x| Other(format!("Polaris internal error: {x}")))
.map(RLazyFrame)
let lf = LazyFrame::scan_ipc(robj_to!(String, path)?, args)?;
Ok(RLazyFrame(lf))
}

extendr_module! {
Expand Down
130 changes: 130 additions & 0 deletions src/rust/src/rerr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use extendr_api::{extendr, extendr_module, symbol::class_symbol, Attributes, Rinternals, Robj};

#[derive(Clone, Debug)]
pub enum Rctx {
Extendr(String),
Hint(String),
Plain(String),
Polars(String),
When(String),
TypeMismatch(String, String, String),
}

#[derive(Clone, Debug)]
pub struct Rerr(Vec<Rctx>);
pub type RResult<T> = core::result::Result<T, Rerr>;

pub trait WithRctx<T> {
fn ctx(self, rctx: Rctx) -> RResult<T>;
fn hint<S: Into<String>>(self, msg: S) -> RResult<T>;
fn when<S: Into<String>>(self, msg: S) -> RResult<T>;
}

impl<T: Clone, E: Into<Rerr>> WithRctx<T> for core::result::Result<T, E> {
Sicheng-Pan marked this conversation as resolved.
Show resolved Hide resolved
fn ctx(self, rctx: Rctx) -> RResult<T> {
self.map_err(|e| {
let mut rerr = e.into();
rerr.0.push(rctx);
rerr
})
}

fn hint<S: Into<String>>(self, msg: S) -> RResult<T> {
self.ctx(Rctx::Hint(msg.into()))
}

fn when<S: Into<String>>(self, msg: S) -> RResult<T> {
self.ctx(Rctx::When(msg.into()))
}
}

#[extendr]
impl Rerr {
pub fn new() -> Self {
Rerr(Vec::new())
}

pub fn info(&self) -> String {
self.0
.iter()
.rev()
.map(|rctx| match rctx {
Rctx::Extendr(e) => format!("Encountered the following error in Extendr:\n{}", e),
Rctx::Hint(e) => format!("An error occured likely because {}", e),
Rctx::Plain(e) => e.clone(),
Rctx::Polars(e) => format!("Encountered the following error in Polars:\n{}", e),
Rctx::TypeMismatch(name, expected, received) => {
format!(
"The argument [{}] should be a [{}] value, but got [{}] instead",
name, expected, received
)
}
Rctx::When(e) => format!("When {}", e),
})
.fold(String::from("Error"), |msg, ctx| {
format!("{}: {}", msg, ctx)
})
}

pub fn contexts(&self) -> Vec<&str> {
self.0
.iter()
.rev()
.map(|rctx| match rctx {
Rctx::Extendr(_) => "Extendr",
Rctx::Hint(_) => "Hint",
Rctx::Plain(_) => "Plain",
Rctx::Polars(_) => "Polars",
Rctx::TypeMismatch(_, _, _) => "TypeMismatch",
Rctx::When(_) => "When",
})
.collect()
}
Sicheng-Pan marked this conversation as resolved.
Show resolved Hide resolved
}

// Implementation for transition
impl From<String> for Rerr {
fn from(err_msg: String) -> Self {
Rerr(vec![Rctx::Plain(err_msg)])
}
}

impl From<extendr_api::Error> for Rerr {
fn from(extendr_err: extendr_api::Error) -> Self {
Rerr(vec![Rctx::Extendr(format!("{:?}", extendr_err))])
}
}

impl From<polars::error::PolarsError> for Rerr {
fn from(polars_err: polars::error::PolarsError) -> Self {
let mut rerr = Rerr::new();
rerr.0.push(Rctx::Polars(format!("{:?}", polars_err)));
match polars_err {
polars::prelude::PolarsError::InvalidOperation(x) => {
rerr.0.push(Rctx::Hint(format!(
"something (likely a column) with name {:?} is not found",
x
)));
}
_ => {}
};
rerr
}
}

#[extendr]
pub fn test_rerr() -> RResult<String> {
Err(Rerr::new())
.ctx(Rctx::TypeMismatch(
"path".to_string(),
"String".to_string(),
"2.0".to_string(),
))
.when("calling test function")
}

extendr_module! {
mod rerr;
impl Rerr;
fn test_rerr;
}
Loading