class: center, middle, inverse, title-slide #
- Packages Development ## A Short Introduction ### Mickaƫl Canouil,
Ph.D.
(
mickael.canouil.fr
) ###
Inserm U1283 / CNRS UMR8199 / Institut Pasteur de Lille / UniversitƩ de Lille
### DerniĆØre mise Ć jour : 24-08-2021 --- class: part-slide # Helper<br><i class="fab fa-r-project"></i> Packages --- # `devtools`: To Develop <i class="fab fa-r-project"></i> Packages [https://devtools.r-lib.org/](https://devtools.r-lib.org/) ```r # Install devtools from CRAN install.packages("devtools") # Or the development version from GitHub: # install.packages("devtools") devtools::install_github("r-lib/devtools") ``` ```r library("devtools") ``` --- # `roxygen2`: To Document the Code [https://roxygen2.r-lib.org/](https://roxygen2.r-lib.org/) ```r # Install devtools from CRAN install.packages("roxygen2") # Or the development version from GitHub: # install.packages("devtools") devtools::install_github("r-lib/roxygen2") ``` ```r library("roxygen2") ``` --- # `roxygen2`: To Document the Code ```r #' Add to message on top of a call to `print()` #' #' This function print a greeting message on top of #' the regular call to `print()`. #' #' @inheritParams print #' @param msg A string to print as a greeting message #' @export #' @examples #' print_msg(1, "The value is: ") print_msg <- function(x, msg) { message(msg) x } ``` --- # `usethis`: To Setup the Environment [https://usethis.r-lib.org/](https://usethis.r-lib.org/) ```r # Install devtools from CRAN install.packages("usethis") # Or the development version from GitHub: # install.packages("devtools") devtools::install_github("r-lib/usethis") ``` ```r library("usethis") ``` --- # `usethis`: To Setup the Environment Global options for `usethis`: ```r options( usethis.full_name = "Firstname Lastname", usethis.protocol = "ssh", usethis.description = list( `Authors@R` = 'person( given = "Firstname", family = "Lastname", role = c("aut", "cre"), email = "Firstname.Lastname@cnrs.fr", comment = c(ORCID = "0000-0000-0000-0000") )', Version = "0.0.0.9000" ) ) ``` --- # `usethis`: To Setup the Environment Setup Git: ```r use_git_config( user.name = "Firstname Lastname", user.email = "Firstname.Lastname@cnrs.fr" ) # git_sitrep() # To check if Git is configured properly ``` ```bash git config --global user.name 'Firstname Lastname' git config --global user.email 'Firstname.Lastname@cnrs.fr' git config --global --list ``` --- # `usethis`: To Setup the Environment First an access token from GitHub needs to be created: https://github.com/settings/tokens ```r browse_github_token() # open the form in a browser edit_r_environ() # open .Renviron file from your home ``` Edit the `.Renviron` and add your token. ```txt GITHUB_PAT=xloltrglmlm9v0wqb4zgnks86z5uwkqgoat29aar ``` Restart and check if you have access to your token ```r Sys.getenv("GITHUB_PAT") github_token() ``` --- class: part-slide # Let's `usethis` <br>Create an <i class="fab fa-r-project"></i> package --- # `usethis`: A Tidy Package ```r library("usethis") create_tidy_package() function (path, name = "RStudio") { path <- create_package(path, rstudio = TRUE, open = FALSE) old_project <- proj_set(path) on.exit(proj_set(old_project), add = TRUE) use_roxygen_md() use_testthat() use_gpl3_license(name) use_tidy_description() use_readme_rmd(open = FALSE) use_lifecycle_badge("experimental") use_cran_badge() use_cran_comments(open = FALSE) use_tidy_github() ui_todo("In the new package, remember to do:") ui_todo("{ui_code('use_git()')}") ui_todo("{ui_code('use_github()')}") ui_todo("{ui_code('use_tidy_ci()')}") ui_todo("{ui_code('use_pkgdown()')}") ui_todo("{ui_code('use_pkgdown_travis()')}") proj_activate(path) } ``` --- # `usethis`: A Tidy Package Create the package skeleton. ```r path <- create_package("mypackage", rstudio = TRUE, open = FALSE) ``` ```txt ā Creating './' ā Creating 'R/' ā Writing 'DESCRIPTION' Package: mypackage 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] (<https://orcid.org/YOUR-ORCID-ID>) Description: What the package does (one paragraph). License: What license it uses Encoding: UTF-8 LazyData: true ā Writing 'NAMESPACE' ā Writing 'mypackage.Rproj' ā Adding '.Rproj.user' to '.gitignore' ā Adding '^mypackage\\.Rproj$', '^\\.Rproj\\.user$' to '.Rbuildignore' ``` --- # `usethis`: A Tidy Package Setup Rstudio project (`rstudio = TRUE` from `create_package()`). ```r old_project <- proj_set(path) on.exit(proj_set(old_project), add = TRUE) ``` --- # `usethis`: A Tidy Package Setup roxygen2 as tool to render documentation. ```r use_roxygen_md() ``` ```txt ā Setting Roxygen field in DESCRIPTION to 'list(markdown = TRUE)' ā Setting RoxygenNote field in DESCRIPTION to '7.0.2' ā Run `devtools::document()` ``` --- # `usethis`: A Tidy Package Setup unit test directory with default scripts. ```r use_testthat() ``` ```txt ā Adding 'testthat' to Suggests field in DESCRIPTION ā Creating 'tests/testthat/' ā Writing 'tests/testthat.R' ā Call `use_test()` to initialize a basic test file and open it for editing. ``` --- # `usethis`: A Tidy Package Setup licence (several available). ```r use_gpl3_license("mypackage") ``` ```txt ā Setting License field in DESCRIPTION to 'GPL-3 + file LICENSE' ā Writing 'LICENSE.md' ā Adding '^LICENSE\\.md$' to '.Rbuildignore' ā Writing 'LICENSE' ``` --- # `usethis`: A Tidy Package Format/clean `DESCRIPTION` file. ```r use_tidy_description() ``` Add version for packages listed in `DESCRIPTION` (*e.g.*, `Imports` field). ```r use_tidy_versions() ``` --- # `usethis`: A Tidy Package Add an Rmarkdown script to render the `README.md` file. ```r use_readme_rmd(open = FALSE) ``` ```txt ā Writing 'README.Rmd' ā Adding '^README\\.Rmd$' to '.Rbuildignore' ``` --- # `usethis`: A Tidy Package Add a development status badge following tidyverse convention. ```r use_lifecycle_badge("experimental") ``` ```txt ā Adding Lifecycle: experimental badge to 'README.Rmd' ā Re-knit 'README.Rmd ``` --- # `usethis`: A Tidy Package Add a CRAN badge displaying CRAN version. ```r use_cran_badge() ``` ```txt ā Adding CRAN status badge to 'README.Rmd' ā Re-knit 'README.Rmd' ``` --- # `usethis`: A Tidy Package Add a markdown file (used for the release to CRAN). ```r use_cran_comments(open = FALSE) ``` ```txt ā Writing 'cran-comments.md' ā Adding '^cran-comments\\.md$' to '.Rbuildignore' ``` --- # `usethis`: A Tidy Package Add default files to use in GitHub (*Check them*). **Note:** `github/SUPPORT.md` must be edited to fix GitHub repository at line 23. ```r use_tidy_github() ``` ```txt ā Creating '.github/' ā Adding '^\\.github$' to '.Rbuildignore' ā Writing '.github/CONTRIBUTING.md' ā Creating '.github/ISSUE_TEMPLATE/' ā Adding '^\\.github/ISSUE_TEMPLATE$' to '.Rbuildignore' ā Writing '.github/ISSUE_TEMPLATE/issue_template.md' ā Writing '.github/SUPPORT.md' ā Writing '.github/CODE_OF_CONDUCT.md' ā Don't forget to describe the code of conduct in your README: Please note that the 'mypackage' project is released with a [Contributor Code of Conduct](.github/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. [Copied to clipboard] ``` --- ## `usethis`: A Tidy Package ```r ui_todo("In the new package, remember to do:") ui_todo("{ui_code('use_git()')}") ui_todo("{ui_code('use_github()')}") ui_todo("{ui_code('use_tidy_ci()')}") ui_todo("{ui_code('use_pkgdown()')}") ui_todo("{ui_code('use_pkgdown_travis()')}") ``` ```txt ā In the new package, remember to do: ā `use_git()` ā `use_github()` ā `use_tidy_ci()` ā `use_pkgdown()` ā `use_pkgdown_travis()` ``` --- # `usethis`: A Tidy Package Open the newly created package as an Rstudio project. ```r proj_activate(path) ``` ```txt ā Opening 'C:/mypackage' in new RStudio session ``` --- # `usethis`: A Tidy Package Setup the package to use Git. ```r use_git() ``` ```txt ā Initialising Git repo ā Adding '.Rhistory', '.RData' to '.gitignore' There are 11 uncommitted files: * '.github/' * '.gitignore' * '.Rbuildignore' * 'cran-comments.md' * 'DESCRIPTION' * 'LICENSE' * 'LICENSE.md' * 'mypackage.Rproj' * 'NAMESPACE' * 'README.Rmd' * 'tests/' Is it ok to commit them? 1: I agree 2: Not now 3: No way ``` --- # `usethis`: A Tidy Package Setup a repository on GitHub for the package. ```r use_github() ``` ```txt ā Setting active project to 'C:/mypackage' ā Checking that current branch is 'master' ā Check title and description Name: mypackage Description: What the Package Does (One Line, Title Case) Are title and description ok? 1: Negative 2: Absolutely not 3: Yup ``` --- # `usethis`: A Tidy Package Setup continuous integration using travis-CI and code coverage. ```r use_tidy_ci() ``` ```txt ā Writing '.travis.yml' ā Adding '^\\.travis\\.yml$' to '.Rbuildignore' ā Writing 'codecov.yml' ā Adding '^codecov\\.yml$' to '.Rbuildignore' ā Adding 'R' to Depends field in DESCRIPTION ā Adding 'covr' to Suggests field in DESCRIPTION ā Adding '^\\.covrignore$' to '.Rbuildignore' ā Adding 'R/deprec-*.R', 'R/compat-*.R' to '.covrignore' ā Adding Travis build status badge to 'README.Rmd' ā Re-knit 'README.Rmd' ā Adding Codecov test coverage badge to 'README.Rmd' ā Re-knit 'README.Rmd' ā Replacing release environment in 'cran-comments.md' ā Turn on travis for your repo at https://travis-ci.org/profile/user ``` --- # `usethis`: A Tidy Package Add utils for tidy-evaluation (*e.g.*, `.data` pronoun). ```r use_tidy_eval() ``` ```txt ā Adding 'roxygen2' to Suggests field in DESCRIPTION ā Adding 'rlang' to Imports field in DESCRIPTION ā Writing 'R/utils-tidy-eval.R' ā Run `devtools::document()` ``` --- # `usethis`: A Tidy Package Add pipe (`%>%`). ```r use_pipe() ``` ```txt ā Adding 'magrittr' to Imports field in DESCRIPTION ā Writing 'R/utils-pipe.R' ā Run `devtools::document()` to update 'NAMESPACE' ``` --- # `usethis`: A Tidy Package Add the package `stats` to the package. ```r use_package("stats") ``` ```txt ā Adding 'stats' to Imports field in DESCRIPTION ā Refer to functions with `stats::fun()` ``` --- class: part-slide # `devtools`<br>Build / Check / Test --- # `devtools`: To Build / Check / Test Frequent development tasks: * `load_all()` simulates installing and reloading your package, loading <i class="fab fa-r-project"></i> code in `R/`, compiled shared objects in `src/` and data files in `data/`. * `document()` updates generated documentation in `man/`, file collation and `NAMESPACE`. * `test()` reloads your code with `load_all()`, then runs all `testthat` tests. * `test_coverage()` runs test coverage on your package with [covr](https://github.com/r-lib/covr). --- # `devtools`: Build / Check / Test Building and installing: * `install()` reinstalls the package, detaches the currently loaded version then reloads the new version with `library()`. * `build()` builds a package file from package sources. You can use it to build a binary version of your package. --- # `devtools`: Build / Check / Test Check and release: * `check()` updates the documentation, then builds and checks the package locally. `check_win()` checks a package using [win-builder](http://win-builder.r-project.org/), and `check_rhub()` checks a package using [r-hub](http://log.r-hub.io/). This allows you to easily check your package on all systems CRAN uses before submission. * `release()` makes sure everything is ok with your package (including asking you a number of questions), then builds and uploads to CRAN. --- # Render the `README.md` Before trying to render the `README.Rmd`, set the chunk with `library(mypackage)` to `eval = FALSE`. ```r rmarkdown::render('README.Rmd', encoding = 'UTF-8') ``` --- # Update the Code Documentation ```r document() ``` ```txt Updating mypackage documentation Writing NAMESPACE Loading mypackage Writing NAMESPACE Writing pipe.Rd Writing tidyeval.Rd ``` --- # Check the Package ```r check() ``` ```txt -- R CMD check results ---------------------------------------------------------- mypackage 0.0.0.9000 ---- Duration: 19.6s > checking tests ... See below... -- Test failures ---------------------------------------------------------------------------- testthat ---- > library(testthat) > library(mypackage) > > test_check("mypackage") Error: No tests found for mypackage Execution halted 1 error x | 0 warnings ā | 0 notes ā ``` --- class: part-slide # <img src = "data:image/png;base64,#https://avatars1.githubusercontent.com/u/8896044" height = "150px" id = "picture" /> .center[ <a href = "https://mickael.canouil.fr" target = "_blank"><i class = "fas fa-home"></i> mickael.canouil.fr</a> .column[ <a href = "https://www.linkedin.com/in/mickael-canouil/" target = "_blank"><i class = "fab fa-linkedin"></i> mickael-canouil</a> ] .column[ <a href = "https://github.com/mcanouil/" target = "_blank"><i class = "fab fa-github"></i> mcanouil</a> ] .column[ <a href = "https://twitter.com/mickaelcanouil/" target = "_blank"><i class = "fab fa-twitter"></i> @mickaelcanouil</a> ] ]