Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List as is #33

Merged
merged 19 commits into from
Sep 3, 2024
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
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: pacta.workflow.utils
Title: Utility functions for PACTA workflows
Version: 0.0.0.9012
Version: 0.0.0.9013
Authors@R:
c(person(given = "Alex",
family = "Axthelm",
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export(git_tag_info)
export(inherit_params)
export(is_git_path)
export(merge_lists)
export(modify_list_element)
export(modify_single_list_element)
export(parse_params)
export(parse_raw_params)
importFrom(logger,log_debug)
Expand Down
28 changes: 26 additions & 2 deletions R/export_manifest.R
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,20 @@ create_manifest <- function(
return(manifest_list)
}

# Check that arguments are nicely coercible to JSON. called for side effect of
# `stop` if not.
#' check_arg_type
#'
#' Check that arguments are nicely coercible to JSON. Primarily a check that
#' lists are composed of simple types (other lists, characters,
#' numeric/integers, or logicals). Called for side effect of `stop` if not.
#'
#' @param arg object to check. Lists will be checked recursively, and must be
#' named.
#' @return the same object, unchanged. Function will throw an error if objects
#' are not simple
check_arg_type <- function(arg) {
log_trace("Checking argument type")
# remove AsIs class if necessary
arg <- un_asis(arg)
if (inherits(arg, "list")) {
if (
length(arg) != length(names(arg)) ||
Expand Down Expand Up @@ -113,3 +123,17 @@ check_arg_type <- function(arg) {
}
return(arg)
}

#' un_asis
#'
#' Remove AsIs class from object
#'
#' @param x an object (with the `AsIs` class)
#' @return the same object, without AsIs class
un_asis <- function(x) {
if (inherits(x, "AsIs")) {
log_trace("Removing AsIs class from object")
class(x) <- class(x)[-match("AsIs", class(x))]
}
return(x)
}
84 changes: 84 additions & 0 deletions R/modify_list_element.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#' modify_list_element
#'
#' Apply a function to a one or more elements of a list, given the positions of
#' the elements.
#'
#' @param x List to modify
#' @param positions (List or vector) Position of elements to modify, as a
#' vector of indices
#' @param function_to_apply Function to apply to elements
#' @return modified list
#' @examples
# nolint start
#' test_list <- list(a = 1L, b = list(ba = 2L, bb = 2.2), c = "a")
#' results <- modify_list_element(
#' x = test_list,
#' position = list(
#' c("b", "bb"),
#' "a"
#' ),
#' function_to_apply = I
#' )
#' results
# nolint end
#' @export
modify_list_element <- function(
x,
positions,
function_to_apply
) {
# cast as list, if not already (if a simple vector was passed in)
if (!is.list(positions)) {
positions <- list(positions)
}
for (position in positions) {
x <- modify_single_list_element(
x = x,
position = position,
function_to_apply = function_to_apply
)
}
return(x)
}

#' modify_single_list_element
#'
#' Apply a function to a single element of a list, givin a vector of list
#' indices.
#'
#' @param x List to modify
#' @param position Position of element to modify, as a vector of indices
#' @param function_to_apply Function to apply to element
#' @return modified list
#' @examples
# nolint start
#' test_list <- list(a = 1L, b = list(ba = 2L, bb = 2.2), c = "a")
#' results <- modify_single_list_element(
#' x = test_list,
#' position = c("b", "bb"),
#' function_to_apply = I
#' )
#' results
# nolint end
#' @export
modify_single_list_element <- function(
x,
position,
function_to_apply
) {
if (length(position) == 1L) {
if (is.null(x[[position[[1L]]]])) {
log_warn("Element {position[[1L]]} is not found (NULL).")
warning("NULL list elements cannot be modified.")
} else {
x[[position]] <- function_to_apply(x[[position]])
}
} else {
x[[position[[1L]]]] <- modify_single_list_element(
x = x[[position[[1L]]]],
position = position[-1L],
function_to_apply = function_to_apply
)
}
return(invisible(x))
}
14 changes: 12 additions & 2 deletions R/parse_params.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@
#' @param inheritence_search_paths Paths to search for inherited parameters.
#' See `inherit_params`.
#' @param schema_file Path to JSON Schema file for validation.
#' @param force_array Path in params list to force casting as JSON array.
#' (Default empty)
#' @return Parsed parameters as a standard R list.
#' @export
parse_params <- function(
json,
inheritence_search_paths = NULL,
schema_file = NULL
schema_file = NULL,
force_array = list()
) {
log_trace("Parsing params.")
if (length(json) == 1L && file.exists(json)) {
log_trace("Reading params from file: {json}.}")
log_trace("Reading params from file: {json}.")
} else {
log_trace("Reading params from string.")
}
Expand All @@ -25,6 +28,13 @@ parse_params <- function(
inheritence_search_paths
)

# force array
full_params <- modify_list_element(
x = full_params,
positions = force_array,
function_to_apply = I
)

if (!is.null(schema_file)) {
if (requireNamespace("jsonvalidate", quietly = TRUE)) {
log_trace("Validating parameters.")
Expand Down
3 changes: 2 additions & 1 deletion R/parse_raw_params.R
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ parse_raw_params <- function(
params <- parse_params(
json = json,
inheritence_search_paths = inheritence_search_paths,
schema_file = schema_file
schema_file = schema_file,
force_array = c("portfolio", "files")
)

return(params)
Expand Down
21 changes: 21 additions & 0 deletions man/check_arg_type.Rd

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

35 changes: 35 additions & 0 deletions man/modify_list_element.Rd

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

31 changes: 31 additions & 0 deletions man/modify_single_list_element.Rd

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

10 changes: 9 additions & 1 deletion man/parse_params.Rd

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

17 changes: 17 additions & 0 deletions man/un_asis.Rd

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

Loading
Loading