From c3fbab8a95adffb2bc39aaa646c5793e0869623a Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 26 Jun 2017 10:57:35 -0400 Subject: Shared library mode --- conda.groovy | 274 --------------------------------------------- resources/.keep | 0 src/org/stsci/conda.groovy | 274 +++++++++++++++++++++++++++++++++++++++++++++ vars/.keep | 0 4 files changed, 274 insertions(+), 274 deletions(-) delete mode 100644 conda.groovy create mode 100644 resources/.keep create mode 100644 src/org/stsci/conda.groovy create mode 100644 vars/.keep diff --git a/conda.groovy b/conda.groovy deleted file mode 100644 index a8e2fb7..0000000 --- a/conda.groovy +++ /dev/null @@ -1,274 +0,0 @@ -class OSInfo { - public String name - public String version - public String arch - - OSInfo () { - name = 'uname -s'.execute().text.trim() - if (name == 'Darwin') { name = 'MacOSX' } - arch = 'uname -p'.execute().text.trim() - if (arch.matches('^i.*86$')) { arch = 'x86' } - - this.name = name - this.arch = arch - this.version = 'uname -r'.execute().text.trim() - } - -} - -class CondaInstaller { - OSInfo os - String prefix - String dist_version - String url - def dist = [:] - - CondaInstaller(prefix, dist="miniconda", variant="3", version="latest") { - def distributions = [ - miniconda: [name: 'Miniconda', - variant: variant, - baseurl: 'https://repo.continuum.io/miniconda'], - anaconda: [name: 'Anaconda', - variant: variant, - baseurl: 'https://repo.continuum.io/archive'] - ] - this.os = new OSInfo() - this.dist = distributions."${dist}" - this.dist_version = version - this.prefix = prefix - this.url = "${this.dist.baseurl}/" + - "${this.dist.name}${this.dist.variant}-" + - "${this.dist_version}-${this.os.name}-${this.os.arch}.sh" - } - - void download() { - - println("Downloading $url") - File fp = new File('installer.sh') - def installer = fp.newOutputStream() - installer << new URL(this.url).openStream() - installer.close() - println("Received ${fp.length()} bytes") - } - - int install() { - if (new File(this.prefix).exists()) { - println("Skipping installation: ${this.prefix} exists.") - return 0xFF - } - - if (!new File('installer.sh').exists()) { - this.download() - } - - def cmd = "bash installer.sh -b -p ${this.prefix}" - def proc = cmd.execute() - def stdout = new StringBuffer() - - proc.inputStream.eachLine { println(it) } - - //proc.waitForProcessOutput(stdout, System.err) - //print(stdout.toString()) - - return proc.exitValue() - } - - private void detect() { - } -} - -class Conda { - public String prefix - public boolean prefix_exists - public Map shell_environment - public String environment_name - public ArrayList channels - public boolean override - - Conda (prefix) { - this.prefix = prefix - this.prefix_exists = new File(this.prefix).exists() - this.shell_environment = [:] - this.environment_name = "" - this.channels = [] - this.override = false - - if (this.prefix_exists) { - this.activate("root") - } - } - - private def runshell(String args, silent=false) { - def cmd = new String[3] - def proc_env = [:] - - if (this.shell_environment) { - proc_env = this.shell_environment - } - - cmd[0] = 'bash' - cmd[1] = '-c' - cmd[2] = args - - def process = new ProcessBuilder(cmd) - process.redirectErrorStream(true) - Map env_tmp = process.environment() - - if (proc_env) { - env_tmp <<= proc_env - } - - Process p = process.start() - if (!silent) { - p.inputStream.eachLine { println it} - } - p.waitFor() - return p - } - - void activate(String conda_env) { - def records = [:] - def env_dump = this.runshell("source ${prefix}/bin/activate ${conda_env} ; printenv", true) - - /* Split each environment keypair by first occurance of '=' */ - env_dump.inputStream.eachLine { line -> - if(line) { - def (k, v) = line.split('=', 2).collect { it.trim() } - /* Strip out envmodules if they exist, i.e. multiline variables*/ - if (k.contains("_FUNC_") || !line.contains("=")) { - return - } - records."$k" = v - } - } - - /* runshell can now natively resolve this conda installation */ - this.shell_environment = records - - /* record latest conda environment name */ - this.environment_name = conda_env - } - - def version() { - return this.runshell("conda --version") - } - - def verify() { - this.runshell("echo \$PATH") - this.runshell("which python") - this.runshell("python -c 'from pprint import pprint; import sys; pprint(sys.path)'") - } - - def command(String task, String... args) { - /* Not every Conda task accepts --quiet or --yes - so only apply $extra_args when necessary */ - ArrayList silent_args = ["--quiet", "--yes"] - boolean use_channels = false - boolean prompt_avoid = false - ArrayList channels = this.channels - - switch (task) { - case 'install': - use_channels = true - prompt_avoid = true - break - case 'create': - use_channels = true - prompt_avoid = true - break - case 'search': - use_channels = true - case 'env remove': - prompt_avoid = true - break - default: - break - } - - String cmd = "${prefix}/bin/conda ${task}" - cmd += ' ' + args.join(' ') - if (prompt_avoid) { - cmd += ' ' + silent_args.join(' ') - } - - if (use_channels) { - if (this.override) { - cmd += " --override-channels" - channels.add("defaults") - } - for (channel in channels) { - cmd += ' -c ' + channel - } - } - - println("[CONDA] ${cmd}") - return this.runshell(cmd) - } - - boolean provides(String env_name) { - def result = "" - def output = this.runshell("${this.prefix}/bin/conda env list", true) - - output.inputStream.eachLine { line -> - if (line && !line.matches('^#.*$')) { - def tmp = line.split(' ')[0].trim() - if (tmp == env_name) { - result = tmp - return - } - } - } - if (env_name == result) { - return true - } - return false - } - - int create(String name, String packages) { - String args = "-n \"${name}\"" - def proc = this.command("create", args, packages) - return proc.exitcode - } - - int install(String packages, boolean reinstall=false) { - String args = "" - if (reinstall) { - args = "--force" - } - def proc = this.command("install", args, packages) - return proc.exitcode - } - - int destroy(String name) { - String args = "-n \"${name}\"" - def proc = this.command("env remove", args) - return proc.exitcode - } -} - -static void main(String[] args) { - final String PREFIX = "/tmp/miniconda3" - final String NAME = "astroconda35" - final String PKGS = "python=3.5 numpy=1.12 drizzlepac" - - cinst = new CondaInstaller(PREFIX) - cinst.install() - - c = new Conda(PREFIX) - assert c.prefix_exists == true - - c.override = true - c.channels.add("astropy") - c.channels.add("http://ssb.stsci.edu/astroconda") - c.channels.add("conda-forge") - - if (c.provides(NAME)) { - assert c.destroy(NAME) == 0 - } - assert c.create(NAME, PKGS) == 0 - c.activate(NAME) - assert c.environment_name == NAME - assert c.provides(NAME) == true -} - - diff --git a/resources/.keep b/resources/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/org/stsci/conda.groovy b/src/org/stsci/conda.groovy new file mode 100644 index 0000000..a8e2fb7 --- /dev/null +++ b/src/org/stsci/conda.groovy @@ -0,0 +1,274 @@ +class OSInfo { + public String name + public String version + public String arch + + OSInfo () { + name = 'uname -s'.execute().text.trim() + if (name == 'Darwin') { name = 'MacOSX' } + arch = 'uname -p'.execute().text.trim() + if (arch.matches('^i.*86$')) { arch = 'x86' } + + this.name = name + this.arch = arch + this.version = 'uname -r'.execute().text.trim() + } + +} + +class CondaInstaller { + OSInfo os + String prefix + String dist_version + String url + def dist = [:] + + CondaInstaller(prefix, dist="miniconda", variant="3", version="latest") { + def distributions = [ + miniconda: [name: 'Miniconda', + variant: variant, + baseurl: 'https://repo.continuum.io/miniconda'], + anaconda: [name: 'Anaconda', + variant: variant, + baseurl: 'https://repo.continuum.io/archive'] + ] + this.os = new OSInfo() + this.dist = distributions."${dist}" + this.dist_version = version + this.prefix = prefix + this.url = "${this.dist.baseurl}/" + + "${this.dist.name}${this.dist.variant}-" + + "${this.dist_version}-${this.os.name}-${this.os.arch}.sh" + } + + void download() { + + println("Downloading $url") + File fp = new File('installer.sh') + def installer = fp.newOutputStream() + installer << new URL(this.url).openStream() + installer.close() + println("Received ${fp.length()} bytes") + } + + int install() { + if (new File(this.prefix).exists()) { + println("Skipping installation: ${this.prefix} exists.") + return 0xFF + } + + if (!new File('installer.sh').exists()) { + this.download() + } + + def cmd = "bash installer.sh -b -p ${this.prefix}" + def proc = cmd.execute() + def stdout = new StringBuffer() + + proc.inputStream.eachLine { println(it) } + + //proc.waitForProcessOutput(stdout, System.err) + //print(stdout.toString()) + + return proc.exitValue() + } + + private void detect() { + } +} + +class Conda { + public String prefix + public boolean prefix_exists + public Map shell_environment + public String environment_name + public ArrayList channels + public boolean override + + Conda (prefix) { + this.prefix = prefix + this.prefix_exists = new File(this.prefix).exists() + this.shell_environment = [:] + this.environment_name = "" + this.channels = [] + this.override = false + + if (this.prefix_exists) { + this.activate("root") + } + } + + private def runshell(String args, silent=false) { + def cmd = new String[3] + def proc_env = [:] + + if (this.shell_environment) { + proc_env = this.shell_environment + } + + cmd[0] = 'bash' + cmd[1] = '-c' + cmd[2] = args + + def process = new ProcessBuilder(cmd) + process.redirectErrorStream(true) + Map env_tmp = process.environment() + + if (proc_env) { + env_tmp <<= proc_env + } + + Process p = process.start() + if (!silent) { + p.inputStream.eachLine { println it} + } + p.waitFor() + return p + } + + void activate(String conda_env) { + def records = [:] + def env_dump = this.runshell("source ${prefix}/bin/activate ${conda_env} ; printenv", true) + + /* Split each environment keypair by first occurance of '=' */ + env_dump.inputStream.eachLine { line -> + if(line) { + def (k, v) = line.split('=', 2).collect { it.trim() } + /* Strip out envmodules if they exist, i.e. multiline variables*/ + if (k.contains("_FUNC_") || !line.contains("=")) { + return + } + records."$k" = v + } + } + + /* runshell can now natively resolve this conda installation */ + this.shell_environment = records + + /* record latest conda environment name */ + this.environment_name = conda_env + } + + def version() { + return this.runshell("conda --version") + } + + def verify() { + this.runshell("echo \$PATH") + this.runshell("which python") + this.runshell("python -c 'from pprint import pprint; import sys; pprint(sys.path)'") + } + + def command(String task, String... args) { + /* Not every Conda task accepts --quiet or --yes + so only apply $extra_args when necessary */ + ArrayList silent_args = ["--quiet", "--yes"] + boolean use_channels = false + boolean prompt_avoid = false + ArrayList channels = this.channels + + switch (task) { + case 'install': + use_channels = true + prompt_avoid = true + break + case 'create': + use_channels = true + prompt_avoid = true + break + case 'search': + use_channels = true + case 'env remove': + prompt_avoid = true + break + default: + break + } + + String cmd = "${prefix}/bin/conda ${task}" + cmd += ' ' + args.join(' ') + if (prompt_avoid) { + cmd += ' ' + silent_args.join(' ') + } + + if (use_channels) { + if (this.override) { + cmd += " --override-channels" + channels.add("defaults") + } + for (channel in channels) { + cmd += ' -c ' + channel + } + } + + println("[CONDA] ${cmd}") + return this.runshell(cmd) + } + + boolean provides(String env_name) { + def result = "" + def output = this.runshell("${this.prefix}/bin/conda env list", true) + + output.inputStream.eachLine { line -> + if (line && !line.matches('^#.*$')) { + def tmp = line.split(' ')[0].trim() + if (tmp == env_name) { + result = tmp + return + } + } + } + if (env_name == result) { + return true + } + return false + } + + int create(String name, String packages) { + String args = "-n \"${name}\"" + def proc = this.command("create", args, packages) + return proc.exitcode + } + + int install(String packages, boolean reinstall=false) { + String args = "" + if (reinstall) { + args = "--force" + } + def proc = this.command("install", args, packages) + return proc.exitcode + } + + int destroy(String name) { + String args = "-n \"${name}\"" + def proc = this.command("env remove", args) + return proc.exitcode + } +} + +static void main(String[] args) { + final String PREFIX = "/tmp/miniconda3" + final String NAME = "astroconda35" + final String PKGS = "python=3.5 numpy=1.12 drizzlepac" + + cinst = new CondaInstaller(PREFIX) + cinst.install() + + c = new Conda(PREFIX) + assert c.prefix_exists == true + + c.override = true + c.channels.add("astropy") + c.channels.add("http://ssb.stsci.edu/astroconda") + c.channels.add("conda-forge") + + if (c.provides(NAME)) { + assert c.destroy(NAME) == 0 + } + assert c.create(NAME, PKGS) == 0 + c.activate(NAME) + assert c.environment_name == NAME + assert c.provides(NAME) == true +} + + diff --git a/vars/.keep b/vars/.keep new file mode 100644 index 0000000..e69de29 -- cgit