Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

load/remove user-defined unit on package load/unload: best practise?

In a package I am developing I need to define a new unit: flight level (FL) equivalent to 100 ft.

The units package provides the following possibility:

units::install_conversion_constant("FL", "ft", 100)

In order to make package test (devtools::test()) and package check (devtools::test()) both work for my unit tests using this user-defined unit, I discovered that I need to register it in the package load phase.

Here is what I did:

In zzz.R (a new files as per "When you do need side-effects" section):

# register flight levels (FL) as a unit when loading this package
.onLoad <- function(libname, pkgname) {
  # install user-define unit for flight level
  units::install_conversion_constant("FL", "ft", 100)

  invisible()
}

# register flight levels (FL) as a unit when loading this package
.onUnload <- function(libname, pkgname) {
  # uninstall user-define unit for flight level
  units::remove_symbolic_unit("FL")

  invisible()
}

Failing to do that and putting the unit registration code in some R/unit-conversion.R file makes devtools::test() succeed but devtools::check() fail.

Is the solution above the correct approach to register (and remove [should this be done too?]) a new unit in a package?

like image 368
espinielli Avatar asked Aug 06 '18 14:08

espinielli


1 Answers

This is almost absolutely the place to do it for your package. I say Almost because there is an exception to every rule. Read the section below for some more detail and the good practice reccomendation from the base R manual

https://stat.ethz.ch/R-manual/R-devel/library/base/html/ns-hooks.html

Good practice Loading a namespace should where possible be silent, with startup messages given by .onAttach. These messages (and any essential ones from .onLoad) should use packageStartupMessage so they can be silenced where they would be a distraction.

There should be no calls to library nor require in these hooks. The way for a package to load other packages is via the Depends field in the ‘DESCRIPTION’ file: this ensures that the dependence is documented and packages are loaded in the correct order. Loading a namespace should not change the search path, so rather than attach a package, dependence of a namespace on another package should be achieved by (selectively) importing from the other package's namespace.

Uses of library with argument help to display basic information about the package should use format on the computed package information object and pass this to packageStartupMessage.

There should be no calls to installed.packages in startup code: it is potentially very slow and may fail in versions of R before 2.14.2 if package installation is going on in parallel. See its help page for alternatives.

Compiled code should be loaded (e.g., via library.dynam) in .onLoad or a useDynLib directive in the ‘NAMESPACE’ file, and not in .onAttach. Similarly, compiled code should not be unloaded (e.g., via library.dynam.unload) in .Last.lib nor .onDetach, only in .onUnload.

like image 69
Adam Wheeler Avatar answered Nov 08 '22 19:11

Adam Wheeler