From 9a3ddd7998ec2acc692c76b04398452cd9824d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Tue, 22 Jul 2025 15:40:45 +0200 Subject: [PATCH 1/3] chore: create `check_vertex()` --- R/aaa-auto.R | 132 ++++++++------------------------ R/interface.R | 8 +- R/utils-vertex.R | 20 +++++ tests/testthat/_snaps/flow.md | 16 ++-- tests/testthat/test-interface.R | 2 +- tools/stimulus/types-RR.yaml | 8 +- 6 files changed, 66 insertions(+), 120 deletions(-) create mode 100644 R/utils-vertex.R diff --git a/R/aaa-auto.R b/R/aaa-auto.R index 1de6e7c5ff4..aa59fc9bb67 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -63,13 +63,9 @@ get_all_eids_between_impl <- function(graph, from, to, directed=TRUE) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (length(to) == 0) { - stop("No vertex was specified") - } + check_vertex(to) directed <- as.logical(directed) on.exit( .Call(R_igraph_finalizer) ) @@ -666,13 +662,9 @@ are_adjacent_impl <- function(graph, v1, v2) { # Argument checks ensure_igraph(graph) v1 <- as_igraph_vs(graph, v1) - if (length(v1) == 0) { - stop("No vertex was specified") - } + check_vertex(v1) v2 <- as_igraph_vs(graph, v2) - if (length(v2) == 0) { - stop("No vertex was specified") - } + check_vertex(v2) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -685,13 +677,9 @@ get_shortest_path_impl <- function(graph, from, to, mode=c("out", "in", "all", " # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (length(to) == 0) { - stop("No vertex was specified") - } + check_vertex(to) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -710,13 +698,9 @@ get_shortest_path_bellman_ford_impl <- function(graph, from, to, weights=NULL, m # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (length(to) == 0) { - stop("No vertex was specified") - } + check_vertex(to) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -743,13 +727,9 @@ get_shortest_path_dijkstra_impl <- function(graph, from, to, weights=NULL, mode= # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (length(to) == 0) { - stop("No vertex was specified") - } + check_vertex(to) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -809,13 +789,9 @@ get_k_shortest_paths_impl <- function(graph, from, to, ..., k, weights=NULL, mod } k <- as.numeric(k) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (length(to) == 0) { - stop("No vertex was specified") - } + check_vertex(to) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -834,13 +810,9 @@ get_widest_path_impl <- function(graph, from, to, weights=NULL, mode=c("out", "i # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (length(to) == 0) { - stop("No vertex was specified") - } + check_vertex(to) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -867,13 +839,9 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights=NULL, mode=c # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } + check_vertex(to) if (!is.null(weights) && any(!is.na(weights))) { weights <- as.numeric(weights) } else { @@ -1865,9 +1833,7 @@ pseudo_diameter_impl <- function(graph, start.vid, directed=TRUE, unconnected=TR # Argument checks ensure_igraph(graph) start.vid <- as_igraph_vs(graph, start.vid) - if (length(start.vid) == 0) { - stop("No vertex was specified") - } + check_vertex(start.vid) directed <- as.logical(directed) unconnected <- as.logical(unconnected) @@ -1890,9 +1856,7 @@ pseudo_diameter_dijkstra_impl <- function(graph, weights=NULL, start.vid, direct weights <- NULL } start.vid <- as_igraph_vs(graph, start.vid) - if (length(start.vid) == 0) { - stop("No vertex was specified") - } + check_vertex(start.vid) directed <- as.logical(directed) unconnected <- as.logical(unconnected) @@ -1937,9 +1901,7 @@ random_walk_impl <- function(graph, start, steps, weights=NULL, mode=c("out", "i weights <- NULL } start <- as_igraph_vs(graph, start) - if (length(start) == 0) { - stop("No vertex was specified") - } + check_vertex(start) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) steps <- as.numeric(steps) stuck <- switch(igraph.match.arg(stuck), "error" = 0L, "return" = 1L) @@ -2072,9 +2034,7 @@ bfs_simple_impl <- function(graph, root, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) root <- as_igraph_vs(graph, root) - if (length(root) == 0) { - stop("No vertex was specified") - } + check_vertex(root) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -2941,13 +2901,9 @@ maxflow_impl <- function(graph, source, target, capacity=NULL) { # Argument checks ensure_igraph(graph) source <- as_igraph_vs(graph, source) - if (length(source) == 0) { - stop("No vertex was specified") - } + check_vertex(source) target <- as_igraph_vs(graph, target) - if (length(target) == 0) { - stop("No vertex was specified") - } + check_vertex(target) if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) { capacity <- E(graph)$capacity } @@ -3016,9 +2972,7 @@ dominator_tree_impl <- function(graph, root, mode=c("out", "in", "all", "total") # Argument checks ensure_igraph(graph) root <- as_igraph_vs(graph, root) - if (length(root) == 0) { - stop("No vertex was specified") - } + check_vertex(root) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) @@ -3034,13 +2988,9 @@ all_st_cuts_impl <- function(graph, source, target) { # Argument checks ensure_igraph(graph) source <- as_igraph_vs(graph, source) - if (length(source) == 0) { - stop("No vertex was specified") - } + check_vertex(source) target <- as_igraph_vs(graph, target) - if (length(target) == 0) { - stop("No vertex was specified") - } + check_vertex(target) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3058,13 +3008,9 @@ all_st_mincuts_impl <- function(graph, source, target, capacity=NULL) { # Argument checks ensure_igraph(graph) source <- as_igraph_vs(graph, source) - if (length(source) == 0) { - stop("No vertex was specified") - } + check_vertex(source) target <- as_igraph_vs(graph, target) - if (length(target) == 0) { - stop("No vertex was specified") - } + check_vertex(target) if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) { capacity <- E(graph)$capacity } @@ -3783,9 +3729,7 @@ fundamental_cycles_impl <- function(graph, start=NULL, bfs.cutoff=-1, weights=NU # Argument checks ensure_igraph(graph) if (!is.null(start)) start <- as_igraph_vs(graph, start) - if (length(start) == 0) { - stop("No vertex was specified") - } + check_vertex(start) bfs.cutoff <- as.numeric(bfs.cutoff) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight @@ -3917,9 +3861,7 @@ random_spanning_tree_impl <- function(graph, vid=0) { # Argument checks ensure_igraph(graph) if (!is.null(vid)) vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") - } + check_vertex(vid) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -3962,9 +3904,7 @@ deterministic_optimal_imitation_impl <- function(graph, vid, optimality=c("maxim # Argument checks ensure_igraph(graph) vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") - } + check_vertex(vid) optimality <- switch(igraph.match.arg(optimality), "minimum"=0L, "maximum"=1L) strategies <- as.numeric(strategies) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -4003,9 +3943,7 @@ roulette_wheel_imitation_impl <- function(graph, vid, is.local, quantities, stra # Argument checks ensure_igraph(graph) vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") - } + check_vertex(vid) is.local <- as.logical(is.local) strategies <- as.numeric(strategies) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -4021,9 +3959,7 @@ stochastic_imitation_impl <- function(graph, vid, algo, quantities, strategies, # Argument checks ensure_igraph(graph) vid <- as_igraph_vs(graph, vid) - if (length(vid) == 0) { - stop("No vertex was specified") - } + check_vertex(vid) strategies <- as.numeric(strategies) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -4038,9 +3974,7 @@ vertex_path_from_edge_path_impl <- function(graph, start=NULL, edge.path, mode=c # Argument checks ensure_igraph(graph) if (!is.null(start)) start <- as_igraph_vs(graph, start) - if (length(start) == 0) { - stop("No vertex was specified") - } + check_vertex(start) edge.path <- as_igraph_es(graph, edge.path) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) diff --git a/R/interface.R b/R/interface.R index e5317fd54ed..fcc4c83ca68 100644 --- a/R/interface.R +++ b/R/interface.R @@ -354,9 +354,7 @@ neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) { mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3) } v <- as_igraph_vs(graph, v) - if (length(v) == 0) { - stop("No vertex was specified") - } + check_vertex(v) on.exit(.Call(R_igraph_finalizer)) res <- .Call(R_igraph_neighbors, graph, v - 1, as.numeric(mode)) + 1L @@ -393,9 +391,7 @@ incident <- function(graph, v, mode = c("all", "out", "in", "total")) { mode <- 1 } v <- as_igraph_vs(graph, v) - if (length(v) == 0) { - stop("No vertex was specified") - } + check_vertex(v) on.exit(.Call(R_igraph_finalizer)) res <- .Call(R_igraph_incident, graph, v - 1, as.numeric(mode)) + 1L diff --git a/R/utils-vertex.R b/R/utils-vertex.R new file mode 100644 index 00000000000..d2ad59068ea --- /dev/null +++ b/R/utils-vertex.R @@ -0,0 +1,20 @@ +check_vertex <- function(arg, call = rlang::caller_env()) { + arg_name <- rlang::caller_arg(arg) + ok <- 0 == + (exit_code <- .standalone_types_check_dot_call( + ffi_standalone_check_number_1.0.7, + x = arg, + allow_decimal = FALSE, + min = 0, + max = NULL, + allow_infinite = FALSE, + allow_na = FALSE, + allow_null = FALSE + )) + + if (!ok) { + cli::cli_abort( + "Can't find vertex corresponding to {.arg {arg_name}}." + ) + } +} diff --git a/tests/testthat/_snaps/flow.md b/tests/testthat/_snaps/flow.md index 01e1e52f55a..2d4c8757566 100644 --- a/tests/testthat/_snaps/flow.md +++ b/tests/testthat/_snaps/flow.md @@ -3,32 +3,32 @@ Code st_cuts(g_path, source = "a", target = NULL) Condition - Error in `st_cuts()`: - ! No vertex was specified + Error in `check_vertex()`: + ! Can't find vertex corresponding to `target`. --- Code st_cuts(g_path, source = NULL, target = "a") Condition - Error in `st_cuts()`: - ! No vertex was specified + Error in `check_vertex()`: + ! Can't find vertex corresponding to `source`. --- Code st_min_cuts(g_path, source = "a", target = NULL) Condition - Error in `st_min_cuts()`: - ! No vertex was specified + Error in `check_vertex()`: + ! Can't find vertex corresponding to `target`. --- Code st_min_cuts(g_path, source = NULL, target = "a") Condition - Error in `st_min_cuts()`: - ! No vertex was specified + Error in `check_vertex()`: + ! Can't find vertex corresponding to `source`. # vertex_connectivity error works diff --git a/tests/testthat/test-interface.R b/tests/testthat/test-interface.R index d1f5b10ecc1..5b36b8646ec 100644 --- a/tests/testthat/test-interface.R +++ b/tests/testthat/test-interface.R @@ -99,7 +99,7 @@ test_that("neighbors works", { test_that("neighbors prints an error for an empty input vector", { g <- make_tree(10) - expect_error(neighbors(g, numeric()), "No vertex was specified") + expect_error(neighbors(g, numeric()), "Can't find vertex") }) diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index 35d208da901..6e0722ea675 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -97,9 +97,7 @@ VERTEX: CALL: '%I%-1' INCONV: |- %I% <- as_igraph_vs(%I1%, %I%) - if (length(%I%) == 0) { - stop("No vertex was specified") - } + check_vertex(%I%) OUTCONV: OUT: |- if (igraph_opt("return.vs.es")) { @@ -110,9 +108,7 @@ VERTEX_ROOT: CALL: '%I%-1' INCONV: |- %I% <- as_igraph_vs(%I1%, %I%) - if (length(%I%) == 0) { - stop("No vertex was specified") - } + check_vertex(%I%) OUTCONV: OUT: |- if (igraph_opt("return.vs.es") && vcount(%I1%) != 0) { From e036512d1ea03bd1dce73f9ebceb3671ce467b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Wed, 27 Aug 2025 11:24:21 +0200 Subject: [PATCH 2/3] fix --- R/utils-vertex.R | 3 ++- tests/testthat/_snaps/flow.md | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/R/utils-vertex.R b/R/utils-vertex.R index d2ad59068ea..757a518ee97 100644 --- a/R/utils-vertex.R +++ b/R/utils-vertex.R @@ -14,7 +14,8 @@ check_vertex <- function(arg, call = rlang::caller_env()) { if (!ok) { cli::cli_abort( - "Can't find vertex corresponding to {.arg {arg_name}}." + "Can't find vertex corresponding to {.arg {arg_name}}.", + call = call ) } } diff --git a/tests/testthat/_snaps/flow.md b/tests/testthat/_snaps/flow.md index 2d4c8757566..566deaedacd 100644 --- a/tests/testthat/_snaps/flow.md +++ b/tests/testthat/_snaps/flow.md @@ -3,7 +3,7 @@ Code st_cuts(g_path, source = "a", target = NULL) Condition - Error in `check_vertex()`: + Error in `st_cuts()`: ! Can't find vertex corresponding to `target`. --- @@ -11,7 +11,7 @@ Code st_cuts(g_path, source = NULL, target = "a") Condition - Error in `check_vertex()`: + Error in `st_cuts()`: ! Can't find vertex corresponding to `source`. --- @@ -19,7 +19,7 @@ Code st_min_cuts(g_path, source = "a", target = NULL) Condition - Error in `check_vertex()`: + Error in `st_min_cuts()`: ! Can't find vertex corresponding to `target`. --- @@ -27,7 +27,7 @@ Code st_min_cuts(g_path, source = NULL, target = "a") Condition - Error in `check_vertex()`: + Error in `st_min_cuts()`: ! Can't find vertex corresponding to `source`. # vertex_connectivity error works From fe4ac3de21b07e8ac87a95ed047c71863f85e6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Wed, 27 Aug 2025 11:36:16 +0200 Subject: [PATCH 3/3] yes --- R/aaa-auto.R | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/R/aaa-auto.R b/R/aaa-auto.R index e5884d6ceab..eba1cf57637 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -952,9 +952,7 @@ get_all_shortest_paths_impl <- function(graph, from, to, mode=c("out", "in", "al # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -974,9 +972,7 @@ get_all_shortest_paths_dijkstra_impl <- function(graph, from, to=V(graph), weigh # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight @@ -1027,9 +1023,7 @@ get_all_simple_paths_impl <- function(graph, from, to=V(graph), cutoff=-1, mode= # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) - if (length(from) == 0) { - stop("No vertex was specified") - } + check_vertex(from) to <- as_igraph_vs(graph, to) cutoff <- as.numeric(cutoff) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) @@ -1109,7 +1103,6 @@ get_widest_paths_impl <- function(graph, from, to=V(graph), weights=NULL, mode=c from <- as_igraph_vs(graph, from) check_vertex(from) to <- as_igraph_vs(graph, to) - check_vertex(to) if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { weights <- E(graph)$weight } @@ -2941,9 +2934,7 @@ layout_star_impl <- function(graph, center=V(graph)[1], order=NULL) { # Argument checks ensure_igraph(graph) center <- as_igraph_vs(graph, center) - if (length(center) == 0) { - stop("No vertex was specified") - } + check_vertex(center) if (!is.null(order)) order <- as.numeric(order)-1 on.exit( .Call(R_igraph_finalizer) ) @@ -4041,9 +4032,7 @@ rooted_product_impl <- function(g1, g2, root) { ensure_igraph(g1) ensure_igraph(g2) root <- as_igraph_vs(g2, root) - if (length(root) == 0) { - stop("No vertex was specified") - } + check_vertex(root) on.exit( .Call(R_igraph_finalizer) ) # Function call @@ -4146,13 +4135,9 @@ st_mincut_impl <- function(graph, source, target, capacity=NULL) { # Argument checks ensure_igraph(graph) source <- as_igraph_vs(graph, source) - if (length(source) == 0) { - stop("No vertex was specified") - } + check_vertex(source) target <- as_igraph_vs(graph, target) - if (length(target) == 0) { - stop("No vertex was specified") - } + check_vertex(target) if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) { capacity <- E(graph)$capacity }