正确使用可选包功能和依赖项

Proper use of optional package features and dependencies

我正在尝试为包 可选 提供一些方便的功能 foo 但我很难解决依赖项的依赖性问题。 具体来说,我想使用已安装的 bioconductor KEGGgraph-package if 中的一些功能。 KEGGgraph 本身依赖于 graph-包。 根据我的阅读(虽然不清楚)是按照建议包括 KEGGgraph(和 graph?)。

the documentation 我看到现在鼓励 requireNamespace 与在函数内部使用 :: 而不是 require 一起使用。事实上,如果使用 require,包裹检查也会报错。但是,当我使用 requireNamespace:: 时,找不到 KEGGgraph 的依赖项。

考虑以下最小的可重现示例。 安装 KEGGgraph 和全新的 R-session。 下面的函数在 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<-"

就好像requireNamespace什么也没做一样。错误重现 运行:

# 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)

如果调用了 require("KEGGgraph"),它工作正常:

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

用户真的有必要手动require这个可选包吗? 在函数定义的 if 条件中添加 && requireNamespace("graph") 似乎没有帮助。

这是 KEGGgraph 的问题 -- 它使用但不导入 graph::nodeDataDefaults<-。解决方案是联系 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 本身工作的原因——它取决于:在图形上,因此在搜索路径上找到丢失的导入;当你 requireNamespace(),你没有将 KEGGgraph 的 Depends: packages 添加到搜索路径,所以 nodeDataDefaults<- 没有找到。

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

解决方案几乎与 Martin 所建议的一样,从 graph 包中显式导入函数。我也借此机会更改了 KEGGgraph 的依赖策略,以便从中导入 graph 包而不是依赖它。希望这能让 KEGGgraph 对上述用例更加友好。

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