Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
DavisVaughan opened this issue Feb 1, 2021 · 1 comment
Open
Labels
S4 Related to the S4 class system in R

Comments

@DavisVaughan
Copy link
Contributor

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"
@DavisVaughan
Copy link
Contributor Author

Once packagesOf() is fixed, it would also be good to ensure that future::getGlobalsAndPackages() does indeed remove dbConnect() from the list of $globals that it returns, since it will instead come from library-ing the $packages that it finds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S4 Related to the S4 class system in R
Projects
None yet
Development

No branches or pull requests

2 participants