Search code examples
renumerationr-s4

How to enumerate all S4 methods implemented by a package?


I'm looking for a way to query all S4 methods implemented by a particular package (given through its namespace environment). I think I could enumerate all objects that start with .__T__, but I'd rather prefer using a documented and/or less hackish way.

> ls(asNamespace("RSQLite"), all.names = TRUE, pattern = "^[.]__T__")
 [1] ".__T__dbBegin:DBI"                 ".__T__dbBeginTransaction:RSQLite" 
 [3] ".__T__dbBind:DBI"                  ".__T__dbClearResult:DBI"          
 [5] ".__T__dbColumnInfo:DBI"            ".__T__dbCommit:DBI"               
 [7] ".__T__dbConnect:DBI"               ".__T__dbDataType:DBI"             
 [9] ".__T__dbDisconnect:DBI"            ".__T__dbExistsTable:DBI"          
[11] ".__T__dbFetch:DBI"                 ".__T__dbGetException:DBI"         
[13] ".__T__dbGetInfo:DBI"               ".__T__dbGetPreparedQuery:RSQLite" 
[15] ".__T__dbGetQuery:DBI"              ".__T__dbGetRowCount:DBI"          
[17] ".__T__dbGetRowsAffected:DBI"       ".__T__dbGetStatement:DBI"         
[19] ".__T__dbHasCompleted:DBI"          ".__T__dbIsValid:DBI"              
[21] ".__T__dbListFields:DBI"            ".__T__dbListResults:DBI"          
[23] ".__T__dbListTables:DBI"            ".__T__dbReadTable:DBI"            
[25] ".__T__dbRemoveTable:DBI"           ".__T__dbRollback:DBI"             
[27] ".__T__dbSendPreparedQuery:RSQLite" ".__T__dbSendQuery:DBI"            
[29] ".__T__dbUnloadDriver:DBI"          ".__T__dbWriteTable:DBI"           
[31] ".__T__fetch:DBI"                   ".__T__isSQLKeyword:DBI"           
[33] ".__T__make.db.names:DBI"           ".__T__show:methods"               
[35] ".__T__sqlData:DBI"                 ".__T__SQLKeywords:DBI"            

Solution

  • I think showMethods is the only thing available in methods, but it does not actually return the functions as an object, just prints them to the screen.

    The following will return a list of the methods defined in an environment. Adapted from covr::replacements_S4(), which is used to modify all methods in a package to track coverage.

    S4_methods <- function(env) {
      generics <- methods::getGenerics(env)
    
      res <- Map(generics@.Data, generics@package, USE.NAMES = FALSE,
        f = function(name, package) {
          what <- methods::methodsPackageMetaName("T", paste(name, package, sep = ":"))
    
          table <- get(what, envir = env)
    
          mget(ls(table, all.names = TRUE), envir = table)
        })
      res[lengths(res) > 0]
    }
    
    m <- S4_methods(asNamespace("DBI"))
    length(m)
    #> [1] 21
    m[1:3]
    #> [[1]]
    #> [[1]]$DBIObject
    #> function(dbObj, obj, ...) {
    #>   dbiDataType(obj)
    #> }
    #> <environment: namespace:DBI>
    #> attr(,"target")
    #> An object of class "signature"
    #>       dbObj 
    #> "DBIObject" 
    #> attr(,"defined")
    #> An object of class "signature"
    #>       dbObj 
    #> "DBIObject" 
    #> attr(,"generic")
    #> [1] "dbDataType"
    #> attr(,"generic")attr(,"package")
    #> [1] "DBI"
    #> attr(,"class")
    #> [1] "MethodDefinition"
    #> attr(,"class")attr(,"package")
    #> [1] "methods"
    #> 
    #> 
    #> [[2]]
    #> [[2]]$character
    #> function(drvName, ...) {
    #>     findDriver(drvName)(...)
    #>   }
    #> <environment: namespace:DBI>
    #> attr(,"target")
    #> An object of class "signature"
    #>     drvName 
    #> "character" 
    #> attr(,"defined")
    #> An object of class "signature"
    #>     drvName 
    #> "character" 
    #> attr(,"generic")
    #> [1] "dbDriver"
    #> attr(,"generic")attr(,"package")
    #> [1] "DBI"
    #> attr(,"class")
    #> [1] "MethodDefinition"
    #> attr(,"class")attr(,"package")
    #> [1] "methods"
    #> 
    #> 
    #> [[3]]
    #> [[3]]$`DBIConnection#character`
    #> function(conn, statement, ...) {
    #>     rs <- dbSendStatement(conn, statement, ...)
    #>     on.exit(dbClearResult(rs))
    #>     dbGetRowsAffected(rs)
    #>   }
    #> <environment: namespace:DBI>
    #> attr(,"target")
    #> An object of class "signature"
    #>            conn       statement 
    #> "DBIConnection"     "character" 
    #> attr(,"defined")
    #> An object of class "signature"
    #>            conn       statement 
    #> "DBIConnection"     "character" 
    #> attr(,"generic")
    #> [1] "dbExecute"
    #> attr(,"generic")attr(,"package")
    #> [1] "DBI"
    #> attr(,"class")
    #> [1] "MethodDefinition"
    #> attr(,"class")attr(,"package")
    #> [1] "methods"