rigraph icon indicating copy to clipboard operation
rigraph copied to clipboard

fix: Add deprecation warnings for inconsistent `mode` parameter defaults

Open Copilot opened this issue 4 months ago • 0 comments

The mode parameter defaults are inconsistent across analysis functions. distances() defaults to "all" (ignoring edge directions) while shortest_paths() defaults to "out" (respecting directions). For directed graphs, "out" is the more intuitive default.

Changes

  • Added deprecation warnings to 9 functions when mode is not explicitly specified on directed graphs:

    • Path/distance functions: distances(), eccentricity(), radius(), graph_center()
    • Neighborhood functions: ego(), ego_size(), make_ego_graph()
    • Degree functions: degree(), strength()
  • Implementation: Used lifecycle::deprecate_soft() with missing(mode) detection. Warnings only fire for directed graphs.

  • Test updates: Fixed internal code and tests to explicitly specify mode where the old "all" behavior is intended.

  • Documentation: Added breaking change notice to NEWS.md.

Example

library(igraph)
g <- make_star(10, mode = "out")

# Now warns:
distances(g)
#> Warning: The default value of `mode` will change from "all" to "out" 
#> in a future version. Please specify `mode` explicitly.

# No warning:
distances(g, mode = "all")

This implements step 2 of the migration plan: warn users before changing defaults in a future release.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cran.rstudio.com
    • Triggering command: /opt/R/4.5.1/lib/R/bin/exec/R --no-restore --no-echo --args nextArgigraph_2.2.1.9002.tar.gznextArg--as-crannextArg--timingsnextArg--no-manual (dns block)
  • packagemanager.posit.co
    • Triggering command: /opt/R/4.5.1/lib/R/bin/exec/R --no-restore --no-echo --args nextArgigraph_2.2.1.9002.tar.gznextArg--as-crannextArg--timingsnextArg--no-manual (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Inconsistent defaults for the 'mode' parameter</issue_title> <issue_description>Describe the bug

The default value of the common mode parameter differs from function to function. In some functions it's out, in others it's all. This is a usability bug, as it makes igraph unpredictable.

To reproduce

In shortest_paths(), the default is out. In the closely related distances(), the default is all.

You can use a grep line such as rg 'mode *= *c\\(.*?\\)' to see many of the defaults.

Grep output
scan.R
106:                       weighted = FALSE, mode = c("out", "in", "all"),

iterators.R
514:  .nei <- function(v, mode = c("all", "in", "out", "total")) {
539:  .innei <- function(v, mode = c("in", "all", "out", "total")) {
546:  .outnei <- function(v, mode = c("out", "all", "in", "total")) {

structural.properties.R
200:                   mode = c("all", "out", "in", "total"), loops = TRUE,
418:                      mode = c("all", "out", "in"),
506:                           mode = c("out", "all", "in"),
602:                               mode = c("out", "all", "in"),
675:subcomponent <- function(graph, v, mode = c("all", "out", "in")) {
1048:                        mode = c("default", "ratio")) {
1114:                     mode = c("all", "out", "in"), mindist = 0) {
1204:                mode = c("all", "out", "in"), mindist = 0) {
1234:                           mode = c("all", "out", "in"), mindist = 0) {
1292:coreness <- function(graph, mode = c("all", "out", "in")) {
1342:topo_sort <- function(graph, mode = c("out", "all", "in")) {
1615:bfs <- function(graph, root, mode = c("out", "in", "all", "total"),
1780:dfs <- function(graph, root, mode = c("out", "in", "all", "total"),
1889:components <- function(graph, mode = c("weak", "strong")) {
1950:unfold_tree <- function(graph, mode = c("all", "out", "in", "total"), roots) {

paths.R
58:                             mode = c("out", "in", "all", "total"),

interface.R
272:neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) {
314:incident <- function(graph, v, mode = c("all", "out", "in", "total")) {
512:                              mode = c("out", "in", "all", "total")) {
555:                           mode = c("out", "in", "all", "total")) {

flow.R
546:dominator_tree <- function(graph, root, mode = c("out", "in", "all", "total")) {

rewire.R
131:each_edge <- function(prob, loops = FALSE, multiple = FALSE, mode = c("all", "out", "in", "total")) {

components.R
27:count_components <- function(graph, mode = c("weak", "strong")) {
101:decompose <- function(graph, mode = c("weak", "strong"), max.comps = NA,

layout.R
432:                           rootlevel = numeric(), mode = c("out", "in", "all"),

conversion.R
362:as.undirected <- function(graph, mode = c("collapse", "each", "mutual"), edge.attr.comb = igraph_opt("edge.attr.comb")) {
423:                        mode = c("all", "out", "in", "total"),
463:                             mode = c("all", "out", "in", "total"),

centrality.R
257:                      mode = c("out", "in", "all", "total"), weights = NULL,
295:estimate_closeness <- function(graph, vids = V(graph), mode = c("out", "in", "all", "total"), cutoff, weights = NULL, normalized = FALSE) {

incidence.R
198:                                        mode = c("all", "out", "in", "total"),

centralization.R
150:centr_degree_tmax <- function(graph = NULL, nodes = 0, mode = c("all", "out", "in", "total"), loops = FALSE) {

aaa-auto.R
35:graph_from_adj_list <- function(adjlist, mode=c("out", "in", "all", "total"), duplicate=TRUE) {
346:harmonic_centrality <- function(graph, vids=V(graph), mode=c("out", "in", "all", "total"), weights=NULL, normalized=FALSE, cutoff=-1) {
683:knn <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), neighbor.degree.mode=c("all", "out", "in", "total"), weights=NULL) {
708:strength <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=TRUE, weights=NULL) {
748:centr_degree <- function(graph, mode=c("all", "out", "in", "total"), loops=TRUE, normalized=TRUE) {
791:centr_clo <- function(graph, mode=c("out", "in", "all", "total"), normalized=TRUE) {
805:centr_clo_tmax <- function(graph=NULL, nodes=0, mode=c("out", "in", "all", "total")) {
906:eccentricity <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total")) {
922:radius <- function(graph, mode=c("all", "out", "in", "total")) {
958:random_walk <- function(graph, start, steps, mode=c("out", "in", "all", "total"), stuck=c("return", "error")) {
979:random_edge_walk <- function(graph, start, steps, weights=NULL, mode=c("out", "in", "all", "total"), stuck=c("return", "error")) {
1029:local_efficiency <- function(graph, vids=V(graph), weights=NULL, directed=TRUE, mode=c("all",...

</details>

- Fixes igraph/rigraph#622

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot avatar Oct 28 '25 22:10 Copilot