diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 0000000..0b5bd85 --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,5 @@ +^.*\.Rproj$ +^\.Rproj\.user$ +^\.pre-commit-config\.yaml$ +^\.github$ +^CHANGELOG\.md$ diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..eb21f8b --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,41 @@ +on: + push: + branches: [main] + pull_request: + branches: [main] + +name: pre-commit + +jobs: + pre-commit: + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.head_ref }} + + - name: Setup R + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Install dependencies + uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::roxygen2 + needs: roxygen2 + + - uses: pre-commit/action@v2.0.3 + + - uses: stefanzweifel/git-auto-commit-action@v5 + if: '!cancelled()' + with: + commit_message: pre-commit autofixes diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3fcb6be --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: Build and Attach R Package + +on: + release: + types: [created] + +jobs: + build: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: release + http-user-agent: release + use-public-rspm: true + + - name: Build package + run: | + R CMD build . + FILENAME=$(ls dso_*.tar.gz) + echo "FILENAME=${FILENAME}" >> $GITHUB_ENV + + - name: Check version + run: | + VERSION=$(echo $FILENAME | sed 's/.*_\(.*\).tar.gz/\1/') + if [ "v${VERSION}" != "${GITHUB_REF#refs/tags/}" ]; then + echo "Version mismatch. Tag version and package version should be the same." + exit 1 + fi + + - name: Attach tarball to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ env.FILENAME }} + asset_name: ${{ env.FILENAME }} + asset_content_type: application/gzip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b94b328 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,50 @@ +# The purpose of this workflow is to execute `R CMD check` on different R and OS version. +# +# 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 +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: R-CMD-check + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - { os: macOS-latest, r: "release" } + - { os: windows-latest, r: "release" } + - { os: ubuntu-latest, r: "devel", http-user-agent: "release" } + - { os: ubuntu-latest, r: "release" } + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..521eaa4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,49 @@ +# All available hooks: https://pre-commit.com/hooks.html +# R specific hooks: https://github.com/lorenzwalthert/precommit +repos: + - repo: https://github.com/lorenzwalthert/precommit + rev: v0.4.3 + hooks: + - id: style-files + args: [--style_pkg=styler, --style_fun=tidyverse_style, --scope=tokens] + - id: parsable-R + - id: no-browser-statement + - id: no-debug-statement + - id: deps-in-desc + args: [--allow_private_imports] + - id: roxygenize + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: end-of-file-fixer + exclude: '\.Rd' + - id: detect-private-key + - id: check-ast + - id: mixed-line-ending + args: [--fix=lf] + - id: trailing-whitespace + - id: check-case-conflict + # Check that there are no merge conflicts (could be generated by template sync) + - id: check-merge-conflict + args: [--assume-in-merge] + - repo: https://github.com/pre-commit-ci/pre-commit-ci-config + rev: v1.5.1 + hooks: + # Only reuiqred when https://pre-commit.ci is used for config validation + - id: check-pre-commit-ci-config + - repo: local + hooks: + - id: forbid-to-commit + name: Don't commit common R artifacts + entry: Cannot commit .Rhistory, .RData, .Rds or .rds. + language: fail + files: '\.(Rhistory|RData|Rds|rds)$' + exclude: "(inst/extdata|data)/.*" + # - repo: https://github.com/pre-commit/mirrors-prettier + # rev: v3.0.0-alpha.6 + # hooks: + # - id: prettier + # language_version: "17.9.1" + +ci: + autoupdate_schedule: monthly diff --git a/CHANGELOG.md b/CHANGELOG.md index acfceb9..17c600f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.4.3 + +### Improvements + +- updated .Rbuildignore ignoring package redundant files +- added precommit configs +- included methods show +- set class of dsoParams object +- fixed R CMD check warnings + ## v0.4.2 ### Improvements diff --git a/DESCRIPTION b/DESCRIPTION index 0bc33bc..7cfaac4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,22 +1,25 @@ Package: dso Type: Package -Title: dso R companion package -Version: 0.4.2 +Title: dso R companion package +Version: 0.4.3 Author: Daniel Schreyer, - Gregor Sturm, + Gregor Sturm, Thomas Schwarzl Maintainer: Daniel Schreyer, - Gregor Sturm, + Gregor Sturm, Thomas Schwarzl -Description: Collection of functions used with the DevOps dso application. +Description: Collection of functions used with the DevOps dso application. License: GPL-3 + file LICENSE Encoding: UTF-8 LazyData: true Imports: yaml, glue, - here -RoxygenNote: 7.3.1 -Suggests: + here, + stringr, + methods, + rlang +RoxygenNote: 7.3.2 +Suggests: testthat (>= 3.0.0) Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index 13de47b..c1781bf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -11,11 +11,13 @@ export(read_params) export(safe_get) export(set_stage) export(stage_here) +exportClasses(dsoParams) exportMethods(as.list) exportMethods(show) importFrom(glue,glue) importFrom(here,here) importFrom(here,i_am) +importFrom(methods,show) importFrom(rlang,caller_env) importFrom(stringr,coll) importFrom(stringr,str_match_all) diff --git a/R/class-dsoParams.R b/R/class-dsoParams.R index 13694eb..22a15bb 100644 --- a/R/class-dsoParams.R +++ b/R/class-dsoParams.R @@ -1,7 +1,18 @@ +#' dsoParams class +#' +#' @slot params A list of lists containing parameters +#' @export +setClass("dsoParams", + slots = list( + params = "list" + ) +) + #' A "dsoParams" and its constructor: #' #' @title dsoParams: list with safe access #' @param x empty, or a recursive list of lists which is converted to dsoParams +#' #' @examples #' # initiating empty #' params <- dsoParams() @@ -15,25 +26,26 @@ #' params <- dsoParams(params) #' #' @export -dsoParams <- function( x = list()) { - if(! is.list(x)) +dsoParams <- function(x = list()) { + if (!is.list(x)) { stop("x needs to be a list or a list of lists.") - + } # recursively x <- lapply(x, function(y) { - if(is.list(y)) { - dsoParams(y) - } else { - y - } + if (is.list(y)) { + dsoParams(y) + } else { + y + } }) class(x) <- c("dsoParams", "list") return(x) } - #' overriding the the $ operator to add secure list calling so that #' it cannot return NULL when call does not exist +#' @param x dsoParams object +#' @param name field name #' @export `$.dsoParams` <- function(x, name) { if (!name %in% names(x)) { @@ -45,6 +57,9 @@ dsoParams <- function( x = list()) { #' And the [[ operator: to add secure list calling so that #' it cannot return NULL when call does not exist +#' @param x dsoParams object +#' @param i index for `[[` operator +#' @param ... additional arguments passed to the `[[` operator #' @export `[[.dsoParams` <- function(x, i, ...) { if (is.character(i) && !i %in% names(x)) { @@ -52,37 +67,45 @@ dsoParams <- function( x = list()) { } else if (is.numeric(i) && (i < 1 || i > length(x))) { stop(paste("Index '", i, "' is out of bounds in dsoParams", sep = "")) } + + NextMethod() } #' Custom print method for dsoParams class +#' @param x dsoParams object +#' @param ... additional parameters are ignored #' @export -print.dsoParams <- function(object, ...) { - cat(yaml::as.yaml(object)) +print.dsoParams <- function(x, ...) { + cat(yaml::as.yaml(x)) } #' Custom show method for dsoParams class +#' @importFrom methods show +#' @param object dsoParams object #' @export -setMethod(f = "show", - signature = "dsoParams", - definition = function(object) { - cat(yaml::as.yaml(object)) - }) +setMethod( + f = "show", + signature = "dsoParams", + definition = function(object) { + cat(yaml::as.yaml(object)) + } +) -# Custom as.list method for dsoParams class +#' Custom as.list method for dsoParams class +#' @param x dsoParams object +#' @return A list #' @export setMethod( - f = "as.list", + f = "as.list", signature = "dsoParams", definition = function(x) { lapply(x, function(y) { - if("dsoParams" %in% class(y)) { + if ("dsoParams" %in% class(y)) { as.list(unclass(y)) } else { - x + y } }) } ) - - diff --git a/R/compile_config.R b/R/compile_config.R index 422ca4c..275a965 100644 --- a/R/compile_config.R +++ b/R/compile_config.R @@ -6,6 +6,8 @@ #' #' @keywords dso dvc yaml compile config #' +#' @param dir directory (including subdirectories and relevant parent files) to compile. By default compiles the current working directory. +#' #' @export #' #' @examples diff --git a/R/read_params.R b/R/read_params.R index d2a4b36..3dd7556 100644 --- a/R/read_params.R +++ b/R/read_params.R @@ -8,7 +8,7 @@ #' to ensure that up-to-date params are always loaded. #' #' @param stage_path relative path to stage directory from project root -#' @param return_list returns a list if TRUE, by default it return `dsoParams` class which is a list with secure access +#' @param return_list returns a list if TRUE, by default it return `dsoParams` class which is a list with secure access #' #' @return parameters as list of list as `dsoParams` or conventional list when `return_list` is set. #' @importFrom yaml read_yaml @@ -19,11 +19,11 @@ read_params <- function(stage_path, return_list = FALSE) { result <- system2(DSO_EXEC, c("get-config", shQuote(stage_path)), stdout = tmp_config_file) yaml <- read_yaml(tmp_config_file) unlink(tmp_config_file) - - if(return_list) { - yaml + + if (return_list) { + yaml } else { - dsoParams(yaml) + dsoParams(yaml) } } @@ -63,6 +63,7 @@ set_stage <- function(stage_path) { #' Get the absolute path to the current stage. The current stage can be set using set_stage() #' by providing the relative path of the stage from the project root directory. #' to the stage dir. +#' @param ... additional parts of the path appended to the stage path using `file.path` #' @export #' @return absolute path to stage stage_here <- function(...) { diff --git a/R/safe_get.R b/R/safe_get.R index df6b0da..c0dd8ab 100644 --- a/R/safe_get.R +++ b/R/safe_get.R @@ -4,63 +4,72 @@ #' @details #' Converts a nested list call to dollar format while resolving variables #' in the environment specified in `env` (by default the caller_env()) -#' +#' #' input_string <- 'CONFIG[[a]][[\"foo\"]]$bar[[\'no\']][[b]]$level' #' a <- "test" #' b <- "bla" -#' print(.convert_list_call_to_dollar_format('CONFIG[[a]][[\"foo\"]]$bar[["no"]][["further"]]$level')) -#' +#' print(.convert_list_call_to_dollar_format('CONFIG[[a]][[\"foo\"]]$bar[["no"]][["further"]]$level')) +#' #' @param input_string input string from deparsed function call -#' +#' #' @param env environment which is used to resolve variables in the list call #' #' @importFrom stringr str_match_all #' @importFrom stringr str_replace #' @importFrom stringr coll #' @importFrom rlang caller_env +#' #' @return converted nested list call in $ format .convert_list_call_to_dollar_format <- function(input_string, env = caller_env()) { - - if(!is.null(input_string) && !is.na(input_string) && !is.character(input_string)) + if (!is.null(input_string) && !is.na(input_string) && !is.character(input_string)) { stop("input_string is not a non-NULL non-NA character string") - + } + # Remove any whitespace x <- gsub("\\s", "", input_string) - + # Replace all $[[\"...\"] x <- gsub('\\[\\[\\"(.+?)\\"\\]\\]', "\\$\\1", x) - + # Replace all $[["..."] x <- gsub('\\[\\["(.+?)"\\]\\]', "\\$\\1", x) - + # Replace all $[[\'...\'] x <- gsub("\\[\\[\\'(.+?)\\'\\]\\]", "\\$\\1", x) - + # Replace all $[['...'] x <- gsub("\\[\\['(.+?)'\\]\\]", "\\$\\1", x) - - + + matches <- str_match_all(x, "\\[\\[(.*?)\\]\\]") - + # evaluates all variables in [[]] in environment specified # and returns function call as $ separated call - if(!is.null(matches) && length(matches) > 0 && nrow(matches[[1]]) > 0 ) { - for(i in 1:nrow(matches[[1]])) { - tryCatch({ - .match = matches[[1]][i,1] - .variable = matches[[1]][i,2] - - x <- str_replace(pattern = coll(.match), - replacement = paste0("$", eval(parse(text = .variable), - envir = env)), - x) - }, error = function(e) { - stop(paste0("Error when trying to evaluate variable ", - .variable," in '", x, "'.: ", e)) - }) + if (!is.null(matches) && length(matches) > 0 && nrow(matches[[1]]) > 0) { + for (i in 1:nrow(matches[[1]])) { + tryCatch( + { + .match <- matches[[1]][i, 1] + .variable <- matches[[1]][i, 2] + + x <- str_replace( + pattern = coll(.match), + replacement = paste0("$", eval(parse(text = .variable), + envir = env + )), + x + ) + }, + error = function(e) { + stop(paste0( + "Error when trying to evaluate variable ", + .variable, " in '", x, "'.: ", e + )) + } + ) } } - + return(x) } @@ -70,70 +79,75 @@ #' @description #' safe checks a nested list call and returns requested value #' @details -#' When accessing parameters stored in a list of list like `params$a$b$c`, -#' R will return `NULL` if an empty slot is accessed intentionally or +#' When accessing parameters stored in a list of list like `params$a$b$c`, +#' R will return `NULL` if an empty slot is accessed intentionally or #' by accident: e.g. `params$a$d$c` (where `d` does not exist) will return -#' in `NULL`. This can lead to unwanted behavior. -#' +#' in `NULL`. This can lead to unwanted behavior. +#' #' safe_get() will produce an error and point to the slot accessed incorrectly. -#' It can utilize other forms of access like params[["a"]]$b$c or +#' It can utilize other forms of access like params[["a"]]$b$c or #' var <- "a"; params[[a]]. Variables will be resolved from the caller_env() -#' by default, but can be changed passing through the `env` parameter. -#' +#' by default, but can be changed passing through the `env` parameter. +#' #' @param config_call nested list call #' @param env environment which is used to resolve variables in the list call #' @importFrom rlang caller_env -#' +#' #' @export #' @return content of nested variable call safe_get <- function(config_call, env = caller_env()) { if (!is.environment(env)) { stop("env is not an environment or derived from an environment") } - - # input can be a mixture of $, [[ ]], variable, etc. This + + # input can be a mixture of $, [[ ]], variable, etc. This # function converts everything into a uniform $ format while # evaluating the variables in the specified environment config_parts <- .convert_list_call_to_dollar_format( - deparse(substitute(config_call)), env = env) - + deparse(substitute(config_call)), + env = env + ) + # input checks error_prefix <- "config_call argument cannot be " - error_postfix <- ". Input could be configuration stored in list of lists, e.g. params$test$a, params[['test']][['a']], params$test[['a']] or params[[ var]]$a." - if(config_parts == "NA") + error_postfix <- ". Input could be configuration stored in list of lists, e.g. params$test$a, params[['test']][['a']], params$test[['a']] or params[[ var]]$a." + if (config_parts == "NA") { stop(paste0(error_prefix, "NA", error_postfix)) - - if(config_parts == "NULL") + } + + if (config_parts == "NULL") { stop(paste0(error_prefix, "NULL", error_postfix)) - - if(config_parts == "") + } + + if (config_parts == "") { stop(paste0(error_prefix, "empty", error_postfix)) - + } + # split the $ separated input string - config_parts <- strsplit(config_parts, "\\$")[[1]] - + config_parts <- strsplit(config_parts, "\\$")[[1]] + # remove backticks `` to get the variable names config_parts <- gsub(pattern = "^`|`$", replacement = "", config_parts) - + # the first variable is the base variable current_list <- get(config_parts[1], envir = env, inherits = FALSE) - + if (is.null(current_list)) { stop(paste0(config_parts[0], " does not exist.")) } - + # while iterating through the calls, check if the elements exist in the parent for (i in 2:length(config_parts)) { if (!exists(config_parts[[i]], envir = as.environment(current_list))) { - stop(paste0("The element '", config_parts[[i]], "' does not exist in '", paste0(config_parts[1:(i-1)], collapse = "$"), "'.")) + stop(paste0("The element '", config_parts[[i]], "' does not exist in '", paste0(config_parts[1:(i - 1)], collapse = "$"), "'.")) } current_list <- current_list[[config_parts[[i]]]] } - + # return cannot be NULL if (is.null(current_list)) { stop(paste0("The call '", paste0(config_parts, collapse = "$"), "' is NULL.")) } - + return(current_list) } diff --git a/man/as.list-dsoParams-method.Rd b/man/as.list-dsoParams-method.Rd new file mode 100644 index 0000000..96cd9e1 --- /dev/null +++ b/man/as.list-dsoParams-method.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-dsoParams.R +\name{as.list,dsoParams-method} +\alias{as.list,dsoParams-method} +\title{Custom as.list method for dsoParams class} +\usage{ +\S4method{as.list}{dsoParams}(x) +} +\arguments{ +\item{x}{dsoParams object} +} +\value{ +A list +} +\description{ +Custom as.list method for dsoParams class +} diff --git a/man/cash-.dsoParams.Rd b/man/cash-.dsoParams.Rd index 56474b4..5a6e88d 100644 --- a/man/cash-.dsoParams.Rd +++ b/man/cash-.dsoParams.Rd @@ -7,6 +7,11 @@ it cannot return NULL when call does not exist} \usage{ \method{$}{dsoParams}(x, name) } +\arguments{ +\item{x}{dsoParams object} + +\item{name}{field name} +} \description{ overriding the the $ operator to add secure list calling so that it cannot return NULL when call does not exist diff --git a/man/compile_config.Rd b/man/compile_config.Rd index 9eea568..5f57809 100644 --- a/man/compile_config.Rd +++ b/man/compile_config.Rd @@ -6,6 +6,9 @@ \usage{ compile_config(dir = getwd()) } +\arguments{ +\item{dir}{directory (including subdirectories and relevant parent files) to compile. By default compiles the current working directory.} +} \description{ Run dso compile-config } diff --git a/man/dsoParams-class.Rd b/man/dsoParams-class.Rd new file mode 100644 index 0000000..c8f3354 --- /dev/null +++ b/man/dsoParams-class.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-dsoParams.R +\docType{class} +\name{dsoParams-class} +\alias{dsoParams-class} +\title{dsoParams class} +\description{ +dsoParams class +} +\section{Slots}{ + +\describe{ +\item{\code{params}}{A list of lists containing parameters} +}} + diff --git a/man/print.dsoParams.Rd b/man/print.dsoParams.Rd index d5a7f5f..000e8f2 100644 --- a/man/print.dsoParams.Rd +++ b/man/print.dsoParams.Rd @@ -4,7 +4,12 @@ \alias{print.dsoParams} \title{Custom print method for dsoParams class} \usage{ -\method{print}{dsoParams}(object, ...) +\method{print}{dsoParams}(x, ...) +} +\arguments{ +\item{x}{dsoParams object} + +\item{...}{additional parameters are ignored} } \description{ Custom print method for dsoParams class diff --git a/man/safe_get.Rd b/man/safe_get.Rd index 54b42ae..4c4c144 100644 --- a/man/safe_get.Rd +++ b/man/safe_get.Rd @@ -18,13 +18,13 @@ content of nested variable call safe checks a nested list call and returns requested value } \details{ -When accessing parameters stored in a list of list like `params$a$b$c`, -R will return `NULL` if an empty slot is accessed intentionally or +When accessing parameters stored in a list of list like `params$a$b$c`, +R will return `NULL` if an empty slot is accessed intentionally or by accident: e.g. `params$a$d$c` (where `d` does not exist) will return -in `NULL`. This can lead to unwanted behavior. +in `NULL`. This can lead to unwanted behavior. safe_get() will produce an error and point to the slot accessed incorrectly. -It can utilize other forms of access like params[["a"]]$b$c or +It can utilize other forms of access like params[["a"]]$b$c or var <- "a"; params[[a]]. Variables will be resolved from the caller_env() by default, but can be changed passing through the `env` parameter. } diff --git a/man/show-dsoParams-method.Rd b/man/show-dsoParams-method.Rd index ea4bc26..cdac90b 100644 --- a/man/show-dsoParams-method.Rd +++ b/man/show-dsoParams-method.Rd @@ -6,6 +6,9 @@ \usage{ \S4method{show}{dsoParams}(object) } +\arguments{ +\item{object}{dsoParams object} +} \description{ Custom show method for dsoParams class } diff --git a/man/stage_here.Rd b/man/stage_here.Rd index bf96538..8bf5e7b 100644 --- a/man/stage_here.Rd +++ b/man/stage_here.Rd @@ -6,6 +6,9 @@ \usage{ stage_here(...) } +\arguments{ +\item{...}{additional parts of the path appended to the stage path using `file.path`} +} \value{ absolute path to stage } diff --git a/man/sub-sub-.dsoParams.Rd b/man/sub-sub-.dsoParams.Rd index 47d4abf..de444be 100644 --- a/man/sub-sub-.dsoParams.Rd +++ b/man/sub-sub-.dsoParams.Rd @@ -7,6 +7,13 @@ it cannot return NULL when call does not exist} \usage{ \method{[[}{dsoParams}(x, i, ...) } +\arguments{ +\item{x}{dsoParams object} + +\item{i}{index for `[[` operator} + +\item{...}{additional arguments passed to the `[[` operator} +} \description{ And the [[ operator: to add secure list calling so that it cannot return NULL when call does not exist diff --git a/tests/testthat/test-class-dsoParams.R b/tests/testthat/test-class-dsoParams.R index ff90bc1..6a07f2b 100644 --- a/tests/testthat/test-class-dsoParams.R +++ b/tests/testthat/test-class-dsoParams.R @@ -2,16 +2,16 @@ test_that("dsoParams() creation of dsoParams objects", { x <- dsoParams() expect_s3_class(x, "dsoParams") expect_equal(length(x), 0) - + y <- list() y$a <- list() y$b <- "b" y$a$c <- "c" + z <- dsoParams(y) - + expect_s3_class(z, "dsoParams") expect_s3_class(z$a, "dsoParams") - }) @@ -29,7 +29,8 @@ test_that("dsoParams() should retrieve value expected", { var_b <- "b" var_c <- "c" params <- dsoParams(params) - + + # styler: off expect_equal(params$a, "bla") expect_equal(params[[var_a]], "bla") expect_equal(params$b$c, "blub") @@ -40,6 +41,7 @@ test_that("dsoParams() should retrieve value expected", { expect_equal(params[[var_b]][["c"]], "blub") expect_equal(params[["b"]][[var_c]], "blub") expect_equal(params[[var_b]][[var_c]], "blub") + # styler: on }) @@ -53,7 +55,8 @@ test_that("access to dsoParams() with $ and [[", { var_c <- "c" var_z <- "z" params <- dsoParams(params) - + + # styler: off expect_error(params$z, "does not exist") expect_error(params[[var_z]], "does not exist") expect_error(params$z$c, "does not exist") @@ -73,6 +76,7 @@ test_that("access to dsoParams() with $ and [[", { expect_error(params[["b"]][[var_z]], "does not exist") expect_error(params[[var_b]][[var_z]], "does not exist") expect_error(params[[var_z]][[var_c]], "does not exist") + # styler: on }) test_that("dsoParams: as.list() convertion", { @@ -84,7 +88,7 @@ test_that("dsoParams: as.list() convertion", { y$a$e <- list() y$a$e$f <- "f" z <- dsoParams(y) - + l_z <- as.list(z) expect_type(l_z, "list") expect_equal(class(l_z), "list") @@ -99,8 +103,7 @@ test_that("dsoParams: as.data.frame() convertion", { y$a$e <- list() y$a$e$f <- "f" z <- dsoParams(y) - + l_z <- as.data.frame(z) expect_s3_class(l_z, "data.frame") }) - diff --git a/tests/testthat/test-safe_get.R b/tests/testthat/test-safe_get.R index d940e4a..49a63a0 100644 --- a/tests/testthat/test-safe_get.R +++ b/tests/testthat/test-safe_get.R @@ -12,7 +12,8 @@ test_that("safe_get() should retrieve value expected", { var_a <- "a" var_b <- "b" var_c <- "c" - + + # styler: off expect_equal(safe_get(params$a), "bla") expect_equal(safe_get(params[[var_a]]), "bla") expect_equal(safe_get(params$b$c), "blub") @@ -23,6 +24,7 @@ test_that("safe_get() should retrieve value expected", { expect_equal(safe_get(params[[var_b]][["c"]]), "blub") expect_equal(safe_get(params[["b"]][[var_c]]), "blub") expect_equal(safe_get(params[[var_b]][[var_c]]), "blub") + # styler: on }) @@ -35,7 +37,8 @@ test_that("safe_get() should raise error when call does not exist", { var_b <- "b" var_c <- "c" var_z <- "z" - + + # styler: off expect_error(safe_get(params$z), "does not exist") expect_error(safe_get(params[[var_z]]), "does not exist") expect_error(safe_get(params$z$c), "does not exist") @@ -55,5 +58,5 @@ test_that("safe_get() should raise error when call does not exist", { expect_error(safe_get(params[["b"]][[var_z]]), "does not exist") expect_error(safe_get(params[[var_b]][[var_z]]), "does not exist") expect_error(safe_get(params[[var_z]][[var_c]]), "does not exist") + # styler: on }) -