Bill Dunlap
2008-Sep-09 20:48 UTC
[Rd] should system.file(package="no such pkg", "no such file") warn or abort?
Currently system.file(package="no such pkg","no","such","file") silently returns the empty string, "", if said file doesn't exist. This forces the caller to check for "" or risk getting a mysterious error message from a function requiring a file name. E.g., > read.dcf(system.file(package="no such pkg","DESCRIPTION")) Error in gzfile(file, "r") : cannot open the connection In addition: Warning message: In gzfile(file, "r") : cannot open compressed file '', probable reason 'No such file or directory' > readLines(system.file(package="no such pkg","no","such","file")) character(0) Warning message: In file(con, "r") : file("") only supports open = "w+" and open = "w+b": using the former > read.table(system.file(package="no such pkg","examples","data.txt")) Error in read.table(system.file(package = "no such pkg", "examples", "data.txt")) : no lines available in input In addition: Warning message: In file(file, "r") : file("") only supports open = "w+" and open = "w+b": using the former I think it would help if system.file(), by default, threw an error in this case. It could have an argument to suppress the error if the caller desires. I suppose it could just have a warning. I've attached a prototype, with the new argument missingFileOK=FALSE. (I don't like the name, but didn't take the time to come up with something better.) > read.table(system.file(package="no such pkg","examples","data.txt")) Error in system.file(package = "no such pkg", "examples", "data.txt") : Cannot find package "no such pkg" > read.table(system.file(package="base", "no", "such", "file")) Error in system.file(package = "base", "no", "such", "file") : Cannot find file "no/such/file" in package "base" > system.file(package="no such pkg","examples","data.txt", missingFileOK=TRUE) [1] "" Is this sort of thing desirable? It would require changes to code that calls system.file() and checks for its output being "", but it would make code that doesn't make the check work better. `system.file` <- function (..., package = "base", lib.loc = NULL, missingFileOK = FALSE) { if (nargs() == 0) return(file.path(.Library, "base")) if (length(package) != 1) stop("'package' must be of length 1") packagePath <- .find.package(package, lib.loc, quiet = TRUE) if (length(packagePath) == 0) { if (missingFileOK) return("") else stop("Cannot find package ", dQuote(package)) } FILES <- file.path(packagePath, ...) present <- file.exists(FILES) if (any(present)) FILES[present] else if (missingFileOK) "" else stop("Cannot find file ", dQuote(file.path(...)), " in package ", dQuote(package)) } The diffs are --- system.file.R~ 2008-09-09 13:47:06.608527000 -0700 +++ system.file.R 2008-09-09 11:46:41.509481000 -0700 @@ -1,16 +1,23 @@ `system.file` <- -function (..., package = "base", lib.loc = NULL) +function (..., package = "base", lib.loc = NULL, missingFileOK = FALSE) { if (nargs() == 0) return(file.path(.Library, "base")) if (length(package) != 1) stop("'package' must be of length 1") packagePath <- .find.package(package, lib.loc, quiet = TRUE) - if (length(packagePath) == 0) - return("") + if (length(packagePath) == 0) { + if (missingFileOK) + return("") + else + stop("Cannot find package ", dQuote(package)) + } FILES <- file.path(packagePath, ...) present <- file.exists(FILES) if (any(present)) FILES[present] - else "" + else if (missingFileOK) + "" + else stop("Cannot find file ", dQuote(file.path(...)), " in package ", dQuote(package)) } ---------------------------------------------------------------------------- Bill Dunlap TIBCO Spotfire bill at insightful dot com (for a while) "All statements in this message represent the opinions of the author and do not necessarily reflect TIBCO Software Inc. policy or position."