diff --git a/DESCRIPTION b/DESCRIPTION index 4c70304..98ca371 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,15 +9,19 @@ Description: Provides functions for learning about your R libraries, and the License: MIT + file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 URL: https://github.com/ateucher/libminer, http://andyteucher.ca/libminer/ BugReports: https://github.com/ateucher/libminer/issues +Depends: R (>= 4.1) Suggests: knitr, rmarkdown, testthat (>= 3.0.0) Config/testthat/edition: 3 Imports: + cli, + dplyr, fs, - purrr + purrr, + rlang VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 6a5787d..6aabc74 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,4 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(lib) export(lib_summary) importFrom(purrr,map_dbl) +importFrom(rlang,.data) diff --git a/R/lib-summary.R b/R/lib-summary.R index a2e4e43..59152f9 100644 --- a/R/lib-summary.R +++ b/R/lib-summary.R @@ -2,6 +2,8 @@ #' #' Provides a brief summary of the package libraries on your machine #' +#' @param ... Grouping variables for the summary. Zero or more of the column +#' names from [lib()]. #' @param sizes Should the sizes of the libraries be calculated? #' Logical; default `FALSE`. #' @@ -12,18 +14,48 @@ #' @examples #' lib_summary() #' lib_summary(sizes = TRUE) -lib_summary <- function(sizes = FALSE) { - pkgs <- utils::installed.packages() - pkg_tbl <- table(pkgs[, "LibPath"]) - pkg_df <- as.data.frame(pkg_tbl, stringsAsFactors = FALSE) - names(pkg_df) <- c("Library", "n_packages") +lib_summary <- function(..., sizes = FALSE) { + if (!is.logical(sizes)) { + cli::cli_abort("You supplied {.val {sizes}} to {.var sizes}. It should be a {.cls logical} value, not {.obj_type_friendly {sizes}}.") + } - if (sizes) { - pkg_df$lib_size <- map_dbl( - pkg_df$Library, - ~ sum(fs::file_size(fs::dir_ls(.x, recurse = TRUE))), + lib() |> + calculate_sizes(do_calc = sizes) |> + dplyr::group_by(...) |> + dplyr::summarise( + n = dplyr::n(), + dplyr::across(dplyr::any_of("size"), sum), + .groups = "drop" ) - } +} + +#' calculate sizes +#' +#' @param df a data.frame +#' @param do_calc should the sizes be calculated? If `FALSE`, `df` is +#' returned unaltered. +#' +#' @return df with a lib_size column +#' @noRd +calculate_sizes <- function(df, do_calc) { + if (!isTRUE(do_calc)) return(df) - pkg_df + cli::cli_inform(c("i" = "Calculating sizes...")) + + df |> + dplyr::mutate( + size = purrr::map_dbl( + fs::path(.data$LibPath, .data$Package), + \(x) sum(fs::file_size(fs::dir_ls(x, recurse = TRUE))) + ) + ) +} + +#' Generate a tible of installed packages +#' +#' @return a tibble of all packages installed on a system +#' @export +lib <- function() { + utils::installed.packages() |> + dplyr::as_tibble() } diff --git a/R/libminer-package.R b/R/libminer-package.R index f5dba9b..3473664 100644 --- a/R/libminer-package.R +++ b/R/libminer-package.R @@ -3,5 +3,6 @@ ## usethis namespace: start #' @importFrom purrr map_dbl +#' @importFrom rlang .data ## usethis namespace: end NULL diff --git a/README.Rmd b/README.Rmd index dff1c86..1fea8b9 100644 --- a/README.Rmd +++ b/README.Rmd @@ -33,12 +33,25 @@ devtools::install_github("ateucher/libminer") ## Example usage -To get a count of installed packages in each of your library locations, -optionally with the total sizes, use the `lib_summary()` function: -```{r example} +To get a nicely formatted tibble of your installed packages, use the `lib()` +function: + +```{r} library(libminer) -lib_summary() -# specify `sizes = TRUE` to calculate the total size on disk of your packages -lib_summary(sizes = TRUE) +lib() +``` + + +To get a count of installed packages, grouped by any combination of variables +in the `lib()` data.frame, optionally with the total sizes, use the `lib_summary()` function: + +```{r example} +lib_summary(LibPath, License) +``` + +Specify `sizes = TRUE` to calculate the total size on disk of your packages + +```{r} +lib_summary(LibPath, NeedsCompilation, sizes = TRUE) ``` diff --git a/README.md b/README.md index 7b1124c..c77a7b2 100644 --- a/README.md +++ b/README.md @@ -24,28 +24,67 @@ devtools::install_github("ateucher/libminer") ## Example usage -To get a count of installed packages in each of your library locations, -optionally with the total sizes, use the `lib_summary()` function: +To get a nicely formatted tibble of your installed packages, use the +`lib()` function: ``` r library(libminer) -lib_summary() -#> Library -#> 1 /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library -#> 2 /private/var/folders/_f/n9fw7ctx3fqf2ty9ylw502g80000gn/T/RtmpTxIv1Z/temp_libpath17e8111f3ca5d -#> 3 /Users/andy/Library/R/arm64/4.3/library -#> n_packages -#> 1 29 -#> 2 1 -#> 3 191 -# specify `sizes = TRUE` to calculate the total size on disk of your packages -lib_summary(sizes = TRUE) -#> Library -#> 1 /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library -#> 2 /private/var/folders/_f/n9fw7ctx3fqf2ty9ylw502g80000gn/T/RtmpTxIv1Z/temp_libpath17e8111f3ca5d -#> 3 /Users/andy/Library/R/arm64/4.3/library -#> n_packages lib_size -#> 1 29 71351828 -#> 2 1 14402 -#> 3 191 1164955163 +lib() +#> # A tibble: 406 × 16 +#> Package LibPath Version Priority Depends Imports LinkingTo Suggests Enhances +#> +#> 1 libminer /priva… 0.0.0.… R (>= … "cli,\… "knitr,… +#> 2 abind /Users… 1.4-8 R (>= … "metho… +#> 3 anytime /Users… 0.3.9 R (>= … "Rcpp … Rcpp (>=… "tinyte… +#> 4 arrow /Users… 17.0.0… R (>= … "asser… cpp11 (>… "blob, … +#> 5 askpass /Users… 1.2.1 "sys (… "testth… +#> 6 assertt… /Users… 0.2.1 "tools" "testth… +#> 7 backpor… /Users… 1.5.0 R (>= … +#> 8 base64e… /Users… 0.1-3 R (>= … png +#> 9 bayespl… /Users… 1.11.1 R (>= … "dplyr… "ggfort… +#> 10 bccamtr… /Users… 0.0.0.… R (>= … "bcmap… "DBI,\n… +#> # ℹ 396 more rows +#> # ℹ 7 more variables: License , License_is_FOSS , +#> # License_restricts_use , OS_type , MD5sum , +#> # NeedsCompilation , Built +``` + +To get a count of installed packages, grouped by any combination of +variables in the `lib()` data.frame, optionally with the total sizes, +use the `lib_summary()` function: + +``` r +lib_summary(LibPath, License) +#> # A tibble: 42 × 3 +#> LibPath License n +#> +#> 1 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… GPL 1 +#> 2 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… GPL (>… 5 +#> 3 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… GPL (>… 1 +#> 4 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… GPL-2 … 5 +#> 5 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… LGPL (… 1 +#> 6 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… Part o… 14 +#> 7 /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/l… Unlimi… 2 +#> 8 /Users/andy/Library/R/arm64/4.4/library Apache… 1 +#> 9 /Users/andy/Library/R/arm64/4.4/library Apache… 2 +#> 10 /Users/andy/Library/R/arm64/4.4/library Apache… 5 +#> # ℹ 32 more rows +``` + +Specify `sizes = TRUE` to calculate the total size on disk of your +packages + +``` r +lib_summary(LibPath, NeedsCompilation, sizes = TRUE) +#> ℹ Calculating sizes... +#> # A tibble: 7 × 4 +#> LibPath NeedsCompilation n size +#> +#> 1 /Library/Frameworks/R.framework/Versions/4.4-ar… no 2 8.81e5 +#> 2 /Library/Frameworks/R.framework/Versions/4.4-ar… yes 23 6.14e7 +#> 3 /Library/Frameworks/R.framework/Versions/4.4-ar… 4 4.70e6 +#> 4 /Users/andy/Library/R/arm64/4.4/library no 216 3.23e8 +#> 5 /Users/andy/Library/R/arm64/4.4/library yes 158 1.84e9 +#> 6 /Users/andy/Library/R/arm64/4.4/library 2 3.70e6 +#> 7 /private/var/folders/_f/n9fw7ctx3fqf2ty9ylw502g… 1 1.79e4 ``` diff --git a/man/lib.Rd b/man/lib.Rd new file mode 100644 index 0000000..3b3ff94 --- /dev/null +++ b/man/lib.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lib-summary.R +\name{lib} +\alias{lib} +\title{Generate a tible of installed packages} +\usage{ +lib() +} +\value{ +a tibble of all packages installed on a system +} +\description{ +Generate a tible of installed packages +} diff --git a/man/lib_summary.Rd b/man/lib_summary.Rd index a5ca53f..cdd8dda 100644 --- a/man/lib_summary.Rd +++ b/man/lib_summary.Rd @@ -4,9 +4,12 @@ \alias{lib_summary} \title{R Library Summary} \usage{ -lib_summary(sizes = FALSE) +lib_summary(..., sizes = FALSE) } \arguments{ +\item{...}{Grouping variables for the summary. Zero or more of the column +names from \code{\link[=lib]{lib()}}.} + \item{sizes}{Should the sizes of the libraries be calculated? Logical; default \code{FALSE}.} } diff --git a/man/libminer-package.Rd b/man/libminer-package.Rd index efb759d..c9904f8 100644 --- a/man/libminer-package.Rd +++ b/man/libminer-package.Rd @@ -12,6 +12,7 @@ Provides functions for learning about your R libraries, and the packages you hav Useful links: \itemize{ \item \url{https://github.com/ateucher/libminer} + \item \url{http://andyteucher.ca/libminer/} \item Report bugs at \url{https://github.com/ateucher/libminer/issues} } diff --git a/tests/testthat/_snaps/lib-summary.md b/tests/testthat/_snaps/lib-summary.md new file mode 100644 index 0000000..176c608 --- /dev/null +++ b/tests/testthat/_snaps/lib-summary.md @@ -0,0 +1,16 @@ +# lib_summary fails appropriately + + Code + lib_summary(sizes = "foo") + Condition + Error in `lib_summary()`: + ! You supplied "foo" to `sizes`. It should be a value, not a string. + +--- + + Code + lib_summary(sizes = 12) + Condition + Error in `lib_summary()`: + ! You supplied 12 to `sizes`. It should be a value, not a number. + diff --git a/tests/testthat/test-lib-summary.R b/tests/testthat/test-lib-summary.R index dcea005..faeb219 100644 --- a/tests/testthat/test-lib-summary.R +++ b/tests/testthat/test-lib-summary.R @@ -1,18 +1,21 @@ -test_that("lib_summary returns expected results", { +test_that("lib_summary returns expected results with defaults", { res <- lib_summary() expect_s3_class(res, "data.frame") - expect_equal(ncol(res), 2) - expect_equal(names(res), c("Library", "n_packages")) - expect_type(res$Library, "character") - expect_type(res$n_packages, "integer") + expect_equal(ncol(res), 1) + expect_equal(names(res), "n") + expect_type(res$n, "integer") }) -test_that("lib_summary fails appropriately", { - expect_error(lib_summary(sizes = "foo"), "not interpretable as logical") +test_that("lib_summary returns expected results with defaults", { + res <- lib_summary(LibPath, License, sizes = TRUE) + expect_s3_class(res, "data.frame") + expect_equal(ncol(res), 4) + expect_equal(names(res), c("LibPath", "License", "n", "size")) + expect_type(res$n, "integer") + expect_type(res$size, "double") }) -test_that("sizes argument works", { - res <- lib_summary(sizes = TRUE) - expect_equal(names(res), c("Library", "n_packages", "lib_size")) - expect_type(res$lib_size, "double") +test_that("lib_summary fails appropriately", { + expect_snapshot(lib_summary(sizes = "foo"), error = TRUE) + expect_snapshot(lib_summary(sizes = 12), error = TRUE) })