|
4 | 4 | import os |
5 | 5 | import shlex |
6 | 6 | import shutil |
| 7 | +import tempfile |
| 8 | +import textwrap |
7 | 9 | from typing import Generator |
8 | 10 | from typing import Sequence |
9 | 11 |
|
|
21 | 23 | health_check = lang_base.basic_health_check |
22 | 24 |
|
23 | 25 |
|
| 26 | +@contextlib.contextmanager |
| 27 | +def _r_code_in_tempfile(code: str) -> Generator[str, None, None]: |
| 28 | + """ |
| 29 | + To avoid quoting and escaping issues, avoid `Rscript [options] -e {expr}` |
| 30 | + but use `Rscript [options] path/to/file_with_expr.R` |
| 31 | + """ |
| 32 | + with tempfile.TemporaryDirectory() as tmpdir: |
| 33 | + fname = os.path.join(tmpdir, 'script.R') |
| 34 | + with open(fname, 'w') as f: |
| 35 | + f.write(_inline_r_setup(textwrap.dedent(code))) |
| 36 | + yield fname |
| 37 | + |
| 38 | + |
24 | 39 | def get_env_patch(venv: str) -> PatchesT: |
25 | 40 | return ( |
26 | 41 | ('R_PROFILE_USER', os.path.join(venv, 'activate.R')), |
@@ -129,32 +144,36 @@ def install_environment( |
129 | 144 | }} |
130 | 145 | """ |
131 | 146 |
|
132 | | - cmd_output_b( |
133 | | - _rscript_exec(), '--vanilla', '-e', |
134 | | - _inline_r_setup(r_code_inst_environment), |
135 | | - cwd=env_dir, |
136 | | - ) |
| 147 | + with _r_code_in_tempfile(r_code_inst_environment) as f: |
| 148 | + cmd_output_b(_rscript_exec(), '--vanilla', f, cwd=env_dir) |
| 149 | + |
137 | 150 | if additional_dependencies: |
138 | 151 | r_code_inst_add = 'renv::install(commandArgs(trailingOnly = TRUE))' |
139 | 152 | with in_env(prefix, version): |
140 | | - cmd_output_b( |
141 | | - _rscript_exec(), *RSCRIPT_OPTS, '-e', |
142 | | - _inline_r_setup(r_code_inst_add), |
143 | | - *additional_dependencies, |
144 | | - cwd=env_dir, |
145 | | - ) |
| 153 | + with _r_code_in_tempfile(r_code_inst_add) as f: |
| 154 | + cmd_output_b( |
| 155 | + _rscript_exec(), *RSCRIPT_OPTS, |
| 156 | + f, |
| 157 | + *additional_dependencies, |
| 158 | + cwd=env_dir, |
| 159 | + ) |
146 | 160 |
|
147 | 161 |
|
148 | 162 | def _inline_r_setup(code: str) -> str: |
149 | 163 | """ |
150 | 164 | Some behaviour of R cannot be configured via env variables, but can |
151 | 165 | only be configured via R options once R has started. These are set here. |
152 | 166 | """ |
153 | | - with_option = f"""\ |
154 | | - options(install.packages.compile.from.source = "never", pkgType = "binary") |
155 | | - {code} |
156 | | - """ |
157 | | - return with_option |
| 167 | + with_option = [ |
| 168 | + textwrap.dedent("""\ |
| 169 | + options( |
| 170 | + install.packages.compile.from.source = "never", |
| 171 | + pkgType = "binary" |
| 172 | + ) |
| 173 | + """), |
| 174 | + code, |
| 175 | + ] |
| 176 | + return '\n'.join(with_option) |
158 | 177 |
|
159 | 178 |
|
160 | 179 | def run_hook( |
|
0 commit comments