]> kaliko git repositories - mpd-sima.git/blob - vinstall.py
Changed tracks equality test
[mpd-sima.git] / vinstall.py
1 #!/usr/bin/env python3
2 # Copyright (C) 2013 Vinay Sajip. New BSD License.
3 # Copyright (C) 2014 Kaliko Jack
4 #
5 from __future__ import print_function
6
7 REQ_VER = (3,3)
8 import sys
9 if sys.version_info < REQ_VER:
10     print('Need at least python {0}.{1} to run this script'.format(*REQ_VER), file=sys.stderr)
11     sys.exit(1)
12
13 import os
14 import os.path
15 import venv
16
17 from subprocess import Popen, PIPE
18 from threading import Thread
19 from urllib.parse import urlparse
20 from urllib.request import urlretrieve
21 from shutil import rmtree
22
23 class ExtendedEnvBuilder(venv.EnvBuilder):
24     """
25     This builder installs setuptools and pip so that you can pip or
26     easy_install other packages into the created environment.
27     """
28
29     def __init__(self, *args, **kwargs):
30         self.verbose = kwargs.pop('verbose', False)
31         super().__init__(*args, **kwargs)
32
33     def post_setup(self, context):
34         """
35         Set up any packages which need to be pre-installed into the
36         environment being created.
37
38         :param context: The information for the environment creation request
39                         being processed.
40         """
41         os.environ['VIRTUAL_ENV'] = context.env_dir
42         self.install_setuptools(context)
43         self.install_pip(context)
44         setup = os.path.abspath(os.path.join(context.env_dir, '../setup.py'))
45         self.install_script(context, 'sima', setup=setup)
46
47     def reader(self, stream, context):
48         """
49         Read lines from a subprocess' output stream and write progress
50         information to sys.stderr.
51         """
52         while True:
53             s = stream.readline()
54             if not s:
55                 break
56             if not self.verbose:
57                 sys.stderr.write('.')
58             else:
59                 sys.stderr.write(s.decode('utf-8'))
60             sys.stderr.flush()
61         stream.close()
62
63     def install_script(self, context, name, url=None, setup=None):
64         if url:
65             binpath = context.bin_path
66             _, _, path, _, _, _ = urlparse(url)
67             fn = os.path.split(path)[-1]
68             distpath = os.path.join(binpath, fn)
69             # Download script into the env's binaries folder
70             urlretrieve(url, distpath)
71         if url:
72             args = [context.env_exe, fn]
73         else:
74             args = [context.env_exe, setup, 'install']
75             binpath = os.path.dirname(setup)
76         if self.verbose:
77             term = '\n'
78         else:
79             term = ''
80         sys.stderr.write('Installing %s ...%s' % (name, term))
81         sys.stderr.flush()
82         # Install in the env
83         p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)
84         t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))
85         t1.start()
86         t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))
87         t2.start()
88         p.wait()
89         t1.join()
90         t2.join()
91         sys.stderr.write('done.\n')
92         if url:
93             # Clean up - no longer needed
94             os.unlink(distpath)
95
96     def install_setuptools(self, context):
97         """
98         Install setuptools in the environment.
99
100         :param context: The information for the environment creation request
101                         being processed.
102         """
103         url = 'https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py'
104         self.install_script(context, 'setuptools', url)
105         # clear up the setuptools archive which gets downloaded
106         pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz')
107         files = filter(pred, os.listdir(context.bin_path))
108         for f in files:
109             f = os.path.join(context.bin_path, f)
110             os.unlink(f)
111
112     def install_pip(self, context):
113         """
114         Install pip in the environment.
115
116         :param context: The information for the environment creation request
117                         being processed.
118         """
119         url = 'https://bootstrap.pypa.io/get-pip.py'
120         self.install_script(context, 'pip', url)
121         # pip installs to "local/bin" on Linux, but it needs to be accessible
122         # from "bin" since the "activate" script prepends "bin" to $PATH
123         pip_path = os.path.join(context.env_dir, 'local', 'bin', 'pip')
124         if sys.platform != 'win32' and os.path.exists(pip_path):
125             self.symlink_or_copy(pip_path, os.path.join(context.bin_path, 'pip'))
126
127
128 def main(args=None):
129     root = os.path.dirname(os.path.abspath(__file__))
130     vdir = os.path.join(root, 'venv')
131     builder = ExtendedEnvBuilder(clear=True, verbose=False)
132     builder.create(vdir)
133     # clean up
134     for residu in ['MPD_sima.egg-info', 'dist', 'build']:
135         if os.path.exists(os.path.join(root, residu)):
136             rmtree(os.path.join(root, residu))
137     # Write wrapper
138     with open(os.path.join(root, 'vmpd-sima'),'w') as fd:
139         fd.write('#!/bin/sh\n')
140         fd.write('. "{}/venv/bin/activate"\n'.format(root))
141         fd.write('"{}/venv/bin/mpd-sima" "$@"'.format(root))
142     os.chmod(os.path.join(root, 'vmpd-sima'), 0o744)
143
144 if __name__ == '__main__':
145     rc = 1
146     try:
147         main()
148         rc = 0
149     except ImportError as e:
150         print('Error: %s' % e)
151     sys.exit(rc)