<- c(
pkg_list "codetools", "checkmate"
)
lapply(
pkg_list, function(pkg) {
if(! pkg %in% .packages(all.available=TRUE))
install.packages(pkg)
} )
[[1]]
NULL
[[2]]
NULL
Ghislain Durif
LBMC – CNRS
February 28, 2023
(sources)
pkg_list <- c(
"codetools", "checkmate"
)
lapply(
pkg_list,
function(pkg) {
if(! pkg %in% .packages(all.available=TRUE))
install.packages(pkg)
}
)
[[1]]
NULL
[[2]]
NULL
Several R packages to help you develop R packages.
my_package
├── .Rbuildignore
├── _pkgdown.yml
├── DESCRIPTION
├── LICENSE.md
├── LICENSE.note
├── NAMESPACE
├── README.md
├── README.Rmd
├── man
│ └── my_function.Rd
├── R
│ └── my_function.R
├── tests
│ ├── testthat
│ │ └── test-my_function.R
│ └── testthat.R
└── vignettes
└── getting-started-with-my-function.Rmd
devtools
usethis
# Create a new package -------------------------------------------------
path <- file.path(tempdir(), "mypkg")
usethis::create_package(path)
#> ✔ Creating '/tmp/Rtmp4VMzwK/mypkg/'
#> ✔ Setting active project to '/private/tmp/Rtmp4VMzwK/mypkg'
#> ✔ Creating 'R/'
#> ✔ Writing 'DESCRIPTION'
#> Package: mypkg
#> Title: What the Package Does (One Line, Title Case)
#> Version: 0.0.0.9000
#> Authors@R (parsed):
#> * First Last <first.last@example.com> [aut, cre] (YOUR-ORCID-ID)
#> Description: What the package does (one paragraph).
#> License: `use_mit_license()`, `use_gpl3_license()` or friends to pick a
#> license
#> Encoding: UTF-8
#> Roxygen: list(markdown = TRUE)
#> RoxygenNote: 7.2.0
#> ✔ Writing 'NAMESPACE'
#> ✔ Setting active project to '<no active project>'
# only needed since this session isn't interactive
usethis::proj_activate(path)
#> ✔ Setting active project to '/private/tmp/Rtmp4VMzwK/mypkg'
#> ✔ Changing working directory to '/tmp/Rtmp4VMzwK/mypkg/'
# Modify the description ----------------------------------------------
usethis::use_mit_license("My Name")
#> ✔ Setting License field in DESCRIPTION to 'AGPL (>= 3)'
#> ✔ Writing 'LICENSE.md'
#> ✔ Adding '^LICENSE\\.md$' to '.Rbuildignore'
usethis::use_package("ggplot2", "Suggests")
#> ✔ Adding 'ggplot2' to Suggests field in DESCRIPTION
#> • Use `requireNamespace("ggplot2", quietly = TRUE)` to test if package is installed
#> • Then directly refer to functions with `ggplot2::fun()`
# Set up other files -------------------------------------------------
usethis::use_readme_md()
#> ✔ Writing 'README.md'
#> • Update 'README.md' to include installation instructions.
usethis::use_news_md()
#> ✔ Writing 'NEWS.md'
usethis::use_test("my-test")
#> ✔ Adding 'testthat' to Suggests field in DESCRIPTION
#> ✔ Setting Config/testthat/edition field in DESCRIPTION to '3'
#> ✔ Creating 'tests/testthat/'
#> ✔ Writing 'tests/testthat.R'
#> ✔ Writing 'tests/testthat/test-my-test.R'
#> • Edit 'tests/testthat/test-my-test.R'
x <- 1
y <- 2
usethis::use_data(x, y)
#> ✔ Adding 'R' to Depends field in DESCRIPTION
#> ✔ Creating 'data/'
#> ✔ Setting LazyData to 'true' in 'DESCRIPTION'
#> ✔ Saving 'x', 'y' to 'data/x.rda', 'data/y.rda'
#> • Document your data (see 'https://r-pkgs.org/data.html')
# Use git ------------------------------------------------------------
usethis::use_git()
#> ✔ Initialising Git repo
#> ✔ Adding '.Rproj.user', '.Rhistory', '.Rdata', '.httr-oauth', '.DS_Store' to '.gitignore'
usethis::use_devtools()
usethis::use_build_ignore("<filename>")
to add files to .Rbuildignore
usethis::use_git_ignore("<filename>")
to add files to .gitignore
usethis::use_github_action()
or usethis::use_gitlab_ci()
to setup a CI (c.f. gitlabr
package below)fusen
“
{fusen}
inflates a Rmarkdown file to magically create a package.”
path <- file.path(getwd(), "examples", "my.fusen.pkg")
fusen::create_fusen(path, template = "full", open = FALSE)
#> ── Creating new directory: /path/to/examples/my.fusen.pkg ──────────────────────────────────────────────────────────────────────────────────────────────────
#> ✔ Creating '/path/to/examples/my.fusen.pkg/'
#> ✔ Setting active project to '/path/to/examples/my.fusen.pkg'
#> ✔ Creating 'R/'
#> ✔ Writing a sentinel file '.here'
#> • Build robust paths within your project via `here::here()`
#> • Learn more at <https://here.r-lib.org>
#> ✔ Setting active project to '<no active project>'
#> ✔ New directory created: /path/to/examples/my.fusen.pkg
#> ── Adding dev/flat_full.Rmd ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
#> File .here already exists in /path/to/examples/my.fusen.pkg
#> ✔ Added /path/to/examples/my.fusen.pkg/dev/flat_full.Rmd, /path/to/examples/my.fusen.pkg/dev/0-dev_history.Rmd
fusen::add_flat_template(path, flat_name = "package")
#> '0-dev_history.Rmd' already exists. It was not overwritten. Set `add_flat_template(overwrite = TRUE)` if you want to do so.
#> File .here already exists in /path/to/examples/my.fusen.pkg
#> • Modify '/path/to/examples/my.fusen.pkg/dev/flat_package.Rmd'
dev/(0-)dev_history.Rmd
: recipedev/flat_<flat_name1>.Rmd
, dev/flat_<flat_name2>.Rmd
, etc.: package contentroxygen2
File R/add.R
:
Automatic generation of man/add.Rd
with devtools::document()
:
% Generated by roxygen2: do not edit by hand
% Please edit documentation in ./<text>
\name{add}
\alias{add}
\title{Add together two numbers}
\usage{
add(x, y)
}
\arguments{
\item{x}{A number.}
\item{y}{A number.}
}
\value{
A number.
}
\description{
Add together two numbers
}
\examples{
add(1, 1)
add(10, 1)
}
testthat
# run once to configure the package meta-data
usethis::use_testthat()
# to create a test file "tests/testthat/test-my_function.R"
usethis::use_test("my_function")
#> ✔ Setting active project to '/home/drg/work/dev/R/funStatTest'
#> ✔ Writing 'tests/testthat/test-my_function.R'
#> • Modify 'tests/testthat/test-my_function.R'
File tests/testthat/test-my_function.R
:
Automatically run during package check (e.g. with devtools::check()
) or specifically with devtools::test()
.
checkmate
assert_xxx()
fails if assertion not mettest_xxx()
returns a the check result as a logical (TRUE
/FALSE
) valueexpect_xxx()
are designed to be used in testthat
unit tests.Error in eval(expr, envir, enclos): Assertion on '"my-choice"' failed: Must be element of set {'choice_1','choice_2'}, but is 'my-choice'.
Standard input check: ::: {.cell}
fact <- function(n, method = "stirling") {
if (length(n) != 1)
stop("Argument 'n' must have length 1")
if (!is.numeric(n))
stop("Argument 'n' must be numeric")
if (is.na(n))
stop("Argument 'n' may not be NA")
if (is.double(n)) {
if (is.nan(n))
stop("Argument 'n' may not be NaN")
if (is.infinite(n))
stop("Argument 'n' must be finite")
if (abs(n - round(n, 0)) > sqrt(.Machine$double.eps))
stop("Argument 'n' must be an integerish value")
n <- as.integer(n)
}
if (n < 0)
stop("Argument 'n' must be >= 0")
if (length(method) != 1)
stop("Argument 'method' must have length 1")
if (!is.character(method) || !method %in% c("stirling", "factorial"))
stop("Argument 'method' must be either 'stirling' or 'factorial'")
if (method == "factorial")
factorial(n)
else
sqrt(2 * pi * n) * (n / exp(1))^n
}
:::
checkmate
-based input check: ::: {.cell}
fact <- function(n, method = "stirling") {
assertCount(n)
assertChoice(method, c("stirling", "factorial"))
if (method == "factorial")
factorial(n)
else
sqrt(2 * pi * n) * (n / exp(1))^n
}
:::
pkgdown
Config file: _pkgdown.yml
(see the https://pkgdown.r-lib.org/articles/customise.html)
README.md
-> home page index.html
man/*.Rd
-> “reference” pagesNEWS.md
-> “News” pagesDESCRIPTION
metadata file -> home page side bar with links and descriptioncovr
: Test Coverage for Packagesgitlabr
: Access to the ‘Gitlab’ APISetup a Gitlab CI to check the package, check the test coverage and deploy a pkgdown
website as Gitlab pages:
lintr
: A Linter for R Codewithr
: Run Code With Temporarily Modified Global State