From eb5549ec7b2649c343ce9f3ff4f5febbacccda70 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 30 Jan 2026 13:45:52 -0500 Subject: [PATCH 1/2] Explicitly retain `"ordering"` attribute of `chunk_size` --- NEWS.md | 3 +++ R/furrr-options.R | 16 ++++++++++------ tests/testthat/test-furrr-options.R | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index d795bdb..52c3099 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,6 +19,9 @@ * When a furrr function errors, purrr's error index is no longer confusingly reported (#250). +* `furrr_options()` no longer drops the `"ordering"` attribute when casting + a non-integer `chunk_size` to integer (#290). + * furrr now looks up the purrr mapping function on the worker itself, rather than sending over its own copy of the function. This avoids possible issues when you have, say, purrr 1.0.0 locally but purrr 0.3.5 on the worker, where diff --git a/R/furrr-options.R b/R/furrr-options.R index 4fb522f..3359f33 100644 --- a/R/furrr-options.R +++ b/R/furrr-options.R @@ -396,12 +396,8 @@ validate_chunk_size <- function(x) { return(x) } - if (identical(x, Inf)) { - return(x) - } - - vctrs::vec_assert(x, size = 1L, arg = "chunk_size") - x <- vctrs::vec_cast(x, integer(), x_arg = "chunk_size") + vctrs::obj_check_vector(x, arg = "chunk_size") + vctrs::vec_check_size(x, size = 1L, arg = "chunk_size") if (is.na(x)) { abort("`chunk_size` can't be `NA`.") @@ -411,6 +407,14 @@ validate_chunk_size <- function(x) { abort("`chunk_size` must be greater than zero.") } + if (is.infinite(x)) { + return(x) + } + + ordering <- attr(x, "ordering") + x <- vctrs::vec_cast(x, integer(), x_arg = "chunk_size") + attr(x, "ordering") <- ordering + x } diff --git a/tests/testthat/test-furrr-options.R b/tests/testthat/test-furrr-options.R index 6afe884..54243ca 100644 --- a/tests/testthat/test-furrr-options.R +++ b/tests/testthat/test-furrr-options.R @@ -282,6 +282,22 @@ test_that("validates `chunk_size`", { expect_error(furrr_options(chunk_size = "x")) expect_error(furrr_options(chunk_size = 1.5)) expect_error(furrr_options(chunk_size = NA)) + expect_error(furrr_options(chunk_size = -Inf)) + expect_error(furrr_options(chunk_size = lm(1 ~ 1))) +}) + +test_that("`chunk_size` supports an `ordering` attribute (#290)", { + # Integer `chunk_size` + x <- furrr_options(chunk_size = structure(2L, ordering = "random")) + expect_identical(x$chunk_size, structure(2L, ordering = "random")) + + # Double `chunk_size` + x <- furrr_options(chunk_size = structure(2, ordering = "random")) + expect_identical(x$chunk_size, structure(2L, ordering = "random")) + + # Inf `chunk_size` + x <- furrr_options(chunk_size = structure(Inf, ordering = "random")) + expect_identical(x$chunk_size, structure(Inf, ordering = "random")) }) # ------------------------------------------------------------------------------ From 0bf7e5985d52f864df6649b0103645155c9e7221 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 30 Jan 2026 13:55:29 -0500 Subject: [PATCH 2/2] Explicitly retain `"ordering"` attribute of `scheduling` --- NEWS.md | 2 +- R/furrr-options.R | 23 ++++++++-------- tests/testthat/test-furrr-options.R | 42 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index 52c3099..e863ed8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -20,7 +20,7 @@ reported (#250). * `furrr_options()` no longer drops the `"ordering"` attribute when casting - a non-integer `chunk_size` to integer (#290). + non-integer `chunk_size` or `scheduling` to integer (#289, #290). * furrr now looks up the purrr mapping function on the worker itself, rather than sending over its own copy of the function. This avoids possible issues diff --git a/R/furrr-options.R b/R/furrr-options.R index 3359f33..8a04c65 100644 --- a/R/furrr-options.R +++ b/R/furrr-options.R @@ -366,27 +366,28 @@ validate_seed_list <- function(x) { } validate_scheduling <- function(x) { - if (length(x) != 1L) { - abort("`scheduling` must be length 1.") + vctrs::obj_check_vector(x, arg = "scheduling") + vctrs::vec_check_size(x, size = 1L, arg = "scheduling") + + if (is.na(x)) { + abort("`scheduling` can't be `NA`.") } - if (identical(x, Inf)) { + if (is_bool(x)) { return(x) } - if (is.logical(x)) { - if (!is_bool(x)) { - abort("A logical `scheduling` value can't be `NA`.") - } + if (x < 0L) { + abort("`scheduling` must be greater than or equal to zero.") + } + if (is.infinite(x)) { return(x) } + ordering <- attr(x, "ordering") x <- vctrs::vec_cast(x, integer(), x_arg = "scheduling") - - if (x < 0L) { - abort("`scheduling` must be greater than or equal to zero.") - } + attr(x, "ordering") <- ordering x } diff --git a/tests/testthat/test-furrr-options.R b/tests/testthat/test-furrr-options.R index 54243ca..c73ee1e 100644 --- a/tests/testthat/test-furrr-options.R +++ b/tests/testthat/test-furrr-options.R @@ -262,11 +262,49 @@ test_that("validates `seed`", { # ------------------------------------------------------------------------------ # furrr_options(scheduling =) +test_that("can specify `scheduling`", { + x <- furrr_options(scheduling = TRUE) + expect_identical(x$scheduling, TRUE) + + x <- furrr_options(scheduling = FALSE) + expect_identical(x$scheduling, FALSE) + + x <- furrr_options(scheduling = 0) + expect_identical(x$scheduling, 0L) + + x <- furrr_options(scheduling = 5) + expect_identical(x$scheduling, 5L) + + x <- furrr_options(scheduling = Inf) + expect_identical(x$scheduling, Inf) +}) + test_that("validates `scheduling`", { expect_error(furrr_options(scheduling = c(1, 2))) + expect_error(furrr_options(scheduling = c(TRUE, FALSE))) expect_error(furrr_options(scheduling = "x")) expect_error(furrr_options(scheduling = 1.5)) expect_error(furrr_options(scheduling = NA)) + expect_error(furrr_options(scheduling = -Inf)) + expect_error(furrr_options(scheduling = lm(1 ~ 1))) +}) + +test_that("`scheduling` supports an `ordering` attribute (#289)", { + # Integer `scheduling` + x <- furrr_options(scheduling = structure(2L, ordering = "random")) + expect_identical(x$scheduling, structure(2L, ordering = "random")) + + # Double `scheduling` + x <- furrr_options(scheduling = structure(2, ordering = "random")) + expect_identical(x$scheduling, structure(2L, ordering = "random")) + + # Inf `scheduling` + x <- furrr_options(scheduling = structure(Inf, ordering = "random")) + expect_identical(x$scheduling, structure(Inf, ordering = "random")) + + # Logical `scheduling` + x <- furrr_options(scheduling = structure(TRUE, ordering = "random")) + expect_identical(x$scheduling, structure(TRUE, ordering = "random")) }) # ------------------------------------------------------------------------------ @@ -275,9 +313,13 @@ test_that("validates `scheduling`", { test_that("can specify `chunk_size`", { x <- furrr_options(chunk_size = 2) expect_identical(x$chunk_size, 2L) + + x <- furrr_options(chunk_size = Inf) + expect_identical(x$chunk_size, Inf) }) test_that("validates `chunk_size`", { + expect_error(furrr_options(chunk_size = 0)) expect_error(furrr_options(chunk_size = c(1, 2))) expect_error(furrr_options(chunk_size = "x")) expect_error(furrr_options(chunk_size = 1.5))