Run command-line tools in a reproducible and isolated way, right from R.
Tired of system() calls that work on your machine but break everywhere
else? condathis is here to help! It lets you create self-contained
environments for your command-line tools, so your R code runs reliably
for you, your colleagues, and your future self.
Let’s have some fun with cowpy. With just two commands, we can install
and run it in its own isolated environment:
# 1. Install 'cowpy' into an environment named 'cowpy-env'
condathis::create_env(packages = "cowpy", env_name = "cowpy-env")
#> ! Environment cowpy-env succesfully created.
# 2. Run it!
# Example showing redirection from a file to the Standard Input (STDIN)
temp_file <- tempfile()
writeLines("{condathis} is awesome!", temp_file)
condathis::run("cowpy", stdin = temp_file, env_name = "cowpy-env")
#> _________________________
#> < {condathis} is awesome! >
#> -------------------------
#> \ ^__^
#> \ (oo)\_______
#> (__)\ )\/\
#> ||----w |
#> || ||Maybe you want to try something fancier, like rich-cli for formatting
messages?
condathis::create_env(packages = "rich-cli", env_name = "rich-cli-env")
#> ! Environment rich-cli-env succesfully created.
condathis::run(
"rich", "[b]Condathis[/b] is awesome!", "-p", "-a", "heavy",
env_name = "rich-cli-env"
)
#> ┏━━━━━━━━━━━━━━━━━━━━━━━┓
#> ┃ Condathis is awesome! ┃
#> ┗━━━━━━━━━━━━━━━━━━━━━━━┛That’s it! You can now package any command-line tool with your R script, ensuring it works everywhere, every time.
Install the release version of the package from CRAN:
install.packages("condathis")Or get the development version from R-Universe:
install.packages("condathis", repos = c("https://luciorq.r-universe.dev", getOption("repos")))R’s system() and system2() are powerful, but they depend on tools
being installed on the host system. This creates a few problems:
- Reproducibility: Will your script from last year still work? Will your collaborator be able to run your code if they have a different version of a tool?
- Conflicts: What if two different tools need two different versions of the same dependency?
{condathis} solves these issues by creating isolated environments for
each tool.
Let’s say you’re using fastqc for quality control in a bioinformatics
pipeline. Different versions of fastqc can produce slightly different
results.
With {condathis}, you can lock in a specific version:
fastq_file <- system.file("extdata", "sample1_L001_R1_001.fastq.gz", package = "condathis")
temp_out_dir <- file.path(tempdir(), "output")
fs::dir_create(temp_out_dir)
# Always use fastqc version 0.12.1
condathis::create_env(packages = "fastqc==0.12.1", channels = c("conda-forge", "bioconda"), env_name = "fastqc-0.12.1")
#> ! Environment fastqc-0.12.1 succesfully created.
condathis::run("fastqc", fastq_file, "-o", temp_out_dir, env_name = "fastqc-0.12.1")
#> application/gzip
#> Started analysis of sample1_L001_R1_001.fastq.gz
#> Approx 90% complete for sample1_L001_R1_001.fastq.gz
#> Analysis complete for sample1_L001_R1_001.fastq.gzNow your analysis will produce the same output files, regardless of where or when it’s run.
Need to use a specific version of a tool like curl that’s different
from your system’s version? No problem.
Your system’s curl:
libcurlVersion()
#> [1] "8.7.1"
#> attr(,"ssl_version")
#> [1] "SecureTransport (LibreSSL/3.3.6)"
#> attr(,"libssh_version")
#> [1] ""
#> attr(,"protocols")
#> [1] "dict" "file" "ftp" "ftps" "gopher" "gophers" "http"
#> [8] "https" "imap" "imaps" "ldap" "ldaps" "mqtt" "pop3"
#> [15] "pop3s" "rtsp" "smb" "smbs" "smtp" "smtps" "telnet"
#> [22] "tftp"A specific curl version, isolated with condathis:
condathis::create_env(
packages = "curl==8.10.1",
env_name = "curl-env"
)
#> ! Environment curl-env succesfully created.
# Handling output thorough R objects
out <- condathis::run(
"curl", "--version",
env_name = "curl-env",
verbose = "silent"
)
message(out$stdout)
#> curl 8.10.1 (aarch64-apple-darwin20.0.0) libcurl/8.10.1 OpenSSL/3.5.4 (SecureTransport) zlib/1.3.1 zstd/1.5.7 libssh2/1.11.1 nghttp2/1.67.0
#> Release-Date: 2024-09-18
#> Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
#> Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe TLS-SRP UnixSockets zstdThis allows you to run tools with conflicting dependencies side-by-side without any issues.
The package {condathis} relies on
micromamba
to bring reproducibility and isolation. micromamba is a
lightweight, fast, and efficient package manager that “does not need a
base environment and does not come with a default version of Python”.
The integration of micromamba into R is handled using the processx
and withr packages.
Special characters in CLI commands are interpreted as literals and not expanded.
- It is not supported the use of output redirections in commands,
e.g. “|” or “>”.
- Instead of redirects (e.g. “>”), use the argument
stdout = "<FILENAME>.txt". Instead of Pipes (“|”), simple run multiple calls tocondathis::run(), usingstdoutargument to control the output andstdinto control the input of each command. P.S. The current implementation only supports files as the “STDIN”.
- Instead of redirects (e.g. “>”), use the argument
- File paths should not use special characters for relative paths,
e.g. “~”, “.”, “..”.
- Expand file paths directly in R, using
basefunctions or functions from thefspackage.
- Expand file paths directly in R, using