Proper use of optional package features and dependencies

时间:2015-05-24 22:10:35

标签: r dependencies r-package

I'm trying to provide some optional, convenient features to a package foo but I struggle with the dependencies of the dependencies. Specifically, I'd like to use some features from the bioconductor KEGGgraph-package if it is installed. KEGGgraph itself depends on the graph-package. From what I read (although it is not clear) is to include KEGGgraph (and graph?) as suggested.

From the documentation I see that requireNamespace is now encouraged together with usage of :: instead of require inside functions. Indeed the package check will also complain if require is used. However, when I use requireNamespace and :: the dependencies of KEGGgraph is not found.

Consider the following minimal reproducible example. With KEGGgraph installed and a fresh R-session. The function below cannot find a function in the graph-package:

# If KEGGgraph is not installed:
#source("http://bioconductor.org/biocLite.R")
#biocLite("KEGGgraph")

convenientFunction <- function() {
  if (requireNamespace("KEGGgraph")) {
    tmp.file <- paste0(tempfile(), ".kgml")
    kgml <- KEGGgraph::retrieveKGML("hsa:04115", organism = "hsa",
                                    destfile = tmp.file, method = "internal")
    return(KEGGgraph::parseKGML2DataFrame(tmp.file))
  } else {
    stop("This function needs KEGGgraph and its dependencies")
  }
}

convenientFunction()
#Loading required namespace: KEGGgraph
#trying URL 'http://www.genome.jp/kegg-bin/download?entry=hsa04115&format=kgml'
#Content type 'text/xml' length unknown
#opened URL
#.......... .......... ......
#downloaded 26 KB
#
# Error in nodeDataDefaults(gR, "KEGGNode") <- env.node : 
#  could not find function "nodeDataDefaults<-"

It is as-if requireNamespace does nothing. The error reproduce by running:

# In a new R-session...
requireNamespace("KEGGgraph") # With and without this line
tmp.file <- paste0(tempfile(), ".kgml")
kgml <- KEGGgraph::retrieveKGML("hsa:04115", organism = "hsa",
                                destfile = tmp.file, method = "internal")
KEGGgraph::parseKGML2DataFrame(tmp.file)

If require("KEGGgraph") has been called it works fine:

require("KEGGgraph")
res <- convenientFunction()

Is it really necessary for users to require this optional package manually? Adding && requireNamespace("graph") into the if-condition in the function definition does not seem to help.

2 个答案:

答案 0 :(得分:3)

这是KEGGgraph的问题 - 它使用但不导入graph :: nodeDataDefaults&lt; - 。解决方案是与maintainer("KEGGgraph")取得联系并要求他们更新他们的NAMESPACE

KEGGgraph$ svn diff
Index: NAMESPACE
===================================================================
--- NAMESPACE   (revision 104133)
+++ NAMESPACE   (working copy)
@@ -2,7 +2,7 @@

 importFrom(XML, "xmlAttrs", "xmlChildren", "xmlName", "xmlRoot", "xmlTreeParse")

-importFrom(graph, "edges", "nodes<-", "nodes", "edgeData")
+importFrom(graph, "edges", "nodes<-", "nodes", "edgeData", "nodeDataDefaults<-")

 exportPattern("^[^\\.]")
 exportMethods("getDisplayName",

似乎还有其他缺失的进口,严厉的解决方案只是import(graph);一个较轻但不完美的触摸是使用codetoolsBioC :: writeNamespaceImports()来生成导入(这个函数是错误的,因此不要依赖于100%)。

解决方法是在您的包裹中说library(graph)Depends: graph;这会将图形放在search()路径上,而KEGGgraph会在那里找到缺少的导入(这就是为什么KEGGgraph本身有效 - 它取决于:在图表上,因此在搜索路径上找到了缺少的导入;当你{{ 1}},你没有将KEGGgraph的Depends:包添加到搜索路径,因此找不到requireNamespace() - 。

答案 1 :(得分:3)

我是KEGGgraph的维护者。我确认了问题,并更新了包。在Bioconductor subversion资源库修订版103436中,该问题已得到解决,并有望得到解决。

解决方案几乎与Martin建议的一样,是从 graph 包中明确导入函数。我抓住机会也改变了 KEGGgraph 的依赖关系策略,以便导入图形包而不是依赖它。希望这使得KEGGgraph对上述用例更加友好。

感谢您报告此问题,感谢Martin和Dirk的回答。