-
Notifications
You must be signed in to change notification settings - Fork 16
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
Added error handling to multiple functions in R/assign_job_queue.R, R/blastWrappers.R #76
Conversation
- let R-CMD sort NAMESPACE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the extra work here @Seyi007! Providing error handling for these functions will definitely be a worthwhile endeavor. I've rebased this PR on the current main branch to pull in some function name changes and .Rd files that have been submitted in other PRs.
I'd like to see a few modifications before I review further:
tryCatch()
In R, the finally
portion is always evaluated, even if the function generates an error or warning.
Printing “{function} execution completed.” might introduce confusion among our users, as they may think the function executed successfully even if an error occurred. Additionally, it could be overly verbose. I’d prefer to reserve the finally portion of each tryCatch() for cleanup or custom handler functions rather than messaging.
print()
VS message()
This is both a stylistic and functional request. Given the choice between message()
and print()
I'd prefer that we use message()
. Essentially, when using message, users may choose to suppress the additional messaging with suppressWarnings()
or suppressMessages()
-- print()
is harder to escape and I'd rather give the user the choice.
Best option
Use rlang::inform()
, rlang::warn()
, and rlang::abort()
where appropriate:
Next Steps
Please consider the suggested modifications and submit the PR again for further review. Your efforts are greatly appreciated, and I’m looking forward to seeing the improvements!
Thanks for all your work on this @Seyi007. excellent points, @the-mayer! Looking forward to the changes! |
Duly noted @the-mayer , I'll get to work on this! |
- Replaced base R error handling with rlang functions: `abort()`, `warn()`, and `inform()`. - Improved clarity and consistency in error and warning messages. - Enhanced robustness with detailed context for errors and warnings.
Hi @the-mayer @jananiravi , I've implemented the suggestions made earlier and have updated the error handling in the R/acc2lin.R. Kindly review and let me know if I'm missing anything, while I work on the remaining functions. |
…file - Replaced base R error handling with rlang functions: `abort()`, `warn()`, and `inform()`. - Improved clarity and consistency in error and warning messages. - Enhanced robustness with detailed context for errors and warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! Generally, I think having better error reporting will really help things, so thank you for the contribution.
I'm inexperienced at R, so take my comments with a grain of salt. Anyway, I made some suggestions in keeping with what @the-mayer had recommended in a previous comment.
R/blastWrappers.R
Outdated
stop("The DELTABLAST executable path is invalid: ", deltablast_path) | ||
} | ||
if (!dir.exists(db_search_path)) { | ||
stop("The database search path is invalid: ", db_search_path) | ||
} | ||
if (!file.exists(query)) { | ||
stop("The query file path is invalid: ", query) | ||
} | ||
if (!is.numeric(as.numeric(evalue)) || as.numeric(evalue) <= 0) { | ||
stop("The evalue must be a positive number: ", evalue) | ||
} | ||
if (!is.numeric(num_alignments) || num_alignments <= 0) { | ||
stop("The number of alignments must be a | ||
positive integer: ", num_alignments) | ||
} | ||
if (!is.numeric(num_threads) || num_threads <= 0) { | ||
stop("The number of threads must be a positive integer: ", num_threads) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO it would be better to use rlang::abort()
here rather than stop()
, as you do in the rest of your code.
R/blastWrappers.R
Outdated
}, error = function(e) { | ||
message(paste("Error in run_deltablast: ", e)) | ||
}, warning = function(w) { | ||
message(paste("Warning in run_deltablast: ", w)) | ||
}, finally = { | ||
message("run_deltablast completed") | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd consider switching out these message()
calls for the rlang
equivalents, e.g. rlang::error()
in the error handler, and rlang::warn()
in the warning.
As @the-mayer mentioned, I'd also remove the finally
clause entirely, since it'll also be displayed with an error/warning output. Generally, finally
should be used when you really need to clean something up, even if there's an error that would ordinarily terminate execution, not for regular reporting.
R/blastWrappers.R
Outdated
if (!file.exists(rpsblast_path)) { | ||
stop("The RPSBLAST executable path is invalid: ", rpsblast_path) | ||
} | ||
if (!dir.exists(db_search_path)) { | ||
stop("The database search path is invalid: ", db_search_path) | ||
} | ||
if (!file.exists(query)) { | ||
stop("The query file path is invalid: ", query) | ||
} | ||
if (!is.numeric(as.numeric(evalue)) || as.numeric(evalue) <= 0) { | ||
stop("The evalue must be a positive number: ", evalue) | ||
} | ||
if (!is.numeric(num_threads) || num_threads <= 0) { | ||
stop("The number of threads must be a positive integer: ", num_threads) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above; rlang::abort()
is a better option than stop()
.
R/blastWrappers.R
Outdated
}, error = function(e) { | ||
message(paste("Error in run_rpsblast: ", e)) | ||
}, warning = function(w) { | ||
message(paste("Warning in run_rpsblast: ", w)) | ||
}, finally = { | ||
message("run_rpsblast completed") | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above; the error handler should call rlang::error()
rather than message()
, warning should call rlang::warn()
, and the finally handler should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I haven't updated the R/blastWrappers.R file with the suggestions from @the-mayer . I've only updated the first 2 files, and I'm currently working on the said file.
R/assign_job_queue.R
Outdated
@@ -1,3 +1,4 @@ | |||
suppressPackageStartupMessages(library(rlang)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally packages shouldn't invoke library()
, since it'll import symbols into the user's namespace that they might not be expecting.
Instead, you should add the following line to the docstrings of functions that use rlang::abort()
, rlang::warn()
, etc. (with the elements after rlang
being the symbols you're using from rlang
in that specific function):
#' @importFrom rlang abort warn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duly noted! I'll include it in my next commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you are importing multiple functions from that library, it is better to include it as a dependency in the imports
list here.
R/msa.R
Outdated
) | ||
prot_aa | ||
prot_aa <- readAAStringSet( | ||
fa_file, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! The path parameter is indeed named filepath
, not path
as it was in the original code.
It's fine to leave it as a positional parameter as you have it here, since it's the first parameter.
R/acc2lin.R
Outdated
# capturing the call stack | ||
call = sys.call(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can leave call
at its default value, i.e. remove it from the list of arguments. FAICT the argument is intended to be used when you want the stack trace to appear as if it came from another method (e.g., not a helper method). I didn't see any difference in my testing, at least, with it unset versus setting it to sys.call()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Faisal, what's FAICT?
R/acc2lin.R
Outdated
message = paste("Warning during IPG fetching | ||
or lineage processing:", w$message), | ||
class = "lineage_processing_warning", | ||
call = sys.call(), # capturing the call stack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above; its default value seems to work fine, so you can remove call
here.
R/acc2lin.R
Outdated
abort( | ||
message = paste("An error occurred: ", e$message), | ||
class = "fetch_error", | ||
call = sys.call(), | ||
accnums = accnums, | ||
out_path = out_path, | ||
plan = plan | ||
) | ||
}, warning = function(w) { | ||
warn( | ||
message = paste("Warning: ", w$message), | ||
class = "fetch_warning", | ||
call = sys.call(), | ||
accnums = accnums, | ||
out_path = out_path, | ||
plan = plan | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like the other invocations above, these both include call
as well, but don't need to.
R/acc2lin.R
Outdated
abort( | ||
message = paste("An error occurred: ", e$message), | ||
class = "processing_error", | ||
call = sys.call(), | ||
accessions = accessions, | ||
ipg_file = ipg_file, | ||
assembly_path = assembly_path, | ||
lineagelookup_path = lineagelookup_path | ||
) | ||
}, warning = function(w) { | ||
warn( | ||
message = paste("Warning: ", w$message), | ||
class = "processing_warning", | ||
call = sys.call(), | ||
accessions = accessions, | ||
ipg_file = ipg_file, | ||
assembly_path = assembly_path, | ||
lineagelookup_path = lineagelookup_path | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above; you don't need to specify call
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duly Noted!
- Added robust error handling in run_deltablast and run_rpsblast functions. - Updated Roxygen documentation to import rlang::abort, rlang::warn and rlang::inform for better error management. - Refactored code for clarity and consistency based on the suggestion from the last review.
Hi @jananiravi @falquaddoomi, I've implemented all the changes required from the previous review in my latest commit. Could you review this and let me know if I'm missing anything? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, looks like you got to everything I raised.
@falquaddoomi @the-mayer followed the conversation but not the most recent line-by-line edits. Feel free to merge if this looks good. Thanks, @Seyi007 ! |
Yay! Thank you @falquaddoomi @jananiravi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Seyi007, sending to main!
Implement error handling for mapOption2Process, get_proc_medians, write_proc_medians_table, get_proc_weights, advanced_opts2est_walltime, assign_job_queue, and plot_estimated_walltimes .
Validate input arguments for each function to ensure they meet expected criteria.
Use tryCatch blocks to handle errors and warnings gracefully.
Provide informative error messages and detailed logging where appropriate.
Ensure functions fail gracefully and provide useful feedback.
Feature (adds or updates new capabilities)
Bug fix (fixes an issue).
Enhancement (adds functionality).
Breaking change (these changes would cause existing functionality to not work as expected).
Checklist