Skip to content

bug [methods]: double execution of `insertSource` within the same session does not work

3 messages · Demetrio Rodriguez T., Michael Lawrence

#
Hello everyone,


I hope this reaches someone at all. It's my first bug report to the R-core,
and, apparently, bugzilla is locked from new reports for now.

I was using `methods::insertSource` to debug and successfully fix another
package, until it suddenly stopped working. I figured out, that it is
because I am using it on the same function multiple times within one
session. It also produces warnings even during the first call, but somehow
still works. Below I provide a reproducible example:

SETUP:
```bash
demetrio at laptop:[folder_structure]/Bugreports/methods_insertSource$ ls -a
.  ..  gmapsdistance_fix.R  methods_insertSource.R
```

file `gmapsdistance_fix.R`
```R
gmapsdistance = function(param) {
    print('I am a bug report, my params are:')
    print(param)
}
```


file `methods_insertSource.R`
```R
library(gmapsdistance)  # works with any package

methods::insertSource('gmapsdistance_fix.R',
    package = 'gmapsdistance',
    functions = 'gmapsdistance',
    force = T
)
buggy = gmapsdistance('Works?')
```


TO REPRODUCE:
in that directory `R --vanilla` then
```R
Modified functions inserted through trace(): gmapsdistance
[1] "I am a bug report, my params are:"
[1] "Works?"
Warning message:
In methods::insertSource("gmapsdistance_fix.R", package = "gmapsdistance",
:
  cannot insert these (not found in source): "gmapsdistance"
# Works, but gives the warning that it does not

# repeat:
Error in assign(this, thisObj, envir = envwhere) :
  cannot change value of locked binding for 'gmapsdistance'
In addition: Warning message:
In methods::insertSource("gmapsdistance_fix.R", package = "gmapsdistance",
:
  cannot insert these (not found in source): "gmapsdistance"

# does not work, and gets even more confusing: so is it that the object is
not find, or is it about a locked object?
```

I think it's a bug.

--------------------- BUG REPORT END ------------------------


I looked into it a bit myself, in case you are interested:

```R
# lines 20-22
    if (is(source, "environment"))
        env <- source
    else env <- evalSource(source, package, FALSE)
    # We're in the second case I guess

# Browse[2]> env
# Object of class "sourceEnvironment"
# Source environment created  2017-12-01 05:19:51
# For package "gmapsdistance"
# From source file "gmapsdistancefix.R"


# later, before line 52:
x = env
Browse[2]> package
[1] "gmapsdistance"

# evaluate 52
packageSlot(env) <- package

# objects x and env are still identical
# Browse[2]> class(env)
# [1] "sourceEnvironment"
# attr(,"package")
# [1] "methods"
# Browse[2]> class(x)
# [1] "sourceEnvironment"
# attr(,"package")
# [1] "methods"

# Browse[2]> env
# Object of class "sourceEnvironment"
# Source environment created  2017-12-01 05:19:51
# For package "gmapsdistance"
# From source file "gmapsdistancefix.R"
# Browse[2]> x
# Object of class "sourceEnvironment"
# Source environment created  2017-12-01 05:19:51
# For package "gmapsdistance"
# From source file "gmapsdistancefix.R"

# so:
Browse[2]>  names(env)
NULL

# which is why 53-60 do not work:
allObjects <- names(env)
if (!missing(functions)) {
    notThere <- is.na(match(functions, allObjects))
    if (any(notThere)) {
        warning(gettextf("cannot insert these (not found in source): %s",
            paste("\"", functions[notThere], "\"", sep = "",
                collapse = ", ")), domain = NA)
    }
}
```

Looking forward to your feedback!

Cheers,
Demetrio
#
Thanks, I will fix this.

On Mon, Jan 29, 2018 at 8:06 AM, Demetrio Rodriguez T. <
demetrio.rodriguez.t at gmail.com> wrote:

            

  
  
2 days later
#
The issue should be resolved in R-devel. It was actually deeper and more
important than this obscure insertSource() function. names() was not doing
the right thing on S4 objects derived from "environment".

On Mon, Jan 29, 2018 at 11:02 AM, Michael Lawrence <michafla at gene.com>
wrote: