Skip to content

Commit

Permalink
Reload dependent modules (#195)
Browse files Browse the repository at this point in the history
Naïve implementation of dependency reloading (fixes #39, #165)
  • Loading branch information
klmr authored May 21, 2021
1 parent 398cc27 commit 3c7e2ad
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# box (development version)

* Fix: Reload dependent modules (#39, #165, #195)
* Fix: Don’t crash in the presence of nested, expanded functions inside modules
(#203)

Expand Down
5 changes: 5 additions & 0 deletions R/unload.r
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ reload = function (mod) {
call_hook(mod_ns, '.on_unload', mod_ns)
deregister_mod(info)

for (import_ns in namespace_info(mod_ns, 'imports')) {
call_hook(import_ns, '.on_unload', import_ns)
deregister_mod(attr(import_ns, 'info'))
}

on.exit({
warning(sprintf(
'Reloading module %s failed, attempting to restore the old instance.',
Expand Down
44 changes: 44 additions & 0 deletions tests/testthat/test-reload.r
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ unload_all = function () {
rm(list = ls(modenv), envir = modenv)
}

tempfile_dir = function (...) {
file = tempfile()
dir.create(file)
file
}

create_nested_test_module = function (dir) {
mod = file.path(dir, 'mod', 'a')
dir.create(mod, recursive = TRUE)
writeLines("#' @export\nbox::use(./sub)", file.path(mod, '__init__.r'))
writeLines("#' @export\nvalue = 1L", file.path(mod, 'sub.r'))
}

edit_nested_test_module = function (dir) {
mod = file.path(dir, 'mod', 'a')
writeLines("#' @export\nvalue = 2L", file.path(mod, 'sub.r'))
}

test_that('module can be reloaded', {
# Required since other tests have side-effects.
# Tear-down would be helpful here, but not supported by testthat.
Expand All @@ -32,3 +50,29 @@ test_that('reload checks its arguments', {
box::use(mod/a)
expect_error(box::reload((a)))
})

test_that('reload includes submodules', {
dir = tempfile_dir()
on.exit(unlink(dir, recursive = TRUE))

old_path = options(box.path = dir)
on.exit(options(old_path), add = TRUE)

create_nested_test_module(dir)

box::use(mod/a)

expect_equal(a$sub$value, 1L)

edit_nested_test_module(dir)

box::reload(a)

expect_equal(a$sub$value, 2L)

# To do:
# * modules with compiled source,
# * tricky packages loaded as modules, e.g. packages that call
# system.file(), and alike, and
# * modules with S4 classes/object,
})

0 comments on commit 3c7e2ad

Please sign in to comment.