Skip to content
Merged
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
82 changes: 35 additions & 47 deletions .github/workflows/test-coverage.yaml
Original file line number Diff line number Diff line change
@@ -1,62 +1,50 @@
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
name: test-coverage

on:
push:
branches: [main, master]
branches: [main]
pull_request:

name: test-coverage.yaml

permissions: read-all
branches: [main]

jobs:
test-coverage:
coverage:
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

permissions:
contents: write

steps:
- uses: actions/checkout@v4

- uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
- name: Set up R
uses: r-lib/actions/setup-r@v2

- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::covr, any::xml2
needs: coverage
- name: Install system dependencies
uses: r-lib/actions/setup-r-dependencies@v2

- name: Test coverage
run: |
cov <- covr::package_coverage(
quiet = FALSE,
clean = FALSE,
install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
)
print(cov)
covr::to_cobertura(cov)
shell: Rscript {0}

- uses: codecov/codecov-action@v4
with:
# Fail if error if not on PR, or if on PR and token is given
fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
file: ./cobertura.xml
plugin: noop
disable_search: true
token: ${{ secrets.CODECOV_TOKEN }}

- name: Show testthat output
if: always()
- name: Install dependencies
run: |
## --------------------------------------------------------------------
find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
shell: bash
Rscript -e 'install.packages(c("remotes", "covr", " testthat", "DT", "htmltools"))'
Rscript -e 'remotes::install_deps(dependencies = TRUE)'

- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4

- name: Run coverage and generate badge
run: |
mkdir -p coverage
Rscript -e '
cov <- covr::package_coverage(type = "tests")
covr::to_cobertura(cov, "coverage/cobertura.xml")
covr::report(cov, file = "coverage/coverage.html")
pct <- round(covr::percent_coverage(cov))
col <- if (pct >= 90) "brightgreen" else if (pct >= 75) "orange" else "red"
url <- sprintf("https://img.shields.io/badge/coverage-%s%%25-%s.svg", pct, col)
download.file(url, "coverage/badge.svg", quiet = TRUE)
'

- name: Deploy badge and reports to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
name: coverage-test-failures
path: ${{ runner.temp }}/package
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./coverage
publish_branch: gh-pages
destination_dir: _xml_coverage_reports/
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export(build_from_config)
export(detach_autos)
export(envsetup_environment)
export(get_path)
export(init)
export(read_path)
export(rprofile)
Expand Down
3 changes: 2 additions & 1 deletion R/envsetup.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
mustWork = TRUE
),
envsetup.rprofile.path = system.file(".Rprofile", package = "envsetup"),
envsetup.renviron.path = system.file(".Renviron", package = "envsetup")
envsetup.renviron.path = system.file(".Renviron", package = "envsetup"),
envsetup.path.environment = .GlobalEnv
)

toset <- !(names(op.envsetup) %in% names(op))
Expand Down
81 changes: 75 additions & 6 deletions R/paths.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,74 @@
#' Path environment
#' Environment Setup Environment
#'
#' A dedicated environment object used to store and manage path configurations
#' and other setup variables for the envsetup package. This environment provides
#' an isolated namespace for storing path objects that can be retrieved using
#' the package's path management functions.
#'
#' @format An environment object created with \code{new.env()}.
#'
#' @details
#' This environment serves as the default storage location for path objects
#' when using envsetup package functions. It helps maintain clean separation
#' between user workspace and package-managed paths.
#'
#' @examples
#' # Store a path in the envsetup environment
#' assign("project_root", "/path/to/project", envir = envsetup_environment)
#'
#' # List objects in the environment
#' ls(envir = envsetup_environment)
#'
#' # Check if the environment exists and is an environment
#' exists("envsetup_environment")
#' is.environment(envsetup_environment)
#'
#' @seealso \code{\link{get_path}}, \code{\link[base]{new.env}}
#'
#' @export
envsetup_environment <- new.env()

#' Get Path Object from Environment
#'
#' Retrieves a path object from the specified environment using non-standard
#' evaluation. The function uses `substitute()` to capture the unevaluated
#' expression and `get()` to retrieve the corresponding object.
#'
#' @param path An unquoted name of the path object to retrieve from the environment.
#' @param envir The environment to search for the path object. Defaults to the
#' value of `getOption("envsetup.path.environment")`.
#'
#' @return The path object stored in the specified environment under the given name.
#'
#' @examples
#' # Create a custom environment and store some paths
#' path_env <- new.env()
#' assign("data_dir", "/home/user/data", envir = path_env)
#' assign("output_dir", "/home/user/output", envir = path_env)
#'
#' # Set up the option to use our custom environment
#' options(envsetup.path.environment = path_env)
#'
#' # Retrieve paths using the function
#' data_path <- get_path(data_dir)
#' output_path <- get_path(output_dir)
#'
#' print(data_path) # "/home/user/data"
#' print(output_path) # "/home/user/output"
#'
#' # Using with a different environment
#' temp_env <- new.env()
#' assign("temp_dir", "/tmp/analysis", envir = temp_env)
#' temp_path <- get_path(temp_dir, envir = temp_env)
#' print(temp_path) # "/tmp/analysis"
#'
#' @seealso \code{\link[base]{get}}, \code{\link[base]{substitute}}
#'
#' @export
get_path <- function(path, envir = getOption("envsetup.path.environment")){
base::get(substitute(path), envir)
}

#' Read path
#'
#' Check each environment for the file and return the path to the first.
Expand Down Expand Up @@ -57,10 +124,11 @@ envsetup_environment <- new.env()
read_path <- function(lib,
filename,
full.path = TRUE,
envsetup_environ = Sys.getenv("ENVSETUP_ENVIRON")) {
envsetup_environ = Sys.getenv("ENVSETUP_ENVIRON"),
envir = getOption("envsetup.path.environment")) {

# lib can be a object in a different environment
# get this directly from envsetup:paths
# get this directly from envsetup_environment
lib_arg <- quo_get_expr(enquo(lib))

if (is_string(lib_arg)) {
Expand All @@ -70,7 +138,7 @@ read_path <- function(lib,
), call. = FALSE)
}

read_lib <- base::get(toString(lib_arg), "envsetup:paths")
read_lib <- base::get(toString(lib_arg), envir)

restricted_paths <- read_lib

Expand Down Expand Up @@ -166,7 +234,8 @@ read_path <- function(lib,
#'
#' # save data in data folder using write_path
#' saveRDS(mtcars, write_path(data, "mtcars.rds"))
write_path <- function(lib, filename = NULL, envsetup_environ = Sys.getenv("ENVSETUP_ENVIRON")) {
write_path <- function(lib, filename = NULL, envsetup_environ = Sys.getenv("ENVSETUP_ENVIRON"),
envir = getOption("envsetup.path.environment")) {
# examine lib to ensure it's not a string
# if it's a string, you end up with an incorrect path
lib_arg <- quo_get_expr(enquo(lib))
Expand All @@ -178,7 +247,7 @@ write_path <- function(lib, filename = NULL, envsetup_environ = Sys.getenv("ENVS
), call. = FALSE)
}

write_path <- base::get(toString(lib_arg), "envsetup:paths")
write_path <- base::get(toString(lib_arg), envir)
path <- write_path

if (length(write_path) > 1 && envsetup_environ == "") {
Expand Down
27 changes: 9 additions & 18 deletions R/rprofile.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,23 @@
#' writeLines(hierarchy, file.path(tmpdir, "hierarchy.yml"))
#'
#' rprofile(config::get(file = file.path(tmpdir, "hierarchy.yml")))
rprofile <- function(config, overwrite = TRUE) {
if ("envsetup:paths" %in% search()) {
detach("envsetup:paths", character.only = TRUE)
}
rprofile <- function(config,
envir = getOption("envsetup.path.environment"),
overwrite = TRUE) {

# remove autos and pass everything else to "envsetup:paths"
config_minus_autos <- config
config_minus_autos$autos <- NULL

# attach after package to allow functions from package to be used in config
if (any(search() == "package:envsetup")) {
pos <- which(search() == "package:envsetup") + 1
} else {
(pos <- 2L)
}

attach(config_minus_autos$paths,
name = "envsetup:paths",
pos = pos
)
walk2(names(config_minus_autos$paths),
config_minus_autos$paths,
assign,
envir = envir)

message("Attaching paths to envsetup:paths")
message(paste0("Assigned paths to ", envnames::environment_name(envir)))

# store config with a standard name in a standard location
# this will allow `envsetup::library()` to re-attach autos
assign("auto_stored_envsetup_config", config, pos)
assign("auto_stored_envsetup_config", config, envir = envir)

# If autos exist, set them
if (!is.null(config$autos)) {
Expand Down
Loading
Loading