Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ BugReports:
Imports:
cli,
desc,
evaluate,
options,
S7,
tools,
Expand All @@ -48,6 +49,7 @@ Imports:
Suggests:
covr,
rcmdcheck,
htmltools,
igraph,
knitr,
rmarkdown,
Expand Down Expand Up @@ -98,6 +100,7 @@ Collate:
'options.R'
'package.R'
'utils_backports.R'
'utils_evaluate.R'
'utils_rand.R'
'utils_rstudio.R'
'utils_tmp.R'
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ S3method(".DollarNames","val.meter::pkg")
S3method("[","val.meter::pkg")
S3method("[[","val.meter::pkg")
S3method(as.data.frame,list_of_pkg)
S3method(format,evaluate_evaluation)
S3method(format,val_meter_error)
S3method(print,val_meter_error)
export(class_metric_data_frame)
Expand Down Expand Up @@ -56,6 +57,7 @@ importFrom(tools,getVignetteInfo)
importFrom(tools,toRd)
importFrom(utils,.DollarNames)
importFrom(utils,available.packages)
importFrom(utils,capture.output)
importFrom(utils,download.packages)
importFrom(utils,getCRANmirrors)
importFrom(utils,head)
Expand Down
99 changes: 82 additions & 17 deletions R/class_pkg.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ pkg <- class_pkg <- new_class(
# necessary data dependencies to be evaluated.
data = class_environment,

# logs (not user-facing)
# A mutable environment, stores output logs captured using the `evaluate`
# package. Should contain an entry for each value in `@data`.
logs = class_environment,

#' @param resource [`resource`] (often a [`multi_resource`]), providing the
#' resources to be used for deriving packages data. If a
#' [`multi_resource`], the order of resources determines the precedence of
Expand Down Expand Up @@ -62,13 +67,25 @@ pkg <- class_pkg <- new_class(
new_object(
.parent = S7::S7_object(),
data = new.env(parent = emptyenv()),
logs = new.env(parent = emptyenv()),
metrics = list(),
resource = resource,
permissions = policy@permissions
)
}
)

method(convert, list(class_character, class_pkg)) <-
function(from, to, ...) {
if (endsWith(tolower(from), ".rds")) {
convert(readRDS(from), class_pkg)
} else if (grepl("\\bPackage:", from[[1L]])) {
pkg_from_dcf(from, ...)
} else {
pkg(from, ...)
}
}
Comment on lines +78 to +87
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few extra handlers for converting a character string into a pkg object. Specifically ensuring that we can handle Rds file paths and DCF strings.

With these, whatever is passed to the report's package parameter, we can just run convert() on it to build a pkg() object and handle Rds paths, DCF strings and package names through a single interface.


#' Generate Random Package(s)
#'
#' Create a package object to simulate metric derivation. When generating a
Expand Down Expand Up @@ -179,6 +196,8 @@ random_repo <- function(..., path = tempfile("repo")) {
#' @param x [`pkg`] object to derive data for
#' @param name `character(1L)` field name for the data to derive
#' @param ... Additional arguments unused
#' @param logs `logical(1L)` flag indicating whether console output should be
#' captured during execution.
#' @param .raise `logical(1L)` flag indicating whether errors should be raised
#' or captured. This flag is not intended to be set directly, it is exposed
#' so that recursive calls can raise lower-level errors while capturing them
Expand All @@ -189,7 +208,13 @@ random_repo <- function(..., path = tempfile("repo")) {
#'
#' @keywords internal
#' @include utils_err.R
get_pkg_data <- function(x, name, ..., .raise = .state$raise) {
get_pkg_data <- function(
x,
name,
...,
logs = opt("logs"),
.raise = .state$raise
) {
# RStudio, when trying to produce completions,will try to evaluate our lazy
# list elements. Intercept those calls and return only the existing values.
if (is_rs_rpc_get_completions_call()) {
Expand All @@ -213,7 +238,19 @@ get_pkg_data <- function(x, name, ..., .raise = .state$raise) {
assert_permissions(required_permissions, x@permissions)
assert_suggests(required_suggests)

data <- pkg_data_derive(pkg = x, field = name, ...)
if (logs) {
capture <- capture_pkg_data_derive(pkg = x, field = name, ...)
data <- capture$data
x@logs[[name]] <- capture$logs

# re-throw error after storing logs if one was produced
if (inherits(data, "error")) {
stop(data)
}
} else {
data <- pkg_data_derive(pkg = x, field = name, ...)
}

if (!identical(info@data_class, class_any)) {
data <- convert(data, info@data_class)
}
Expand Down Expand Up @@ -382,31 +419,59 @@ as.data.frame.list_of_pkg <- function(x, ...) {
}

#' @include utils_dcf.R
method(from_dcf, list(class_character, class_pkg)) <-
function(x, to, ...) {
dcf <- from_dcf(x, class_any)
method(convert, list(class_list, class_pkg)) <-
function(from, to, ...) {
Comment on lines +422 to +423
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly added handling for lists, which were effectively already handled inside the from_dcf method. Now it's just split into building a list from the DCF contents and then converting the list into a pkg object.

resource <- unknown_resource(
package = dcf[[1, "Package"]],
version = dcf[[1, "Version"]],
md5 = if ("MD5sum" %in% colnames(dcf)) {
dcf[[1, "MD5sum"]]
} else {
NA_character_
}
package = from$name %||% from$Package,
version = from$version %||% from$Version,
md5 = from$MD5sum %||% NA_character_
)

data <- new.env(parent = emptyenv())
for (name in names(from)) {
# recover gracefully from unknown fieldnames
info <- tryCatch(pkg_data_info(name), error = function(e) NULL)
if (is.null(info)) {
next
}

data[[name]] <- metric_coerce(from[[name]], info@data_class)
}

pkg <- pkg(resource)
pkg@data <- data

pkg
}

#' @include utils_dcf.R
method(from_dcf, list(class_character, class_pkg)) <-
function(x, to, ...) {
dcf <- from_dcf(x, class_any)

data <- list()
data$name <- dcf[[1, "Package"]]
data$version <- dcf[[1, "Version"]]
data$md5 <- if ("MD5sum" %in% colnames(dcf)) {
dcf[[1, "MD5sum"]]
} else {
NA_character_
}

prefix <- "Metric/"
for (name in colnames(dcf)[startsWith(colnames(dcf), prefix)]) {
field <- sub(prefix, "", name)
info <- pkg_data_info(field)

# recover gracefully from unknown fieldnames
info <- tryCatch(pkg_data_info(field), error = function(e) NULL)
if (is.null(info)) {
next
}

val <- dcf[[1, name]]
val <- metric_coerce(val, info@data_class)
data[[field]] <- val
}

pkg <- pkg(resource)
pkg@data <- data

pkg
convert(data, class_pkg)
}
12 changes: 8 additions & 4 deletions R/class_resource.R
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,11 @@ method(convert, list(class_character, class_resource)) <-
add_resource <- function(resource) {
resource_type_name <- class_desc(S7::S7_class(resource))
idx <- match(resource_type_name, all_resource_type_names)

if (is.na(idx) || !is.null(resources[[idx]])) {
return()
}

resources[[idx]] <<- resource
idx
}
Expand Down Expand Up @@ -317,8 +319,8 @@ method(convert, list(class_character, class_resource)) <-
# iterate over other allowed resource types
for (to_idx in seq_along(all_resource_types)) {
# that are not yet populated with a known resource
to_resource <- resources[[to_idx]]
if (!is.null(to_resource)) {
existing_resource <- resources[[to_idx]]
if (!is.null(existing_resource)) {
next
}

Expand All @@ -336,7 +338,7 @@ method(convert, list(class_character, class_resource)) <-
# special handling for error conditions used to test discovery in tests
if (inherits(result, "test_suite_signal")) {
stop(result)
} else if (inherits(result, "error")) {
} else if (is.null(result) || inherits(result, "error")) {
next
}

Expand Down Expand Up @@ -589,7 +591,9 @@ method(convert, list(class_local_source_resource, class_install_resource)) <-

method(convert, list(class_resource, class_unknown_resource)) <-
function(from, to, ...) {
set_props(to(), props(from, names(class_unknown_resource@properties)))
out <- to()
props(out) <- props(from, prop_names(out))
out
}

method(to_dcf, class_resource) <- function(x, ...) {
Expand Down
10 changes: 6 additions & 4 deletions R/data_coverage.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ impl_data(
impl_data(
"covr_coverage",
for_resource = local_source_resource,
function(pkg, resource, field, ..., quiet = opt("quiet")) {
covr::package_coverage(resource@path, type = "tests", quiet = quiet)
function(pkg, resource, field, ...) {
# package installs use `system2()` whose output cannot be captured by sink()
# so we just execute quietly
covr::package_coverage(resource@path, type = "tests", quiet = TRUE)
}
)

Expand All @@ -23,7 +25,7 @@ impl_data(
"The fraction of expressions of package code that are evaluated by any ",
"test"
),
function(pkg, resource, field, ..., quiet = opt("quiet")) {
function(pkg, resource, field, ...) {
tally <- covr::tally_coverage(pkg$covr_coverage, by = "expression")
mean(tally$value > 0)
}
Expand All @@ -45,7 +47,7 @@ impl_data(
description = paste0(
"The fraction of lines of package code that are evaluated by any test"
),
function(pkg, resource, field, ..., quiet = opt("quiet")) {
function(pkg, resource, field, ...) {
tally <- covr::tally_coverage(pkg$covr_coverage, by = "line")
mean(tally$value > 0)
}
Expand Down
23 changes: 21 additions & 2 deletions R/data_desc.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ impl_data(
"name",
title = "Package name",
class = class_character,
for_resource = new_union(source_code_resource, install_resource),
function(pkg, resource, field, ...) {
pkg$desc$get_field("Package")
}
)

impl_data(
"name",
for_resource = repo_resource,
for_resource = class_resource,
function(pkg, resource, field, ...) {
resource@package
}
Expand All @@ -30,19 +31,37 @@ impl_data(
impl_data(
"version",
class = class_character,
for_resource = new_union(source_code_resource, install_resource),
function(pkg, resource, field, ...) {
pkg$desc$get_field("Version")
}
)

impl_data(
"version",
for_resource = repo_resource,
for_resource = class_resource,
function(pkg, resource, field, ...) {
resource@version
}
)

impl_data(
"md5",
class = class_character,
for_resource = new_union(source_code_resource, install_resource),
function(pkg, resource, field, ...) {
pkg$desc$get_field("MD5sum")
}
)

impl_data(
"md5",
for_resource = class_resource,
function(pkg, resource, field, ...) {
resource@md5
}
)

impl_data(
"dependency_count",
class = class_integer,
Expand Down
26 changes: 6 additions & 20 deletions R/data_r_cmd_check.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,12 @@ impl_data(
local_source_resource,
source_archive_resource
),
function(pkg, resource, field, ..., quiet = opt("quiet")) {
# suppress messages to avoid stdout output from subprocess
# (eg warnings about latex availability not suppressed by rcmdcheck)

wrapper <- if (quiet) {
function(...) capture.output(..., type = "message")
} else {
identity
}

wrapper({
result <- rcmdcheck::rcmdcheck(
resource@path,
quiet = quiet,
error_on = "never",
build_args = "--no-manual"
)
})

result
function(pkg, resource, field, ...) {
rcmdcheck::rcmdcheck(
resource@path,
error_on = "never",
build_args = "--no-manual"
)
}
)

Expand Down
11 changes: 5 additions & 6 deletions R/data_vignettes.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ impl_data(
return(0)
}

nodes |>
xml2::xml_attr("href") |>
basename() |>
tools::file_path_sans_ext() |>
unique() |>
length()
paths <- xml2::xml_attr(nodes, "href")
filenames <- basename(paths)
filestems <- tools::file_path_sans_ext(filenames)
Comment on lines -34 to +36
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of an unrelated fix, but noticed that the use of |> would force us to bump our minimum R version support so I just converted them into more traditional calls.


length(unique(filestems))
}
)

Expand Down
7 changes: 3 additions & 4 deletions R/data_web_html.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ impl_data(
for_resource = cran_repo_resource,
permissions = "network",
function(pkg, resource, field, ...) {
pkg$web_url |>
httr2::request() |>
httr2::req_perform() |>
httr2::resp_body_html()
req <- httr2::request(pkg$web_url)
resp <- httr2::req_perform(req)
httr2::resp_body_html(resp)
}
)
Loading