The goal of attachment is to help to deal with package dependencies during package development. It also gives useful tools to install or list missing packages used inside Rscripts or Rmds.
When building a package, we have to add @importFrom
in
our documentation or pkg::fun
in the R code. The most
important is not to forget to add the list of dependencies in the
“Imports” or “Suggests” package lists in the DESCRIPTION file.
Why do you have to repeat twice the same thing ?
And what happens when you remove a dependency for one of your functions
? Do you really want to run a “Find in files” to verify that you do not
need this package anymore ?
Let {attachment} help you ! This reads your NAMESPACE, your functions in R directory and your vignettes, then update the DESCRIPTION file accordingly. Are you ready to be lazy ?
See full documentation realized using {pkgdown} at https://thinkr-open.github.io/attachment/
CRAN version
install.packages("attachment")
Development version
install.packages('attachment', repos = c('https://thinkr-open.r-universe.dev', 'https://cloud.r-project.org'))
What you really want is to fill and update your description file along with the modifications of your documentation. Indeed, only the following function will really be called. Use and abuse during the development of your package !
::att_amend_desc() attachment
{attachment} detects all calls to library(pkg)
,
@importFrom pkg fun
, pkg::fun()
in the
different classical directories of your R package, then list them in the
correct “Imports” or “Suggests” category in the DESCRIPTION file,
according to their position in the package.
If you want to add extra packages like {pkgdown} or {covr} that are not listed in any script in your package, a call for your development packages would be:
::att_amend_desc(extra.suggests = c("pkgdown", "covr"), update.config = TRUE) attachment
Note the update.config = TRUE
parameter that will save
the parameters used in the call of att_amend_desc()
to the
package configuration file: “dev/config_attachment.yaml”.
If you run att_amend_desc()
a second time afterwards,
directly from the console, it will use the last set of parameters
extracted from the configuration file.
Indeed, we recommend to store the complete command line in a
“dev/dev_history.R” file to update and run it when needed. If the
parameters do not change, you can run
attachment::att_amend_desc()
directly in the console,
wherever you are, it will use the configuration file.
If you would like to detect the sources of your installations so that you can add dependencies in the “Remotes” field of your DESCRIPTION file, to mimic your local installation, you will use:
::set_remotes_to_desc() attachment
# Copy example package in a temporary directory
<- tempfile(pattern = "fakepkg")
tmpdir dir.create(tmpdir)
file.copy(system.file("dummypackage",package = "attachment"), tmpdir, recursive = TRUE)
#> [1] TRUE
<- file.path(tmpdir, "dummypackage")
dummypackage # browseURL(dummypackage)
# Fill the DESCRIPTION file automatically
# `inside_rmd` is specifically designed here to allow to run this command line in the "Readme.Rmd" file
<- attachment::att_amend_desc(path = dummypackage, inside_rmd = TRUE, update.config = TRUE)
desc_file #> 'update.config' was set to TRUE, hence, 'use.config' was forced to FALSE
#> Saving attachment parameters to yaml config file
#> Updating dummypackage documentation
#> ────────────────────────────────────────────────────────────────────────────────
#> Changes in roxygen2 7.0.0:
#> * `%` is now escaped automatically in Markdown mode.
#> Please carefully check .Rd files for changes
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Setting `RoxygenNote` to "7.2.2"
#> ℹ Loading dummypackage
#> Writing ']8;;file:///tmp/Rtmp3Dpn4h/fakepkg3538450e5c49/dummypackage/NAMESPACENAMESPACE]8;;'
#> Writing ']8;;file:///tmp/Rtmp3Dpn4h/fakepkg3538450e5c49/dummypackage/NAMESPACENAMESPACE]8;;'
#> ℹ Loading dummypackage
#> Package(s) Rcpp is(are) in category 'LinkingTo'. Check your Description file to be sure it is really what you want.
#>
#> [-] 1 package(s) removed: utils.
#>
#> [+] 2 package(s) added: stats, glue.
# Add Remotes if you have some installed
::set_remotes_to_desc(path.d = desc_file)
attachment#> There are no remote packages installed on your computer to add to description
#> NULL
# Clean state
unlink(tmpdir, recursive = TRUE)
Find packages installed out of CRAN. This helps fill the “Remotes”
field in DESCRIPTION file with set_remotes_to_desc()
.
Behind the scene, it uses find_remotes()
.
# From GitHub
::install_github("ThinkR-open/fusen",
remotesquiet = TRUE, upgrade = "never")
::find_remotes("fusen")
attachment#> $fusen
#> [1] "ThinkR-open/fusen"
To quickly install missing packages from a DESCRIPTION file, use:
::install_from_description()
attachment#> All required packages are installed
To quickly install missing packages needed to compile Rmd files or run R scripts, use:
::att_from_rmds(path = ".") |> attachment::install_if_missing()
attachment
::att_from_rscripts(path = ".") |> attachment::install_if_missing() attachment
Function attachment::create_dependencies_file()
will
create a dependencies.R
file in inst/
directory. This R script contains the procedure to quickly install
missing dependencies:
# Remotes ----
# remotes::install_github("ThinkR-open/fcuk")
# Attachments ----
<- c("covr", "desc", "devtools", "glue", "knitr", "magrittr", "rmarkdown", "stats", "stringr", "testthat", "utils")
to_install for (i in to_install) {
message(paste("looking for ", i))
if (!requireNamespace(i)) {
message(paste(" installing", i))
install.packages(i)
} }
If you write a {bookdown} and want to publish it on Github using
GitHub Actions or GitLab CI for instance, you will need a DESCRIPTION
file with list of dependencies just like for a package. In this case,
you can use the function to description from import/suggest:
att_to_desc_from_is()
.
::use_description()
usethis# bookdown Imports are in Rmds
<- c("bookdown", attachment::att_from_rmds("."))
imports ::att_to_desc_from_is(path.d = "DESCRIPTION",
attachmentimports = imports, suggests = NULL)
Then, install dependencies with
::install_deps() remotes
Of course, you can also use {attachment} out of a package to list all
package dependencies of R scripts using att_from_rscripts()
or Rmd/qmd files using att_from_rmds()
.
If you are running this inside a Rmd, you may need parameter
inside_rmd = TRUE
.
library(attachment)
<- system.file("dummypackage", package = "attachment")
dummypackage
att_from_rscripts(path = dummypackage)
#> [1] "stats" "testthat" "dummypackage"
att_from_rmds(path = file.path(dummypackage, "vignettes"), inside_rmd = TRUE)
#> [1] "knitr" "rmarkdown" "glue"
Package {attachment} has vignettes to present the different functions
available. There is also a recommendation to have a
dev_history.R
in the root directory of your package.
(Have a look at dev_history.R
in the present package)
vignette("a-fill-pkg-description", package = "attachment")
vignette("b-bookdown-and-scripts", package = "attachment")
vignette("use_renv", package = "attachment")
vignette("create-dependencies-file", package = "attachment")
The vignettes are available on the {pkgdown} page, in the “Articles” menu: https://thinkr-open.github.io/attachment/
Please note that the attachment project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms