]> kaliko git repositories - mpd-sima.git/commitdiff
New virtualenv installer in pure python
authorkaliko <kaliko@azylum.org>
Wed, 17 Dec 2014 16:58:21 +0000 (17:58 +0100)
committerkaliko <kaliko@azylum.org>
Wed, 17 Dec 2014 17:04:00 +0000 (18:04 +0100)
INSTALL
doc/Changelog
vinstall.py [new file with mode: 0755]
vinstall.sh [deleted file]

diff --git a/INSTALL b/INSTALL
index c622d77b2a5d153649e54c7f46ebf48bbfc87881..ac0b895230999b3001bdd69029ef1d3a5b9ad3fd 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-Design for python >= 3.3
+Design for python >= 3.2
 
 Requires: python-musicpd >= 0.4.0 [0],
           requests >= 2.2.0 [1]
@@ -9,18 +9,20 @@ Requires: python-musicpd >= 0.4.0 [0],
 
 Virtualenv installation:
 
-Run ./vinstall.sh to generate the python virtualenv and install requirements.
+Run "python3 ./vinstall.py" to generate the python virtualenv and install
+requirements (need at least python 3.3).
 
-Default looks for python3 on the system.
-It will setup a virtualenv within a "venv" directory (same level as vinstall.sh file).
+It will setup a virtualenv within a "venv" directory (same level as vinstall.py file).
 It should also write a shell wrapper to run mpd-sima within the virtualenv.
 
        ./vmpd-sima --help
 
-You might specify a python3 interpreter if the binary name differs from python3:
+You might prefer manual installation:
 
-    PY3=/usr/bin/python ./vinstall.sh
+       # On your system <virtualenv_command> may be "pyenv", "python3 -m venv" or "virtualenv"
+       # Refer to the relevant manual to install a python env, 3.2 minimum.
 
-You can locate the virtalenv somewhere else:
-
-    INSTALL_DIR=/tmp/crap_test/ ./vinstall.sh
+       <virtualenv_command> ./venv
+       . ./venv/bin/activate
+       ./setup.py install
+       ./venv/bin/mpd-sima --help
index 67b2cb2e08d7a72973b8046884c724cbbc9a807f..06417aa30aaf7d753ad496f7817ac99c3ea7e723 100644 (file)
@@ -2,6 +2,7 @@ MPD_sima v0.13.0
 
  * Use of MusicBrainzIdentifier by default
    Please consider tagging your library with these metadata
+ * New virtualenv installer in pure python
 
 -- kaliko jack <kaliko@azylum.org>  UNRELEASED
 
diff --git a/vinstall.py b/vinstall.py
new file mode 100755 (executable)
index 0000000..842495c
--- /dev/null
@@ -0,0 +1,149 @@
+#
+# Copyright (C) 2013 Vinay Sajip. New BSD License.
+# Copyright (C) 2014 Kaliko Jack
+#
+REQ_VER = (3,3)
+import sys
+if sys.version_info < REQ_VER:
+    print('Need at least python {0}.{1} to run this script'.format(*REQ_VER), file=sys.stderr)
+    sys.exit(1)
+
+import os
+import os.path
+import venv
+
+from subprocess import Popen, PIPE
+from threading import Thread
+from urllib.parse import urlparse
+from urllib.request import urlretrieve
+from shutil import rmtree
+
+class ExtendedEnvBuilder(venv.EnvBuilder):
+    """
+    This builder installs setuptools and pip so that you can pip or
+    easy_install other packages into the created environment.
+    """
+
+    def __init__(self, *args, **kwargs):
+        self.verbose = kwargs.pop('verbose', False)
+        super().__init__(*args, **kwargs)
+
+    def post_setup(self, context):
+        """
+        Set up any packages which need to be pre-installed into the
+        environment being created.
+
+        :param context: The information for the environment creation request
+                        being processed.
+        """
+        os.environ['VIRTUAL_ENV'] = context.env_dir
+        self.install_setuptools(context)
+        self.install_pip(context)
+        setup = os.path.abspath(os.path.join(context.env_dir, '../setup.py'))
+        self.install_script(context, 'sima', setup=setup)
+
+    def reader(self, stream, context):
+        """
+        Read lines from a subprocess' output stream and write progress
+        information to sys.stderr.
+        """
+        while True:
+            s = stream.readline()
+            if not s:
+                break
+            if not self.verbose:
+                sys.stderr.write('.')
+            else:
+                sys.stderr.write(s.decode('utf-8'))
+            sys.stderr.flush()
+        stream.close()
+
+    def install_script(self, context, name, url=None, setup=None):
+        if url:
+            binpath = context.bin_path
+            _, _, path, _, _, _ = urlparse(url)
+            fn = os.path.split(path)[-1]
+            distpath = os.path.join(binpath, fn)
+            # Download script into the env's binaries folder
+            urlretrieve(url, distpath)
+        if url:
+            args = [context.env_exe, fn]
+        else:
+            args = [context.env_exe, setup, 'install']
+            binpath = os.path.dirname(setup)
+        if self.verbose:
+            term = '\n'
+        else:
+            term = ''
+        sys.stderr.write('Installing %s ...%s' % (name, term))
+        sys.stderr.flush()
+        # Install in the env
+        p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)
+        t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))
+        t1.start()
+        t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))
+        t2.start()
+        p.wait()
+        t1.join()
+        t2.join()
+        sys.stderr.write('done.\n')
+        if url:
+            # Clean up - no longer needed
+            os.unlink(distpath)
+
+    def install_setuptools(self, context):
+        """
+        Install setuptools in the environment.
+
+        :param context: The information for the environment creation request
+                        being processed.
+        """
+        url = 'https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py'
+        self.install_script(context, 'setuptools', url)
+        # clear up the setuptools archive which gets downloaded
+        pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz')
+        files = filter(pred, os.listdir(context.bin_path))
+        for f in files:
+            f = os.path.join(context.bin_path, f)
+            os.unlink(f)
+
+    def install_pip(self, context):
+        """
+        Install pip in the environment.
+
+        :param context: The information for the environment creation request
+                        being processed.
+        """
+        url = 'https://raw.github.com/pypa/pip/master/contrib/get-pip.py'
+        self.install_script(context, 'pip', url)
+        # pip installs to "local/bin" on Linux, but it needs to be accessible
+        # from "bin" since the "activate" script prepends "bin" to $PATH
+        pip_path = os.path.join(context.env_dir, 'local', 'bin', 'pip')
+        if sys.platform != 'win32' and os.path.exists(pip_path):
+            self.symlink_or_copy(pip_path, os.path.join(context.bin_path, 'pip'))
+
+
+def main(args=None):
+    root = os.path.dirname(os.path.abspath(__file__))
+    vdir = os.path.join(root, 'venv')
+    builder = ExtendedEnvBuilder(clear=True, verbose=False)
+    builder.create(vdir)
+    # clean up
+    for residu in ['MPD_sima.egg-info', 'dist', 'build']:
+        if os.path.exists(os.path.join(root, residu)):
+            rmtree(os.path.join(root, residu))
+    # Write wrapper
+    with open(os.path.join(root, 'vmpd-sima'),'w') as fd:
+        fd.write('#!/bin/sh\n')
+        fd.write('. "{}/venv/bin/activate"\n'.format(root))
+        fd.write('"{}/venv/bin/mpd-sima" "$@"'.format(root))
+    os.chmod(os.path.join(root, 'vmpd-sima'), 0o744)
+
+if __name__ == '__main__':
+    rc = 1
+    try:
+        main()
+        rc = 0
+    except ImportError as e:
+        print('Error: %s' % e)
+    sys.exit(rc)
diff --git a/vinstall.sh b/vinstall.sh
deleted file mode 100755 (executable)
index 1afb3b8..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh
-#
-#   vinstall.sh
-#
-#   version: 0.2 : Date: 2013/11/13
-#
-#   TODO:
-#           *
-DEBUG=${DEBUG:-"0"}     #  Set to 1 in order to enable DEBUG message.
-                        ## Use "export DEBUG=1" in the calling script to enable it
-                        ##  or run:
-                        #           >$ DEBUG=1 script_name.sh
-                        ## Only error message will be printed with DEBUG="0"
-
-
-PY3=${PY3:-$(which python3)}
-
-# Test virtualenv presence
-[ -x "$(which virtualenv)" ] || { echo "Cannot find virtualenv executable!"; exit 1; }
-[ -x "$(which ${PY3})"  ] || { echo "Cannot find a python3.3 interpreter!"; exit 1; }
-[ "$DEBUG" != "0" ] && echo "python: $PY3"
-
-INSTALL_DIR=${INSTALL_DIR:-$(dirname $0)}
-# canonicalize path
-INSTALL_DIR=$(readlink -f ${INSTALL_DIR})
-[ "$DEBUG" != "0" ] && echo "install dir: $INSTALL_DIR"
-
-VENV_OPTIONS="--python=$PY3 --prompt="sima_venv" --no-site-packages --clear"
-[ "$DEBUG" = "0" ] && VENV_OPTIONS="$VENV_OPTIONS --quiet"
-
-virtualenv $VENV_OPTIONS $INSTALL_DIR/venv || { echo "something went wrong generating virtualenv"; exit 1; }
-
-. $INSTALL_DIR/venv/bin/activate
-
-PIP_OPTIONS=""
-[ "$DEBUG" = "0" ] && PIP_OPTIONS="$PIP_OPTIONS --quiet"
-
-pip install -e . || exit 1
-
-echo Installing mpd-sima
-$(dirname $0)/setup.py --quiet install || exit 1
-
-deactivate
-
-SIMA_LAUNCHER=mpd-sima
-SIMA_VLAUNCHER=$INSTALL_DIR/vmpd-sima
-
-cat << EOF > "$SIMA_VLAUNCHER"
-#!/bin/sh
-. $INSTALL_DIR/venv/bin/activate
-$INSTALL_DIR/$SIMA_LAUNCHER "\$@"
-EOF
-chmod +x $SIMA_VLAUNCHER
-
-echo Cleaning up
-rm -rf $(dirname $0)/dist
-rm -rf $(dirname $0)/build
-rm -rf $(dirname $0)/sima.egg-info
-
-echo
-
-# vim: fileencoding=utf8