How is system.file() supposed to work when a package is loaded using load_all() or devtools::test()?

During development packages are often loaded directly from source using devtools::load_all().
I think that when a package is tested using devtools::test it is loaded directly from source as well.

The base::system.file() function will not work when a package is loaded from source using load_all because the "/inst" folder still exists. When a package is installed the files in "inst" are copied up one level in the directory hierarchy.

There is an internal function in pkgload called pkgload:::shim_system.file() that is supposed to intercept calls to base::system.file(), so that it behaves well with packages loaded by devtools. It is made available when a package is loaded with load_all().

Sometimes this works well but I often find that this does not work. It seems that calls to system.file are not being correctly intercepted and tests are failing because of the missing '/inst' in file paths.

Do others experience this issue? Is there a way to debug the calls to system.file to understand why the shim is not working?

Can you give a concrete example of when this isn't doing what you expect? Preferably a package on GitHub?

the pkgload shims will only work for unqualified calls from the package loaded with pkgload, e.g. if you explicitly call base::system.file() from your package code that will still use the base version.

Also if the system.file() call comes from a function in another package the shim also will not be used. It will only work from system.file() calls from the package being loaded.

1 Like

Ah this might be the reason for my misunderstanding.

I'm using the Eunomia package (GitHub - OHDSI/Eunomia: A standard CDM dataset for testing and demonstration purposes.). When I run devtools::test() I get a failed test because Eunomia is calling a function in a different package (SqlRender) which is using system.file()

When the same tests run as part of github actions CI everything passes. I used the debugger to get to the offending system.file call and if I add "inst" to the path it will find the file.

I think what is happening is that Eunomia calls a function in SqlRender which uses system.file to get the path for a file in the Eunomia package. Since the call is coming from SqlRender the shim is not used but since Eunomia is loaded from source and the files are in the "inst" folder SqlRender cannot find them.

Do I have that right? Is there any way around this?

One way would be to create a symlink in your package from inst/sql to sql, then the file should exist in both cases. You will need to make sure the symlink is not included in the built package.