Skip to content

Commit cd09c35

Browse files
lorenzwalthertasottile
authored andcommitted
avoid quoting and escaping while installing R hooks by writing code to tempfile instead of execute R code inline
1 parent c389ac0 commit cd09c35

File tree

1 file changed

+35
-16
lines changed
  • pre_commit/languages

1 file changed

+35
-16
lines changed

pre_commit/languages/r.py

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import os
55
import shlex
66
import shutil
7+
import tempfile
8+
import textwrap
79
from typing import Generator
810
from typing import Sequence
911

@@ -21,6 +23,19 @@
2123
health_check = lang_base.basic_health_check
2224

2325

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+
2439
def get_env_patch(venv: str) -> PatchesT:
2540
return (
2641
('R_PROFILE_USER', os.path.join(venv, 'activate.R')),
@@ -129,32 +144,36 @@ def install_environment(
129144
}}
130145
"""
131146

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+
137150
if additional_dependencies:
138151
r_code_inst_add = 'renv::install(commandArgs(trailingOnly = TRUE))'
139152
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+
)
146160

147161

148162
def _inline_r_setup(code: str) -> str:
149163
"""
150164
Some behaviour of R cannot be configured via env variables, but can
151165
only be configured via R options once R has started. These are set here.
152166
"""
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)
158177

159178

160179
def run_hook(

0 commit comments

Comments
 (0)