Last active
January 3, 2016 11:09
-
-
Save Jc2k/8454645 to your computer and use it in GitHub Desktop.
Thinking about python virtualenvs and node/npm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
import os | |
import tempfile | |
import shutil | |
import tarfile | |
import sys | |
import subprocess | |
import optparse | |
NPM_URL = "http://registry.npmjs.org/npm/-/npm-1.3.23.tgz" | |
def search_path(b): | |
path = os.environ.get("PATH", "/usr/bin").split(":") | |
for p in path: | |
binary = os.path.join(p, b) | |
if os.path.exists(binary): | |
return binary | |
def bootstrap_npm_from_internet(virtualenv_dir, node=None): | |
# This method can install NPM when no NPM is available. In practice this | |
# doesn't happen any more - npm ships with nodejs these days | |
node = node or search_path("node") | |
if not node: | |
return False | |
d = tempfile.mkdtemp(dir=virtualenv_dir) | |
try: | |
package_tgz = os.path.join(d, "npm.tgz") | |
package_dir = os.path.join(d, "npm") | |
cli_js = os.path.join(package_dir, "package", "cli.js") | |
print("-> Downloading npm bootstrap (%s)" % NPM_URL) | |
try: | |
import urllib.request | |
urllib.request.urlretrieve(NPM_URL, package_tgz) | |
except ImportError: | |
import urllib | |
urllib.urlretrieve(NPM_URL, package_tgz) | |
print("-> Extracting") | |
t = tarfile.open(package_tgz) | |
t.extractall(package_dir) | |
print("-> Installing") | |
subprocess.check_call([node, cli_js, "install", "-g", "--prefix", virtualenv_dir, "npm"]) | |
finally: | |
shutil.rmtree(d) | |
def bootstrap_npm_from_npm(virtualenv_dir): | |
# Given a working npm, install it somewhere else | |
print("-> Installing") | |
npm = search_path("npm") | |
if not npm: | |
return False | |
subprocess.check_call([npm, "install", "-g", "--prefix", virtualenv_dir, "npm"]) | |
return True | |
def setup_virtualenv(virtualenv_dir, node=None): | |
virtualenv_dir = os.path.abspath(virtualenv_dir) | |
bin_dir = os.path.join(virtualenv_dir, "bin") | |
lib_dir = os.path.join(virtualenv_dir, "lib") | |
node_modules_dir = os.path.join(lib_dir, "node_modules") | |
if not os.path.exists(os.path.join(bin_dir, "npm")): | |
if not bootstrap_npm_from_npm(virtualenv_dir): | |
if not bootstrap_npm_from_internet(virtualenv_dir, node=node): | |
print("Cannot find existing 'npm'/'node'") | |
sys.exit(1) | |
print("-> Setting npm default settings") | |
with open(os.path.join(node_modules_dir, "npm", "npmrc"), "w") as fp: | |
fp.write("\n".join([ | |
"prefix=%s" % virtualenv_dir, | |
"global=true", | |
])) | |
print("Done.") | |
if __name__ == "__main__": | |
p = optparse.OptionParser() | |
p.add_option("-n", "--node") | |
opts, args = p.parse_args() | |
if len(args) != 1: | |
p.print_help() | |
sys.exit(1) | |
setup_virtualenv(args[0], node=opts.node) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment