Skip to content

Commit b79ff02

Browse files
allow escaping via env variable, document and test
1 parent 810f2c7 commit b79ff02

File tree

10 files changed

+129
-6
lines changed

10 files changed

+129
-6
lines changed

.github/workflows/R-CMD-check.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030

3131
env:
3232
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
33+
R_STYLER_FUTURE_NO_OVERRIDE: true
3334
RSPM: ${{ matrix.config.rspm }}
3435
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
3536
_R_CHECK_FORCE_SUGGESTS_: false

.github/workflows/benchmarking.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ jobs:
1818

1919
env:
2020
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
21+
R_STYLER_FUTURE_NO_OVERRIDE: true
2122
RSPM: ${{ matrix.config.rspm }}
2223
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
2324
steps:

.github/workflows/test-coverage.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
runs-on: macOS-latest
1414
env:
1515
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
16+
R_STYLER_FUTURE_NO_OVERRIDE: true
1617
steps:
1718
- uses: actions/checkout@v2
1819

DESCRIPTION

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Collate:
5757
'detect-alignment.R'
5858
'environments.R'
5959
'expr-is.R'
60+
'future.R'
6061
'indent.R'
6162
'initialize.R'
6263
'io.R'

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
## Major changes
1818

19+
- `style_file()`, `style_dir()` and `style_pkg()` now process input files in
20+
parallel and display process bars if `{furrr}` is installed. This feature is
21+
experimental, please see `help(styler_future, package = "styler")` for
22+
details.
1923
- blank lines in function calls and headers are now removed, for the former only
2024
when there are no comments before or after the blank line (#629, #630, #635).
2125
- speed improvements: (~10%) when cache is activated because transformers are not

R/future.R

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#' Parallelization of styling
2+
#'
3+
#' [style_file()], [style_pkg()] and [style_dir()] leverage the `{future}`
4+
#' framework for parallelization. To make use of parallel processing, you need
5+
#' to have the package `{furrr}` installed. In that case, the strategy
6+
#' [future::multiprocess()] is set temporarily during styling (only if there is
7+
#' more than two files to style, because of start-up costs of parallelization).
8+
#' You can prevent this temporary change in the future strategy by setting the
9+
#' environment variable `R_STYLER_FUTURE_NO_OVERRIDE` to `TRUE` (case ignored). In
10+
#' that case, the future strategy set before calling styler will be used, if
11+
#' you have not set any, the future `{framework}` falls back to
12+
#' [future::sequential()].
13+
#'
14+
#' @section Life-cycle:
15+
#' The parallelization feature is experimental, in particular how its governed
16+
#' with `R_STYLER_FUTURE_NO_OVERRIDE` and how progress bars are displayed with
17+
#' `{furrr}`. In the future, most likely the `{progressr}` package will be used
18+
#' to handle progress bars.
19+
#' @name styler_future
20+
NULL

R/transform-files.R

+18-6
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,33 @@ transform_files <- function(files, transformers, include_roxygen_examples, base_
1717
max_char <- min(max(nchar(files), 0), getOption("width"))
1818
len_files <- length(files)
1919
if (len_files > 0L && !getOption("styler.quiet", FALSE)) {
20-
cat("Styling ", len_files, " files:\n")
20+
cat("Styling ", len_files, " files:\n") # TODO should only have one space between words
2121
}
2222

23-
if (!identical(Sys.getenv("TESTTHAT"), "true") && rlang::is_installed("furrr")) {
24-
if (inherits(future::plan(), "uniprocess")) {
23+
future_strategy_no_override <- tolower(Sys.getenv("R_STYLER_FUTURE_NO_OVERRIDE", "FALSE")) == "true"
24+
if (rlang::is_installed("furrr")) {
25+
# only parallelise when furrr is installed
26+
if (!future_strategy_no_override && length(files) > 2) {
27+
# only override when env not set and more than two files.
2528
local_options(future.supportsMulticore.unstable = "quiet")
26-
oplan <- future::plan("multiprocess")
27-
on.exit(future::plan(oplan), add = TRUE)
28-
}
29+
oplan <- future::plan("multisession") # not sure we should use
2930

31+
# withr::defer() gives C stack overflow on macOS, on.exit not.
32+
on.exit(future::plan(oplan), add = TRUE, after = FALSE)
33+
}
3034
changed <- furrr::future_map_lgl(files, transform_file,
3135
fun = transformer, max_char_path = max_char, dry = dry,
3236
.progress = TRUE
3337
)
3438
} else {
39+
if (future_strategy_no_override) {
40+
rlang::warn(paste(
41+
"Environment variable `R_STYLER_FUTURE_NO_OVERRIDE` is not respected",
42+
"because package {furrr} is not installed. Falling back to ",
43+
"`purrr::map_lgl()` to iterate over files to style instead of",
44+
"`furrr::future_map_lgl()`."
45+
))
46+
}
3547
changed <- map_lgl(files, transform_file,
3648
fun = transformer, max_char_path = max_char, dry = dry
3749
)

inst/WORDLIST

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ fileext
5454
filetype
5555
forcond
5656
funct
57+
furrr
5758
gcc
5859
getChecksum
5960
getOption
@@ -91,6 +92,7 @@ macOS
9192
magrittr
9293
md
9394
Müller
95+
multiprocess
9496
mutli
9597
navbar
9698
netlify
@@ -101,6 +103,8 @@ ourself
101103
packagemanager
102104
packrat
103105
pandoc
106+
parallelization
107+
Parallelization
104108
params
105109
parsable
106110
parsesum
@@ -113,6 +117,7 @@ pre
113117
precommit
114118
prefill
115119
prettycode
120+
progressr
116121
PRs
117122
purrr
118123
rcmdcheck

man/styler_future.Rd

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-future.R

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
path_rel <- c(
2+
"dirty-sample-with-scope-tokens.R",
3+
"dirty-sample-with-scope-spaces.R",
4+
"clean-sample-with-scope-tokens.R"
5+
)
6+
7+
path_dir <- file.path(
8+
"public-api", "xyzdir-dirty", path_rel
9+
)
10+
11+
test_that("can style in parallel when no strategy is set and overriding is deactivated", {
12+
withr::local_envvar("R_STYLER_FUTURE_NO_OVERRIDE" = "TRUE")
13+
expect_match(
14+
catch_style_file_output(path_dir),
15+
'Styling +3',
16+
all = FALSE
17+
)
18+
})
19+
20+
test_that("can style in parallel when no strategy is set and overriding is not deactivated", {
21+
withr::local_envvar("R_STYLER_FUTURE_NO_OVERRIDE" = "FALSE")
22+
expect_match(
23+
catch_style_file_output(path_dir),
24+
'Styling +3',
25+
all = FALSE
26+
)
27+
})
28+
29+
test_that("can style in parallel when no strategy is set", {
30+
31+
expect_match(
32+
catch_style_file_output(path_dir),
33+
'Styling +3',
34+
all = FALSE
35+
)
36+
})
37+
38+
test_that("can style in parallel when strategy is set", {
39+
future::plan('sequential')
40+
expect_match(
41+
catch_style_file_output(path_dir),
42+
'Styling +3',
43+
all = FALSE
44+
)
45+
})
46+
47+
test_that("with fewer than two files, the plan is not modified", {
48+
expect_match(
49+
catch_style_file_output(path_dir[1]),
50+
'Styling +1',
51+
all = FALSE
52+
)
53+
})

0 commit comments

Comments
 (0)