Skip to content

Commit f69dc2e

Browse files
authored
Merge branch 'master' into fix/forcedsplits-file-error
2 parents c1ace38 + 6437645 commit f69dc2e

15 files changed

+167
-40
lines changed

.ci/install-r-deps.R

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Install R dependencies, using only base R.
2+
#
3+
# Supported arguments:
4+
#
5+
# --all Install all the 'Depends', 'Imports', 'LinkingTo', and 'Suggests' dependencies
6+
# (automatically implies --build --test).
7+
#
8+
# --build Install the packages needed to build.
9+
#
10+
# --exclude=<pkg1,pkg2,...> Comma-delimited list of packages to NOT install.
11+
#
12+
# --include=<pkg1,pkg2,...> Comma-delimited list of additional packages to install.
13+
# These will always be installed, unless also used in "--exclude".
14+
#
15+
# --test Install packages needed to run tests.
16+
#
17+
18+
19+
# [description] Parse command line arguments into an R list.
20+
# Returns a list where keys are arguments and values
21+
# are either TRUE (for flags) or a vector of values passed via a
22+
# comma-delimited list.
23+
.parse_args <- function(args) {
24+
out <- list(
25+
"--all" = FALSE
26+
, "--build" = FALSE
27+
, "--exclude" = character(0L)
28+
, "--include" = character(0L)
29+
, "--test" = FALSE
30+
)
31+
for (arg in args) {
32+
parsed_arg <- unlist(strsplit(arg, "=", fixed = TRUE))
33+
arg_name <- parsed_arg[[1L]]
34+
if (!(arg_name %in% names(out))) {
35+
stop(sprintf("Unrecognized argument: '%s'", arg_name))
36+
}
37+
if (length(parsed_arg) == 2L) {
38+
# lists, like "--include=roxygen2,testthat"
39+
values <- unlist(strsplit(parsed_arg[[2L]], ",", fixed = TRUE))
40+
out[[arg_name]] <- values
41+
} else {
42+
# flags, like "--build"
43+
out[[arg]] <- TRUE
44+
}
45+
}
46+
return(out)
47+
}
48+
49+
args <- .parse_args(
50+
commandArgs(trailingOnly = TRUE)
51+
)
52+
53+
# which dependencies to install
54+
ALL_DEPS <- isTRUE(args[["--all"]])
55+
BUILD_DEPS <- ALL_DEPS || isTRUE(args[["--build"]])
56+
TEST_DEPS <- ALL_DEPS || isTRUE(args[["--test"]])
57+
58+
# force downloading of binary packages on macOS
59+
COMPILE_FROM_SOURCE <- "both"
60+
PACKAGE_TYPE <- getOption("pkgType")
61+
62+
# CRAN has precompiled binaries for macOS and Windows... prefer those,
63+
# for faster installation.
64+
if (Sys.info()[["sysname"]] == "Darwin" || .Platform$OS.type == "windows") {
65+
COMPILE_FROM_SOURCE <- "never"
66+
PACKAGE_TYPE <- "binary"
67+
}
68+
options(
69+
install.packages.check.source = "no"
70+
, install.packages.compile.from.source = COMPILE_FROM_SOURCE
71+
)
72+
73+
# always use the same CRAN mirror
74+
CRAN_MIRROR <- Sys.getenv("CRAN_MIRROR", unset = "https://cran.r-project.org")
75+
76+
# we always want these
77+
deps_to_install <- c(
78+
"data.table"
79+
, "jsonlite"
80+
, "Matrix"
81+
, "R6"
82+
)
83+
84+
if (isTRUE(BUILD_DEPS)) {
85+
deps_to_install <- c(
86+
deps_to_install
87+
, "knitr"
88+
, "markdown"
89+
)
90+
}
91+
92+
if (isTRUE(TEST_DEPS)) {
93+
deps_to_install <- c(
94+
deps_to_install
95+
, "RhpcBLASctl"
96+
, "testthat"
97+
)
98+
}
99+
100+
# add packages passed through '--include'
101+
deps_to_install <- unique(c(
102+
deps_to_install
103+
, args[["--include"]]
104+
))
105+
106+
# remove packages passed through '--exclude'
107+
deps_to_install <- setdiff(
108+
x = deps_to_install
109+
, args[["--exclude"]]
110+
)
111+
112+
msg <- sprintf(
113+
"[install-r-deps] installing R packages: %s\n"
114+
, toString(sort(deps_to_install))
115+
)
116+
cat(msg)
117+
118+
install.packages( # nolint[undesirable_function]
119+
pkgs = deps_to_install
120+
, dependencies = c("Depends", "Imports", "LinkingTo")
121+
, lib = Sys.getenv("R_LIB_PATH", unset = .libPaths()[[1L]])
122+
, repos = CRAN_MIRROR
123+
, type = PACKAGE_TYPE
124+
, Ncpus = parallel::detectCores()
125+
)

.ci/test-r-package-valgrind.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
set -e -E -u -o pipefail
44

5-
RDscriptvalgrind -e "install.packages(c('R6', 'data.table', 'jsonlite', 'Matrix', 'RhpcBLASctl', 'testthat'), repos = 'https://cran.rstudio.com')" || exit 1
5+
RDscriptvalgrind ./.ci/install-r-deps.R --test || exit 1
66
sh build-cran-package.sh \
77
--r-executable=RDvalgrind \
88
--no-build-vignettes \

.ci/test-r-package-windows.ps1

+1-10
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,7 @@ Remove-Item "$env:RTOOLS_MINGW_BIN/cmake.exe" -Force -ErrorAction Ignore
176176
Write-Output "Done installing CMake"
177177

178178
Write-Output "Installing dependencies"
179-
$packages = -join @(
180-
"c('data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'processx', 'R6', 'RhpcBLASctl', 'testthat'), ",
181-
"dependencies = c('Imports', 'Depends', 'LinkingTo')"
182-
)
183-
$params = -join @(
184-
"options(install.packages.check.source = 'no'); ",
185-
"install.packages($packages, repos = '$env:CRAN_MIRROR', type = 'binary', ",
186-
"lib = '$env:R_LIB_PATH', Ncpus = parallel::detectCores())"
187-
)
188-
Invoke-R-Code-Redirect-Stderr $params ; Assert-Output $?
179+
Rscript.exe --vanilla ".ci/install-r-deps.R" --build --include=processx --test ; Assert-Output $?
189180

190181
Write-Output "Building R-package"
191182

.ci/test-r-package.sh

+4-11
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ set -e -E -u -o pipefail
66
ARCH=$(uname -m)
77

88
# set up R environment
9-
CRAN_MIRROR="https://cran.rstudio.com"
10-
R_LIB_PATH=~/Rlib
9+
export CRAN_MIRROR="https://cran.rstudio.com"
10+
export R_LIB_PATH=~/Rlib
1111
mkdir -p $R_LIB_PATH
1212
export R_LIBS=$R_LIB_PATH
1313
export PATH="$R_LIB_PATH/R/bin:$PATH"
@@ -112,15 +112,8 @@ Rscript --vanilla -e "install.packages('lattice', repos = '${CRAN_MIRROR}', lib
112112
# ref: https://github.com/microsoft/LightGBM/issues/6433
113113
Rscript --vanilla -e "install.packages('https://cran.r-project.org/src/contrib/Archive/Matrix/Matrix_1.6-5.tar.gz', repos = NULL, lib = '${R_LIB_PATH}')"
114114

115-
# Manually install Depends and Imports libraries + 'knitr', 'markdown', 'RhpcBLASctl', 'testthat'
116-
# to avoid a CI-time dependency on devtools (for devtools::install_deps())
117-
packages="c('data.table', 'jsonlite', 'knitr', 'markdown', 'R6', 'RhpcBLASctl', 'testthat')"
118-
compile_from_source="both"
119-
if [[ $OS_NAME == "macos" ]]; then
120-
packages+=", type = 'binary'"
121-
compile_from_source="never"
122-
fi
123-
Rscript --vanilla -e "options(install.packages.compile.from.source = '${compile_from_source}'); install.packages(${packages}, repos = '${CRAN_MIRROR}', lib = '${R_LIB_PATH}', dependencies = c('Depends', 'Imports', 'LinkingTo'), Ncpus = parallel::detectCores())" || exit 1
115+
# Manually install dependencies to avoid a CI-time dependency on devtools (for devtools::install_deps())
116+
Rscript --vanilla ./.ci/install-r-deps.R --build --test --exclude=Matrix || exit 1
124117

125118
cd "${BUILD_DIRECTORY}"
126119
PKG_TARBALL="lightgbm_$(head -1 VERSION.txt).tar.gz"

.github/workflows/r_package.yml

+3-6
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,7 @@ jobs:
245245
- name: Install packages
246246
shell: bash
247247
run: |
248-
R_LIBS="c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl', 'testthat')"
249-
RDscript${{ matrix.r_customization }} \
250-
-e "install.packages(${R_LIBS}, repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"
248+
RDscript${{ matrix.r_customization }} ./.ci/install-r-deps.R --build --test
251249
sh build-cran-package.sh --r-executable=RD${{ matrix.r_customization }}
252250
RD${{ matrix.r_customization }} CMD INSTALL lightgbm_*.tar.gz || exit 1
253251
- name: Run tests with sanitizers
@@ -272,6 +270,7 @@ jobs:
272270
- clang17
273271
- clang18
274272
- clang19
273+
- clang20
275274
- gcc14
276275
- intel
277276
- rchk
@@ -312,9 +311,7 @@ jobs:
312311
- name: Install packages and run tests
313312
shell: bash
314313
run: |
315-
R_LIBS="c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl')"
316-
Rscript \
317-
-e "install.packages(${R_LIBS}, repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"
314+
Rscript ./.ci/install-r-deps.R --build --test --exclude=testthat
318315
sh build-cran-package.sh
319316
320317
# 'rchk' isn't run through 'R CMD check', use the approach documented at

.github/workflows/static_analysis.yml

+1-3
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,10 @@ jobs:
6363
submodules: true
6464
- name: Install packages
6565
shell: bash
66-
# yamllint disable rule:line-length
6766
run: |
68-
Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl', 'roxygen2', 'testthat'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"
67+
Rscript ./.ci/install-r-deps.R --build --include=roxygen2
6968
sh build-cran-package.sh || exit 1
7069
R CMD INSTALL --with-keep.source lightgbm_*.tar.gz || exit 1
71-
# yamllint enable rule:line-length
7270
- name: Test documentation
7371
shell: bash --noprofile --norc {0}
7472
run: |

.vsts-ci.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ jobs:
254254
- script: |
255255
git clean -d -f -x
256256
displayName: 'Clean source directory'
257+
# LGBM_SKIP_DASK_TESTS=true is set below only because running the tests under emulation is so slow...
258+
# in theory, 'lightgbm.dask' should work without issue on aarch64 Linux systems.
259+
# That could probably be removed as part of https://github.com/microsoft/LightGBM/issues/6788
257260
- script: |
258261
cat > docker-script.sh <<EOF
259262
export CONDA=\$HOME/miniforge
@@ -273,6 +276,7 @@ jobs:
273276
--env BUILD_ARTIFACTSTAGINGDIRECTORY=$BUILD_ARTIFACTSTAGINGDIRECTORY \
274277
--env BUILD_DIRECTORY=$BUILD_DIRECTORY \
275278
--env COMPILER=$COMPILER \
279+
--env LGBM_SKIP_DASK_TESTS=true \
276280
--env METHOD=$METHOD \
277281
--env OS_NAME=linux \
278282
--env PRODUCES_ARTIFACTS=$PRODUCES_ARTIFACTS \
@@ -414,16 +418,14 @@ jobs:
414418
- script: |
415419
git clean -d -f -x
416420
displayName: 'Clean source directory'
417-
# yamllint disable rule:line-length
418421
- script: |
419422
LGB_VER=$(head -n 1 VERSION.txt | sed "s/rc/-/g")
420423
R_LIB_PATH=~/Rlib
421424
export R_LIBS=${R_LIB_PATH}
422425
mkdir -p ${R_LIB_PATH}
423-
RDscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl'), lib = '${R_LIB_PATH}', dependencies = c('Depends', 'Imports', 'LinkingTo'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())" || exit 1
426+
RDscript .ci/install-r-deps.R --build --include=RhpcBLASctl || exit 1
424427
sh build-cran-package.sh --r-executable=RD || exit 1
425428
mv lightgbm_${LGB_VER}.tar.gz $(Build.ArtifactStagingDirectory)/lightgbm-${LGB_VER}-r-cran.tar.gz
426-
# yamllint enable rule:line-length
427429
displayName: 'Build CRAN R-package'
428430
- task: PublishBuildArtifacts@1
429431
condition: succeeded()

R-package/R/lightgbm.R

+3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
#' in \code{params}, that metric will be considered the "first" one. If you omit \code{metric},
7070
#' a default metric will be used based on your choice for the parameter \code{obj} (keyword argument)
7171
#' or \code{objective} (passed into \code{params}).
72+
#'
73+
#' \bold{NOTE:} if using \code{boosting_type="dart"}, any early stopping configuration will be ignored
74+
#' and early stopping will not be performed.
7275
#' @section Model serialization:
7376
#'
7477
#' LightGBM model objects can be serialized and de-serialized through functions such as \code{save}

R-package/man/lgb.cv.Rd

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

R-package/man/lgb.train.Rd

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

R-package/man/lgb_shared_params.Rd

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

R-package/man/lightgbm.Rd

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

docs/Parallel-Learning-Guide.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ LightGBM's Python-package supports distributed learning via `Dask`_. This integr
6464

6565
.. warning::
6666

67-
Dask integration is only tested on Linux.
67+
Dask integration is only tested on macOS and Linux.
6868

6969
Dask Examples
7070
'''''''''''''

python-package/lightgbm/callback.py

+5
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,11 @@ def early_stopping(
468468
To check only the first metric set ``first_metric_only`` to True.
469469
The index of iteration that has the best performance will be saved in the ``best_iteration`` attribute of a model.
470470
471+
.. note::
472+
473+
If using ``boosting_type="dart"``, this callback has no effect and early stopping
474+
will not be performed.
475+
471476
Parameters
472477
----------
473478
stopping_rounds : int

tests/python_package_test/test_dask.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import socket
66
from itertools import groupby
77
from os import getenv
8-
from platform import machine
98
from sys import platform
109
from urllib.parse import urlparse
1110

@@ -16,10 +15,8 @@
1615

1716
from .utils import sklearn_multiclass_custom_objective
1817

19-
if not platform.startswith("linux"):
20-
pytest.skip("lightgbm.dask is currently supported in Linux environments", allow_module_level=True)
21-
if machine() != "x86_64":
22-
pytest.skip("lightgbm.dask tests are currently skipped on some architectures like arm64", allow_module_level=True)
18+
if platform in {"cygwin", "win32"}:
19+
pytest.skip("lightgbm.dask is not currently supported on Windows", allow_module_level=True)
2320
if not lgb.compat.DASK_INSTALLED:
2421
pytest.skip("Dask is not installed", allow_module_level=True)
2522

@@ -58,6 +55,10 @@
5855
pytest.mark.skipif(getenv("TASK", "") == "mpi", reason="Fails to run with MPI interface"),
5956
pytest.mark.skipif(getenv("TASK", "") == "gpu", reason="Fails to run with GPU interface"),
6057
pytest.mark.skipif(getenv("TASK", "") == "cuda", reason="Fails to run with CUDA interface"),
58+
pytest.mark.skipif(
59+
getenv("LGBM_SKIP_DASK_TESTS", "") == "true",
60+
reason="Skipping lightgbm.dask tests (found env variable LGBM_SKIP_DASK_TESTS=true)",
61+
),
6162
]
6263

6364

0 commit comments

Comments
 (0)