Skip to content

Commit d832377

Browse files
rpreenjim-smith
andauthored
feat: add support for conda environments (#35)
* feat: add support for conda environments * add conda to ci; clean up public API * feat: add yaml config param to acro init * chore: clean up conda warning message --------- Signed-off-by: Richard Preen <rpreen@gmail.com> Co-authored-by: Jim-smith <jim-smith@users.noreply.github.com>
1 parent 115be3a commit d832377

8 files changed

Lines changed: 135 additions & 125 deletions

File tree

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,67 @@ on:
33
branches: [main, master]
44
pull_request:
55
branches: [main, master]
6+
67
name: R-CMD-check
8+
79
jobs:
810
R-CMD-check:
911
runs-on: ${{ matrix.os }}
10-
name: ${{ matrix.os }} (${{ matrix.r }})
12+
name: ${{ matrix.os }} (${{ matrix.r }}) - ${{ matrix.backend }}
13+
1114
strategy:
1215
fail-fast: false
1316
matrix:
1417
include:
15-
- { os: "ubuntu-latest", python: "3.13", r: "release" }
16-
- { os: "windows-latest", python: "3.13", r: "release" }
17-
- { os: "macOS-latest", python: "3.13", r: "release" }
18-
- { os: "ubuntu-latest", python: "3.10", r: "oldrel-1" }
19-
- { os: "ubuntu-latest", python: "3.10", r: "oldrel-2" }
20-
- { os: "ubuntu-latest", python: "3.10", r: "oldrel-3" }
18+
- { os: "ubuntu-latest", python: "3.13", r: "release", backend: "venv" }
19+
- { os: "ubuntu-latest", python: "3.13", r: "release", backend: "conda" }
20+
21+
- { os: "windows-latest", python: "3.13", r: "release", backend: "venv" }
22+
- { os: "windows-latest", python: "3.13", r: "release", backend: "conda" }
23+
24+
- { os: "macOS-latest", python: "3.13", r: "release", backend: "venv" }
25+
- { os: "macOS-latest", python: "3.13", r: "release", backend: "conda" }
26+
27+
- { os: "ubuntu-latest", python: "3.10", r: "oldrel-1", backend: "venv" }
28+
- { os: "ubuntu-latest", python: "3.10", r: "oldrel-2", backend: "venv" }
29+
- { os: "ubuntu-latest", python: "3.10", r: "oldrel-3", backend: "venv" }
30+
2131
env:
2232
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
2333
R_KEEP_PKG_SOURCE: yes
2434
MPLBACKEND: Agg
35+
ACRO_USE_CONDA: ${{ matrix.backend == 'conda' && 'true' || 'false' }}
36+
2537
steps:
2638
- name: Checkout ACRO
2739
uses: actions/checkout@v6
40+
41+
- name: Setup Miniconda
42+
if: matrix.backend == 'conda'
43+
uses: conda-incubator/setup-miniconda@v3
44+
with:
45+
python-version: ${{ matrix.python }}
46+
auto-activate-base: false
47+
2848
- name: Setup Python
2949
uses: actions/setup-python@v6
3050
with:
3151
python-version: ${{ matrix.python }}
52+
3253
- name: Setup pandoc
3354
uses: r-lib/actions/setup-pandoc@v2
55+
3456
- name: Setup R
3557
uses: r-lib/actions/setup-r@v2
3658
with:
3759
r-version: ${{ matrix.r }}
60+
3861
- name: Install R dependencies
3962
uses: r-lib/actions/setup-r-dependencies@v2
4063
with:
4164
extra-packages: any::rcmdcheck
4265
needs: check
66+
4367
- name: Check R Package
4468
uses: r-lib/actions/check-r-package@v2
4569
with:

R/acro_init.R

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,96 @@
1+
# Globals -----------------------------------------------------------------
2+
acro_venv <- "r-acro"
3+
acro_pkg <- "acro==0.4.11"
4+
ch <- "conda-forge"
5+
6+
7+
# Internal helper: resolve Python executable
8+
## nocov start
9+
get_python <- function() {
10+
python <- Sys.which("python3")
11+
if (python == "") {
12+
python <- Sys.which("python")
13+
if (python == "") {
14+
stop("Python not found in PATH. Please ensure Python is installed.")
15+
}
16+
}
17+
return(python)
18+
}
19+
## nocov end
20+
21+
22+
# Internal helper: install ACRO in a Conda environment
23+
## nocov start
24+
install_conda <- function(envname) { # nocov
25+
if (!reticulate::condaenv_exists(envname = envname, conda = "auto")) {
26+
reticulate::conda_create(envname = envname, python_version = "3.12", channel = ch)
27+
reticulate::conda_install(envname = envname, packages = acro_pkg, channel = ch)
28+
}
29+
}
30+
## nocov end
31+
32+
33+
# Internal helper: install ACRO in a Python virtual environment
34+
install_venv <- function(envname = acro_venv) {
35+
if (!reticulate::virtualenv_exists(envname)) {
36+
python <- get_python()
37+
38+
reticulate::virtualenv_create(
39+
envname = envname,
40+
python = python,
41+
force = TRUE,
42+
packages = NULL
43+
)
44+
45+
reticulate::py_install(acro_pkg, envname = envname)
46+
}
47+
}
48+
49+
50+
# Internal helper: resolve whether Conda should be used
51+
get_use_conda <- function(use_conda = NULL) {
52+
if (is.null(use_conda)) {
53+
use_conda <- tolower(Sys.getenv("ACRO_USE_CONDA")) %in% c("1", "true", "yes")
54+
}
55+
use_conda <- isTRUE(use_conda) # default FALSE
56+
57+
if (use_conda && is.null(reticulate::conda_binary())) { # nocov
58+
stop("Conda requested but no conda installation found", call. = FALSE) # nocov
59+
}
60+
61+
return(use_conda)
62+
}
63+
64+
165
#' Initialise an ACRO object
266
#'
67+
#' @param config Name of a yaml configuration file with safe parameters.
368
#' @param suppress Whether to automatically apply suppression.
69+
#' @param envname Name of the Python environment to use.
70+
#' @param use_conda Whether to use a Conda environment.
71+
#' If `NULL`, looks for environment variable `ACRO_USE_CONDA`,
72+
#' defaults to `FALSE` if unset.
473
#'
5-
#' @return No return value, called for side effects
74+
#' @return Invisibly returns the ACRO object, which is used internally.
675
#' @export
76+
acro_init <- function(config = "default", suppress = FALSE, envname = acro_venv, use_conda = NULL) {
77+
# define the environment
78+
use_conda <- get_use_conda(use_conda)
779

8-
acro_init <- function(suppress = FALSE) {
9-
create_virtualenv()
80+
# initialise the environment
81+
if (!reticulate::py_available(initialize = FALSE)) {
82+
if (use_conda) { # nocov
83+
install_conda(envname) # nocov
84+
reticulate::use_condaenv(envname, required = TRUE) # nocov
85+
} else {
86+
install_venv(envname)
87+
reticulate::use_virtualenv(envname, required = TRUE)
88+
}
89+
}
90+
91+
# import the acro package and instantiate an object
1092
acro <- reticulate::import("acro", delay_load = TRUE)
11-
acroEnv$ac <- acro$ACRO(suppress = suppress)
93+
acroEnv$ac <- acro$ACRO(config = config, suppress = suppress)
94+
95+
invisible(acroEnv$ac)
1296
}

R/create_virtualenv.R

Lines changed: 0 additions & 55 deletions
This file was deleted.

man/acro_init.Rd

Lines changed: 15 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/create_virtualenv.Rd

Lines changed: 0 additions & 17 deletions
This file was deleted.

man/install_acro.Rd

Lines changed: 0 additions & 21 deletions
This file was deleted.

tests/testthat/test-create_virtualenv.R

Lines changed: 0 additions & 18 deletions
This file was deleted.

tests/testthat/test-install_acro.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ test_that("install_acro installs 'acro' in the specified environment", {
44
test_envname <- "test-acro-env"
55

66
# Run the install_acro function
7-
install_acro(envname = test_envname)
7+
install_venv(envname = test_envname)
88

99
# Check if 'acro' is installed in the test environment
1010
is_installed <- reticulate::py_module_available("acro")

0 commit comments

Comments
 (0)