Skip to content

Packages of S4 functions are not identified by packagesOf() #73

@DavisVaughan

Description

@DavisVaughan

Notice that DBI is not recognized as a required package in fn(). dbConnect() is a function from DBI.

library(globals)
library(DBI)

fn <- function() {
  con <- dbConnect(RSQLite::SQLite(), dbname = ":memory:")
  dbDisconnect(con)
  1
}

# bad - where is DBI?
packagesOf(globalsOf(fn))
#> [1] "base"

This causes the following type of failure:

library(DBI)
library(future)

fn <- function() {
  # Tries to use `dbConnect()` that future pushes into the global env.
  # DBI package is never loaded!
  con <- dbConnect(RSQLite::SQLite(), dbname = ":memory:")
  dbDisconnect(con)
  1
}

fn2 <- function() {
  # Forcibly use the `dbConnect()` function found in `DBI::`
  con <- DBI::dbConnect(RSQLite::SQLite(), dbname = ":memory:")
  DBI::dbDisconnect(con)
  1
}

fn3 <- function() {
  library(DBI)
  # Tries to use `dbConnect()` that future pushes into the global env.
  # That still shadows the one loaded by DBI
  con <- dbConnect(RSQLite::SQLite(), dbname = ":memory:")
  dbDisconnect(con)
  1
}

# Failure, because DBI isn't loaded, we can't register methods for it
plan(multisession, workers = 2)
fut <- future(fn(), seed = 123)
value(fut)
#> Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘dbConnect’ for signature ‘"SQLiteDriver"’
plan(sequential)

# Works because `DBI::` loads DBI, and because we explicitly use
# the dbConnect() from `DBI::`, not the global env one
plan(multisession, workers = 2)
fut <- future(fn2(), seed = 123)
value(fut)
#> [1] 1
plan(sequential)

# DBI gets loaded by `library(DBI)`, but the `dbConnect()` that is
# present in the global env (put there by future) overshadows the
# DBI::dbConnect() function
plan(multisession, workers = 2)
fut <- future(fn3(), seed = 123)
value(fut)
#> Warning: package ‘DBI’ was built under R version 4.0.2
#> 
#> Attaching package: ‘DBI’
#> The following objects are masked _by_ ‘.GlobalEnv’:
#> 
#>     dbConnect, dbDisconnect
#> Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘dbConnect’ for signature ‘"SQLiteDriver"’
plan(sequential)

Created on 2021-02-01 by the reprex package (v0.3.0.9001)

packagesOf() cannot identify where S4 standard generic functions come from. Here is an example of why, and a guess on what you could look for instead?

fn <- vctrs::vec_slice
fn_s4 <- DBI::dbConnect

# this is what `packagesOf.Globals()` does
environmentName(environment(fn))
#> [1] "vctrs"

# doesn't work for S4 functions!
environmentName(environment(fn_s4))
#> [1] ""

# It is a "standardGeneric" function
class(fn_s4)
#> [1] "standardGeneric"
#> attr(,"package")
#> [1] "methods"

# These have a "package" attribute
attr(fn_s4, "package", exact = TRUE)
#> [1] "DBI"

# And a "generic" attribute, which also has a "package" attribute on it
attr(fn_s4, "generic", exact = TRUE)
#> [1] "dbConnect"
#> attr(,"package")
#> [1] "DBI"

Metadata

Metadata

Assignees

No one assigned

    Labels

    S4Related to the S4 class system in R

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions