Skip to content

Commit

Permalink
feat: added proper support for adding attributes via data.frames (#1716)
Browse files Browse the repository at this point in the history
  • Loading branch information
schochastics authored Feb 26, 2025
1 parent 07e0ccb commit d886780
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 249 deletions.
49 changes: 24 additions & 25 deletions R/attributes.R
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ graph.attributes <- function(graph) {
"graph.attributes<-" <- function(graph, value) {
ensure_igraph(graph)
assert_named_list(value)
if (inherits(value, "data.frame")) {
value <- as.list(value)
}

.Call(R_igraph_mybracket2_set, graph, igraph_t_idx_attr, igraph_attr_idx_graph, value)
}
Expand Down Expand Up @@ -487,12 +490,8 @@ i_set_vertex_attr <- function(graph, name, index = V(graph), value, check = TRUE
} else if (length(value) == length(index)) {
value_in <- unname(value)
} else {
stop(
"Length of new attribute value must be ",
if (length(index) != 1) "1 or ",
length(index),
", the number of target vertices, not ",
length(value)
cli::cli_abort(
"Length of new attribute value must be {if (length(index) != 1) '1 or '}{length(index)}, the number of target vertices, not {length(value)}."
)
}

Expand Down Expand Up @@ -541,16 +540,19 @@ set_value_at <- function(value, idx, length_out) {
ensure_igraph(graph)

assert_named_list(value)
if (inherits(value, "data.frame")) {
value <- as.list(value)
}

if (!all(lengths(value) == length(index))) {
stop("Invalid attribute value length, must match number of vertices")
cli::cli_abort("Invalid attribute value length, must match number of vertices.")
}

if (!missing(index)) {
index <- as_igraph_vs(graph, index)

if (anyDuplicated(index) || anyNA(index)) {
stop("Invalid vertices in index")
cli::cli_abort("{.arg index} contains duplicated vertices or NAs.")
}
}

Expand Down Expand Up @@ -698,12 +700,8 @@ i_set_edge_attr <- function(graph, name, index = E(graph), value, check = TRUE)
} else if (length(value) == length(index)) {
value_in <- unname(value)
} else {
stop(
"Length of new attribute value must be ",
if (length(index) != 1) "1 or ",
length(index),
", the number of target edges, not ",
length(value)
cli::cli_abort(
"Length of new attribute value must be {if (length(index) != 1) '1 or '}{length(index)}, the number of target edges, not {length(value)}."
)
}

Expand Down Expand Up @@ -741,15 +739,18 @@ edge.attributes <- function(graph, index = E(graph)) {
ensure_igraph(graph)

assert_named_list(value)
if (inherits(value, "data.frame")) {
value <- as.list(value)
}

if (any(sapply(value, length) != length(index))) {
stop("Invalid attribute value length, must match number of edges")
cli::cli_abort("Invalid attribute value length, must match number of edges")
}

if (!missing(index)) {
index <- as_igraph_es(graph, index)
if (any(duplicated(index)) || any(is.na(index))) {
stop("Invalid edges in index")
cli::cli_abort("{.arg index} contains duplicated edges or NAs.")
}
}

Expand Down Expand Up @@ -855,7 +856,7 @@ delete_graph_attr <- function(graph, name) {

name <- as.character(name)
if (!name %in% graph_attr_names(graph)) {
stop("No such graph attribute: ", name)
cli::cli_abort("No graph attribute {.arg {name}} found.")
}

gattr <- .Call(R_igraph_mybracket2, graph, igraph_t_idx_attr, igraph_attr_idx_graph)
Expand Down Expand Up @@ -884,7 +885,7 @@ delete_vertex_attr <- function(graph, name) {

name <- as.character(name)
if (!name %in% vertex_attr_names(graph)) {
stop("No such vertex attribute: ", name)
cli::cli_abort("No vertex attribute {.arg {name}} found.")
}

vattr <- .Call(R_igraph_mybracket2, graph, igraph_t_idx_attr, igraph_attr_idx_vertex)
Expand Down Expand Up @@ -913,7 +914,7 @@ delete_edge_attr <- function(graph, name) {

name <- as.character(name)
if (!name %in% edge_attr_names(graph)) {
stop("No such edge attribute: ", name)
cli::cli_abort("No edge attribute {.arg {name}} found.")
}

eattr <- .Call(R_igraph_mybracket2, graph, igraph_t_idx_attr, igraph_attr_idx_edge)
Expand Down Expand Up @@ -1020,7 +1021,7 @@ igraph.i.attribute.combination <- function(comb) {
if (any(!sapply(comb, function(x) {
is.function(x) || (is.character(x) && length(x) == 1)
}))) {
stop("Attribute combination element must be a function or character scalar")
cli::cli_abort("Attribute combination element must be a function or character scalar.")
}
if (is.null(names(comb))) {
names(comb) <- rep("", length(comb))
Expand All @@ -1041,7 +1042,7 @@ igraph.i.attribute.combination <- function(comb) {
)
x <- pmatch(tolower(x), known[, 1])
if (is.na(x)) {
stop("Unknown/unambigous attribute combination specification")
cli::cli_abort("Unknown/unambigous attribute combination specification.")
}
known[, 2][x]
}
Expand Down Expand Up @@ -1185,17 +1186,15 @@ NULL
}

assert_named_list <- function(value) {
error_msg <- "{.arg value} must be a named list with unique names"

if (!is.list(value)) {
rlang::abort(error_msg)
cli::cli_abort("{.arg value} must be a named list with unique names")
}

if (length(value) == 0) {
return()
}

if (!rlang::is_named(value) || anyDuplicated(names(value)) > 0) {
rlang::abort(error_msg)
cli::cli_abort("{.arg value} must be a named list with unique names")
}
}
56 changes: 56 additions & 0 deletions tests/testthat/_snaps/attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# error messages work

Code
set_vertex_attr(g, "test", value = c(1, 2))
Condition
Error in `i_set_vertex_attr()`:
! Length of new attribute value must be 1 or 5, the number of target vertices, not 2.

---

Code
set_edge_attr(g, "test", value = c(1, 2))
Condition
Error in `i_set_edge_attr()`:
! Length of new attribute value must be 1 or 10, the number of target edges, not 2.

---

Code
delete_graph_attr(g, "a")
Condition
Error in `delete_graph_attr()`:
! No graph attribute `a` found.

---

Code
delete_vertex_attr(g, "a")
Condition
Error in `delete_vertex_attr()`:
! No vertex attribute `a` found.

---

Code
delete_edge_attr(g, "a")
Condition
Error in `delete_edge_attr()`:
! No edge attribute `a` found.

---

Code
assert_named_list("a")
Condition
Error in `assert_named_list()`:
! `value` must be a named list with unique names

---

Code
assert_named_list(list("a", "b"))
Condition
Error in `assert_named_list()`:
! `value` must be a named list with unique names

Loading

0 comments on commit d886780

Please sign in to comment.