ExampleRPackage package README.

What you will need for this lesson is:

Configuring your machine

Instructions on how to configure a machine are given here

These steps require some knowledge of working with your computer, network access, disk space, and admin rights. We strongly advise you take the steps in this section before class. We also strongly advise taking the trouble to run these steps. Having full control of a package-enabled R environment is very powerful. Please reach out for help if you are stuck on steps.

Once you have your machine configured start up R and install the packages we will be using.

A word of warning

There are many systems and tutorials that sit on top of higher order R tools. These can be useful, but, one must remember in R "Writing R Extensions" is the primary source for how to develop R packges.

Packages we assume you have installed

We assume your machine has a current working R, command-shell (bash / zsh), and text editor (emacs, vim, or other).

Start R and run the following.

install.packages(c(
   "tinytest",   # for running tests
   "roxygen2",   # to generate manuals from comments
   "knitr",      # to generate vignettes from markdown
   "rmarkdown",  # to convert markdown formats, may not need this
   "wrapr"       # example for argument list checking
   ))

The file structure of this project

DESCRIPTION    # the main project control file

R              # project source code directory
 /example_function.R  # our example function
 /package_help.R      # package documentation

README.Rmd     # package documentation source
README.md      # package documentation, produced from README.Rmd

inst           # installed items distributed with package
    /tinytest  # package test directory
    /tinytest/test_ExampleRPackage.R  # the one test we have now

vignettes      # where we place longer documents
         /Example_Vignette.Rmd  # Example markdown document

tests             # test trigger, do not edit
     /tinytest.R  # test trigger, do not edit

.Rbuildignore  # file that tells the builder what files to ignore

.gitignore     # file that tells version control what files to skip

NAMESPACE      # project imports/exports, produced by roxygen2

man            # roxygen2 generated documentation
   /ExampleRPackage.Rd   # generated package documentation
   /example_function.Rd  # generated function documentation

ExampleRPackage.Rproj   # (optional) config file for RStudio

How to copy this project

From GitHub

Point browser to https://github.com/WinVector/ExampleRPackage and press "Fork" in the upper right portion of the page.

Copying the project at the command line (base/zsh for Linux, MacOS, or Windows with Windows Subsystem for Linux)

From a bash/zsh command line:

# get a copy of the repository
git clone https://github.com/WinVector/ExampleRPackage.git

# remove the .git directory to sever it from the original repository
cd ExampleRPackage
rm -rf .git

# start up a new git repository
git init .
git add -A .
git commit -m"example package"

Then associate the package with your own repository by creating an new empty repository on GitHub and following their "preexisting project" instructions (adding a remote).

Procedures for working with packages.

For all of these steps we are assuming your current directory is the top-level of the package you are working with. This can be accomplished with the setwd() command. Alternately one can use an RStudio project, which largely keeps track of the working directory.

Build Package

We will run this with our working directory inside our package (please see getwd()/setwd() for how to navigate between directories in R). This will produce the file ExampleRPackage_0.1.0.tar.gz.

library(wrapr)

# assumes our current directory is our package
# see setwd()/getwd() for how to change directories
rebuild_current_package_and_attach <- function(
   ...,  # not used, force later arguments to bind by name
   package_dir = getwd(),  # default to package is current directory.
   lib = .libPaths()[[1]]  # where to attach package
   ) {
   wrapr::stop_if_dot_args(substitute(list(...)), "rebuild_current_package")
   start_time <- date()
   message(paste("rebuild_current_package working in directory", package_dir))
   message(paste("rebuild_current_package working in lib", lib))
   # get package name from current directory
   pkg_name <- tail(strsplit(package_dir, .Platform$file.sep)[[1]], n = 1)
   message(paste("rebuild_current_package working on package", pkg_name))
   # get into a clean state with no package installed/attached
   detach_str <- paste0('package:', pkg_name)
   res <- tryCatch(do.call(detach, list(detach_str)), error = function(e) e)
   if(pkg_name %in% rownames(installed.packages())) {
      remove.packages(pkg_name, lib = lib)
   }
   # regenerate man/.Rd files from roxygen comments
   res_text <- capture.output(suppressMessages(roxygen2::roxygenize(package.dir = package_dir)))
   # rebuild a source distribution of package
   res <- system(paste("R CMD build", package_dir), 
                 intern = TRUE)
   # find the tar name
   matches <- res[grepl(pkg_name, res)]
   pkg_pattern <- paste0(pkg_name, '[_.0-9]+', '.tar.gz')
   matches <- matches[grepl(pkg_pattern, matches)]
   if(length(matches) != 1) {
      stop("having trouble finding package tar name from R CMD build output")
   }
   str_span <- regexpr(pkg_pattern, matches)
   tar_name <- substr(matches, str_span, str_span + attr(str_span, 'match.length') - 1)
   # install the package from the source distribution
   res_text <- capture.output(install.packages(tar_name, repos = NULL, verbose = FALSE, quiet = TRUE))
   # attach package for use
   res_text <- capture.output(library(pkg_name, character.only = TRUE))
   end_time <- date()
   return(list(
      pkg_name = pkg_name,
      tar_name = tar_name,
      package_dir = package_dir,
      package_dir = package_dir,
      lib = lib,
      start_time = start_time,
      end_time = end_time
   ))
}
# re-document, re-build, re-install, and re-attach package
# write only name of package and tar file name into current work-space
(unpack[pkg_name, tar_name] := rebuild_current_package_and_attach())

# rebuild_current_package working in directory /Users/johnmount/Documents/work/ExampleRPackage
# rebuild_current_package working in lib /Users/johnmount/Library/R/4.0/library
# rebuild_current_package working on package ExampleRPackage
# 
# $pkg_name
# [1] "ExampleRPackage"
# 
# $tar_name
# [1] "ExampleRPackage_0.1.0.tar.gz"
# 
# $package_dir
# [1] "/Users/johnmount/Documents/work/ExampleRPackage"
# 
# $package_dir
# [1] "/Users/johnmount/Documents/work/ExampleRPackage"
# 
# $lib
# [1] "/Users/johnmount/Library/R/4.0/library"
# 
# $start_time
# [1] "Fri Nov 27 11:13:31 2020"
# 
# $end_time
# [1] "Fri Nov 27 11:13:35 2020"
# get into state as if last block had been run
library(ExampleRPackage)
pkg_name <- "ExampleRPackage"
tar_name <- "ExampleRPackage_0.1.0.tar.gz"
ls()

print(pkg_name)

print(tar_name)

Probably want to restart R at this point and re-attach the package with library(ExampleRPackage).

Build README.md from README.Rmd

knitr::knit("README.Rmd")

Some time after rebuilding README.md you may want to rebuild the package again to make sure the new copy is included in the package tar.

Run tests

This package is already setup to use tinytest. Existing packages can be configured to work with tinytest by running tinytest::setup_tinytest('.').

# test directory of tests
dir <- system.file('tinytest', 
                   package = 'ExampleRPackage', 
                   mustWork = TRUE)
print(dir)

test_text <- capture.output(tinytest::run_test_dir(
   dir,
   verbose = TRUE,
   color = FALSE))
cat(paste(test_text, collapse = '\n'))

Check package

check_text <- system(paste("R CMD check", tar_name),
       intern = TRUE)
cat(paste(check_text, collapse = '\n'))

Example code

example_function(3)

Sharing packages

Install from file

install.packages(tar_name, repos = NULL)

Install from tar on github

# get this path by copying Github's download link
url <- "https://github.com/WinVector/ExampleRPackage/raw/main/ExampleRPackage_0.1.0.tar.gz"
install.packages(url, repos = NULL)

Install package from github

remotes::install_github("https://github.com/WinVector/ExampleRPackage")

Submitting to CRAN

Submitting to CRAN is a specialized step. First your package must pass all checks and all CRAN rules (most of which are listed in "Writing R Extensions"). It is important to note the following:

For now I am going to leave CRAN submissions as a "to be covered later" topic.



WinVector/ExampleRPackage documentation built on Dec. 31, 2020, 6:33 p.m.