]> kaliko git repositories - mpd-sima.git/blob - vinstall.py
Add more info in crash report (Closes #56)
[mpd-sima.git] / vinstall.py
1 #!/usr/bin/env python3
2 # Copyright (C) 2013 Vinay Sajip. New BSD License.
3 # Copyright (C) 2014, 2020 kaliko <kaliko@azylum.org>
4 #
5 from __future__ import print_function
6
7 REQ_VER = (3,4)
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         setup = os.path.abspath(os.path.join(context.env_dir, '../setup.py'))
43         self.install_script(context, 'sima', setup=setup)
44
45     def reader(self, stream, context):
46         """
47         Read lines from a subprocess' output stream and write progress
48         information to sys.stderr.
49         """
50         while True:
51             s = stream.readline()
52             if not s:
53                 break
54             if not self.verbose:
55                 sys.stderr.write('.')
56             else:
57                 sys.stderr.write(s.decode('utf-8'))
58             sys.stderr.flush()
59         stream.close()
60
61     def install_script(self, context, name, url=None, setup=None):
62         if url:
63             binpath = context.bin_path
64             _, _, path, _, _, _ = urlparse(url)
65             fn = os.path.split(path)[-1]
66             distpath = os.path.join(binpath, fn)
67             # Download script into the env's binaries folder
68             urlretrieve(url, distpath)
69         if url:
70             args = [context.env_exe, fn]
71         else:
72             args = [context.env_exe, setup, 'install']
73             binpath = os.path.dirname(setup)
74         if self.verbose:
75             term = '\n'
76         else:
77             term = ''
78         sys.stderr.write('Installing %s ...%s' % (name, term))
79         sys.stderr.flush()
80         # Install in the env
81         p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)
82         t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))
83         t1.start()
84         t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))
85         t2.start()
86         p.wait()
87         t1.join()
88         t2.join()
89         sys.stderr.write('done.\n')
90         if url:
91             # Clean up - no longer needed
92             os.unlink(distpath)
93
94
95 def main(args=None):
96     root = os.path.dirname(os.path.abspath(__file__))
97     vdir = os.path.join(root, 'venv')
98     builder = ExtendedEnvBuilder(clear=True, verbose=False, with_pip=True)
99     builder.create(vdir)
100     # clean up
101     for residu in ['MPD_sima.egg-info', 'dist', 'build']:
102         if os.path.exists(os.path.join(root, residu)):
103             rmtree(os.path.join(root, residu))
104     # Write wrapper
105     with open(os.path.join(root, 'vmpd-sima'),'w') as fd:
106         fd.write('#!/bin/sh\n')
107         fd.write('. "{}/venv/bin/activate"\n'.format(root))
108         fd.write('"{}/venv/bin/mpd-sima" "$@"'.format(root))
109     os.chmod(os.path.join(root, 'vmpd-sima'), 0o744)
110
111
112 if __name__ == '__main__':
113     rc = 1
114     try:
115         main()
116         rc = 0
117     except ImportError as e:
118         print('Error: %s' % e)
119     sys.exit(rc)