Warm tip: This article is reproduced from serverfault.com, please click

Calling stop( ) within function causes R CMD Check to throw error

发布于 2020-12-03 09:19:11

I am attempting to call stop( ) from within an internal package function (stop_quietly()) which should break the function and return to the topline. This works except that R CMD Check thinks this is an error because I am forcing stop.

How do I get around the R CMD check interpreting this as an error? The function needs to stop since it requires user input as a confirmation before it creates a file directory tree at a given location. The code currently produces a message and stops the function.

tryCatch({
      path=normalizePath(path=where, winslash = "\\", mustWork = TRUE)
      message(paste0("This will create research directories in the following directory: \n",path))
      confirm=readline(prompt="Please confirm [y/n]:")
      if(tolower(stringr::str_trim(confirm)) %in% c("y","yes","yes.","yes!","yes?")){
         .....
         dir.create(path, ... [directories])
         .....
       }
       message("There, I did some work, now you do some work.")
      }
        else{
        message("Okay, fine then. Don't do your research. See if I care.")
        stop_quietly()
      }
    },error=function(e){message("This path does not work, please enter an appropriate path \n or set the working directory with setwd() and null the where parameter.")})

stop_quietly is an exit function I took from this post with the modification of error=NULL which suppresses R executing the error handler as a Browser. I do not want the function to terminate to a Browser I just want it to quit without throwing an error in the R CMD Check.

stop_quietly <- function() {
  opt <- options(show.error.messages = FALSE, error=NULL)
  on.exit(options(opt))
  stop()
}

Here is the component of the error R CMD produces:

-- R CMD check results ------------------------------------------------ ResearchDirectoR 1.0.0 ----
Duration: 12.6s

> checking examples ... ERROR
  Running examples in 'ResearchDirectoR-Ex.R' failed
  The error most likely occurred in:
  
  > base::assign(".ptime", proc.time(), pos = "CheckExEnv")
  > ### Name: create_directories
  > ### Title: Creates research directories
  > ### Aliases: create_directories
  > 
  > ### ** Examples
  > 
  > create_directories()
  This will create research directories in your current working directory: 
  C:/Users/Karnner/AppData/Local/Temp/RtmpUfqXvY/ResearchDirectoR.Rcheck
  Please confirm [y/n]:
  Okay, fine then. Don't do your research. See if I care.
  Execution halted
Questioner
Jonathan Fluharty-Jaidee
Viewed
0
user2554330 2020-12-04 18:30:05

Since your function has global side effects, I think check isn't going to like it. It would be different if you required the user to put tryCatch at the top level, and then let it catch the error. But think about this scenario: a user defines f() and calls it:

f <- function() {
  call_your_function()
  do_something_essential()
}
f()

If your function silently caused it to skip the second line of f(), it could cause a lot of trouble for the user.

What you could do is tell the user to wrap the call to your function in tryCatch(), and have it catch the error:

f <- function() {
  tryCatch(call_your_function(), error = function(e) ...)
  do_something_essential()
}
f()

This way the user will know that your function failed, and can decide whether or not to continue.

From discussion in the comments and your edit to the question, it seems like your function is only intended to be used interactively, so the above scenario isn't an issue. In that case, you can avoid the R CMD check problems by skipping the example unless it is being run interactively. This is fairly easy: in the help page for a function like create_directories(), set up your example as

if (interactive()) {
  create_directories()
  # other stuff if you want
}

The checks are run with interactive() returning FALSE, so this will stop the error from ever happening in the check. You could also use tryCatch within create_directories() to catch the error coming up from below if that makes more sense in your package.