Skip to content

Commit

Permalink
Merge pull request #117 from ThinkR-open/att_from_examples
Browse files Browse the repository at this point in the history
Att from examples
  • Loading branch information
MurielleDelmotte authored Aug 1, 2024
2 parents b26fefd + 2c6270c commit fe48132
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 14 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: attachment
Title: Deal with Dependencies
Version: 0.4.2
Version: 0.4.2.9000
Authors@R: c(
person("Sébastien", "Rochette", , "[email protected]", role = c("cre", "aut"),
comment = c(ORCID = "0000-0002-1565-9313")),
Expand Down Expand Up @@ -31,7 +31,7 @@ Config/Needs/website: ThinkR-open/thinkrtemplate
Config/testthat/edition: 3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.0
RoxygenNote: 7.3.1
Language: en-US
Depends:
R (>= 3.4)
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export("%>%")
export(att_amend_desc)
export(att_from_description)
export(att_from_examples)
export(att_from_namespace)
export(att_from_qmd)
export(att_from_qmds)
Expand Down
13 changes: 12 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# attachment (development version)

## New features

- Add `att_from_examples()` to get all packages called in examples from R files
- `att_amend_desc` amend package DESCRIPTION file (Suggests) with the list of dependencies extracted from examples in R files.

## Patch

- Adding an example using a suggest package to the dummypackage

# attachment 0.4.2

## New features
Expand Down Expand Up @@ -182,7 +193,7 @@ Minor
* New function `install_from_description` to install all missing packages listed in the description file
* Add an hex by @statnmap !
* Allow for absence of vignette folder in `att_to_description`
* Add `create_dependencies_file` to create a file listing all packages dependencies to install before your package
* Add `create_dependencies_file` to create a file listing all packages dependencies to dinstall before your package
* Allow for `pkg::fun` calls in R scripts with `att_from_functions`
* Add option to run `devtools::document()` before `att_from_description`

Expand Down
34 changes: 34 additions & 0 deletions R/add_from_examples.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#' Get all packages called in examples from R files
#'
#' @param dir.r path to directory with R scripts.
#'
#' @return Character vector of packages called with library or require.
#'
#' @examples
#' dummypackage <- system.file("dummypackage",package = "attachment")
#'
#' # browseURL(dummypackage)
#' att_from_examples(dir.r = file.path(dummypackage,"R"))

#' @export
att_from_examples <- function(dir.r = "R") {
rfiles <- list.files(dir.r, full.names = TRUE)

roxy_file <- tempfile("roxy.examples", fileext = ".R")

all_examples <- unlist(lapply(rfiles, function(the_file) {
file_roxytags <- roxygen2::parse_file(the_file)
res <- unlist(
lapply(file_roxytags,
function(x) roxygen2::block_get_tag_value(block = x, tag = "examples"))
)
res
}))
# Clean \dontrun and \donttest, and replace with '{' on next line
all_examples_clean <-
gsub(pattern = "\\\\dontrun\\s*\\{|\\\\donttest\\s*\\{", replacement = "#ICI\n{", x = all_examples)
cat(all_examples_clean, file = roxy_file, sep = "\n")
all_deps_examples <- attachment::att_from_rscript(roxy_file)
file.remove(roxy_file)
return(all_deps_examples)
}
12 changes: 11 additions & 1 deletion R/att_to_description.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#' Amend DESCRIPTION with dependencies read from package code parsing
#'
#' Amend package DESCRIPTION file with the list of dependencies extracted from
#' R, tests, vignettes files.
#' R, examples, tests, vignettes files.
#' att_to_desc_from_pkg() is an alias of att_amend_desc(),
#' for the correspondence with [att_to_desc_from_is()].
#'
Expand All @@ -19,6 +19,7 @@
#' @inheritParams att_from_namespace
#' @inheritParams att_to_desc_from_is
#' @inheritParams att_from_rmds
#' @inheritParams att_from_examples
#'
#' @importFrom desc description
#'
Expand Down Expand Up @@ -88,6 +89,8 @@ att_amend_desc <- function(path = ".",
on.exit(setwd(old))
}



path <- normalizePath(path)

# decide whether to use or update config file ----
Expand Down Expand Up @@ -196,6 +199,13 @@ att_amend_desc <- function(path = ".",

# Suggests ----
suggests <- NULL

# Get suggests in examples and remove if already in imports
if (dir.r != "") {
ex <- att_from_examples(dir.r = dir.r)
suggests <- c(suggests, ex[!ex %in% imports])
}

# Get suggests in vignettes and remove if already in imports
if (!grepl("^$|^\\s+$$", dir.v)) {
vg <- att_from_rmds(dir.v, inside_rmd = inside_rmd)
Expand Down
3 changes: 3 additions & 0 deletions inst/dummypackage/R/my_mean.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#'
#' @export
#' @importFrom magrittr %>%
#' @examples
#' # example code
#' library(utils)
my_mean <- function(x){
x <- x %>% stats::na.omit()
1+1
Expand Down
2 changes: 1 addition & 1 deletion man/att_amend_desc.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions man/att_from_examples.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/attachment-package.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 100 additions & 6 deletions tests/testthat/test-amend-description.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ test_that("att_amend_desc updates description", {
expect_equal(desc_file[w.depends + 6], " glue,")
expect_equal(desc_file[w.depends + 7], " knitr,")
expect_equal(desc_file[w.depends + 8], " rmarkdown,")
expect_equal(desc_file[w.depends + 9], " testthat")
expect_equal(desc_file[w.depends + 10], "LinkingTo:" )
expect_equal(desc_file[w.depends + 11], " Rcpp")
expect_equal(desc_file[w.depends + 9], " testthat,")
expect_equal(desc_file[w.depends + 10], " utils")
expect_equal(desc_file[w.depends + 11], "LinkingTo:" )
expect_equal(desc_file[w.depends + 12], " Rcpp")
# base does not appear
expect_false(all(grepl("base", desc_file)))
# utils is removed
Expand Down Expand Up @@ -485,12 +486,105 @@ library(ggplot3)
expect_equal(desc_file[w.depends + 7], " glue,")
expect_equal(desc_file[w.depends + 8], " knitr,")
expect_equal(desc_file[w.depends + 9], " rmarkdown,")
expect_equal(desc_file[w.depends + 10], " testthat")
expect_equal(desc_file[w.depends + 11], "LinkingTo:" )
expect_equal(desc_file[w.depends + 12], " Rcpp")
expect_equal(desc_file[w.depends + 10], " testthat,")
expect_equal(desc_file[w.depends + 11], " utils")
expect_equal(desc_file[w.depends + 12], "LinkingTo:" )
expect_equal(desc_file[w.depends + 13], " Rcpp")


# Clean after
unlink(dummypackage, recursive = TRUE)
})


# Test update desc when packages in examples ----
test_that("if a package is used in an example, it is added to Suggests packages", {
# Copy package in a temporary directory
tmpdir <- tempfile("dummysuggestexamples")
dir.create(tmpdir)
file.copy(system.file("dummypackage",package = "attachment"), tmpdir, recursive = TRUE)
dummypackage <- file.path(tmpdir, "dummypackage")

r_file <- file.path(dummypackage, "R", "fun_manual.R")
file.create(r_file)
#> [1] TRUE
writeLines(
text = "#' @importFrom magrittr %>%
#' @examples
#' library(pkgfake)
#' fakepkg::fun()
#' @export
my_length <- function(x) {
x %>% length()
}",
con = r_file
)

attachment::att_amend_desc(path = dummypackage, check_if_suggests_is_installed = FALSE)


desc_file <- readLines(file.path(dummypackage, "DESCRIPTION"))

w.depends <- grep("Depends:", desc_file)
expect_length(w.depends, 1)
expect_equal(desc_file[w.depends + 5], "Suggests: ")
expect_equal(desc_file[w.depends + 6], " fakepkg,")
expect_equal(desc_file[w.depends + 7], " glue,")
expect_equal(desc_file[w.depends + 8], " knitr,")
expect_equal(desc_file[w.depends + 9], " pkgfake,")
expect_equal(desc_file[w.depends + 10], " rmarkdown,")
expect_equal(desc_file[w.depends + 11], " testthat,")
expect_equal(desc_file[w.depends + 12], " utils")
# Clean after
unlink(dummypackage, recursive = TRUE)

})


test_that("if a package is used in an example has already been added to IMPORTS, it is not added to the suggests, it is added to Suggests packages", {
# Copy package in a temporary directory
tmpdir <- tempfile("dummysuggestexamples")
dir.create(tmpdir)
file.copy(system.file("dummypackage",package = "attachment"), tmpdir, recursive = TRUE)
dummypackage <- file.path(tmpdir, "dummypackage")

r_file <- file.path(dummypackage, "R", "fun_manual.R")
file.create(r_file)
#> [1] TRUE
writeLines(
text = "#' @importFrom magrittr %>%
#' @examples
#' library(magrittr)
#' fakepkg::fun()
#' @export
my_length <- function(x) {
x %>% length()
}",
con = r_file
)

attachment::att_amend_desc(path = dummypackage, check_if_suggests_is_installed = FALSE)


desc_file <- readLines(file.path(dummypackage, "DESCRIPTION"))

w.depends <- grep("Depends:", desc_file)
expect_length(w.depends, 1)
expect_equal(desc_file[w.depends + 1], " R (>= 3.5.0)")
expect_equal(desc_file[w.depends + 2], "Imports: ")
expect_equal(desc_file[w.depends + 3], " magrittr,")
expect_equal(desc_file[w.depends + 4], " stats")
expect_equal(desc_file[w.depends + 5], "Suggests: ")
expect_equal(desc_file[w.depends + 6], " fakepkg,")
expect_equal(desc_file[w.depends + 7], " glue,")
expect_equal(desc_file[w.depends + 8], " knitr,")
expect_equal(desc_file[w.depends + 9], " rmarkdown,")
expect_equal(desc_file[w.depends + 10], " testthat,")
expect_equal(desc_file[w.depends + 11], " utils")
expect_equal(desc_file[w.depends + 12], "LinkingTo:" )
expect_equal(desc_file[w.depends + 13], " Rcpp")

# Clean after
unlink(dummypackage, recursive = TRUE)

})
24 changes: 24 additions & 0 deletions tests/testthat/test-att_from_examples.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
test_that("att_from_examples works", {
tmpdir <- tempfile("suggestexamples")

dir.create(file.path(tmpdir, "R"), recursive = TRUE)

r_file <- file.path(tmpdir, "R", "fun_manual.R")
file.create(r_file)

writeLines(
text = "#' @importFrom magrittr %>%
#' @examples
#' library(magrittr)
#' fakepkg::fun()
#' @export
my_length <- function(x) {
x %>% length()
}",
con = r_file
)

expect_equal(att_from_examples(dir.r = file.path(tmpdir, "R")),
c("magrittr", "fakepkg"))

})
3 changes: 2 additions & 1 deletion vignettes/a-fill-pkg-description.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,14 @@ for (i in to_install) {

## Other possibilities

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 files using `att_from_rmds()`.
Of course, you can also use {attachment} out of a package to list all package dependencies of R scripts using `att_from_rscripts()`, Rmd files using `att_from_rmds()` or examples from R scripts using `att_from_examples()`.

```{r, eval=TRUE}
dummypackage <- system.file("dummypackage", package = "attachment")
att_from_rscripts(path = file.path(dummypackage, "R"))
att_from_rmds(path = file.path(dummypackage, "vignettes"), inside_rmd = TRUE)
att_from_examples(dir.r = file.path(dummypackage, "R"))
```


6 changes: 6 additions & 0 deletions vignettes/b-bookdown-and-scripts.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ This reads all files in directories of R scripts (default to `R` directory of a
att_from_rscripts()
```

Called in examples from R scripts:

```{r, eval=FALSE}
att_from_examples()
```

## Get all packages called in your Rmd
If you have vignette, you may want to list extra libraries, not listed in your "Depends" list. This function applies to any Rmd file, of course.

Expand Down

0 comments on commit fe48132

Please sign in to comment.