Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Helpers, inspired from `utils.py <https://github.com/winpython/winpython/blob/master/winpython/utils.py>`_
5"""
6from __future__ import print_function
8import sys
9import os
10import os.path as osp
11import subprocess
12import tarfile
13import zipfile
14import fnmatch
15# import winreg
16import glob
17import shutil
18from ..installcustom.install_custom_python import unzip7_files
20from .win_helper import patch_shebang_line
22if sys.version_info[0] == 2:
23 FileNotFoundError = Exception
26def is_program_installed(basename):
27 """
28 Return program absolute path if installed in PATH
29 Otherwise, return None
31 @param basename base name
32 @return boolean
33 """
34 if os.path.exists(basename):
35 return True
36 for path in os.environ["PATH"].split(os.pathsep):
37 abspath = osp.join(path, basename)
38 if osp.isfile(abspath):
39 return abspath
42def extract_msi(fname, targetdir=None, verbose=False, fLOG=print):
43 """
44 Extract .msi installer to a temporary directory (if targetdir
45 is None). Return the temporary directory path
47 @param fname local installer (exe)
48 @param targetdir where to install
49 @param verbose verbose
50 @param fLOG logging function
51 @return targetdir
52 """
53 extract = 'msiexec.exe'
54 bname = osp.basename(fname)
55 args = ['/a', '%s' % bname]
56 if not verbose:
57 args += ['/quiet', '/qn']
58 args += ['TARGETDIR=%s' % targetdir]
59 cmd = [extract] + args
60 fLOG("[pymy] RUN: ", cmd)
61 subprocess.call(cmd, cwd=osp.dirname(fname))
62 fLOG('fname=%s' % fname)
63 fLOG('TARGETDIR=%s' % targetdir)
65 if "python-3" in fname.lower():
66 subprocess.call(
67 [r'%s\%s' % (targetdir, 'python.exe'), '-m', 'ensurepip'],
68 cwd=osp.dirname(r'%s\%s' % (targetdir, 'pythons.exe')))
69 # We patch ensurepip live (shame) !!!!
70 # rational: https://github.com/pypa/pip/issues/2328
71 for fname in glob.glob(r'%s\Scripts\*.exe' % targetdir):
72 patch_shebang_line(fname)
73 return targetdir
76def extract_exe(fname, targetdir=None, verbose=False, fLOG=print, szip="7z.exe"):
77 """
78 Extract *.exe* archive to a temporary directory (if targetdir
79 is None). Return the temporary directory path
81 @param fname local installer (exe)
82 @param targetdir where to install
83 @param verbose verbose
84 @param szip path to 7z.exe
85 @param fLOG logging function
86 @return targetdir
87 """
88 extract = szip
89 if not is_program_installed(extract):
90 pp = os.environ["PATH"].split(";")
91 raise FileNotFoundError(
92 "Required program '%s' was not found in PATH:\n %s" % (extract, "\n ".join(pp)))
93 bname = osp.basename(fname)
94 args = ['x', '-o%s' % targetdir, '-aos', bname]
95 if verbose:
96 retcode = subprocess.call([extract] + args, cwd=osp.dirname(fname))
97 else:
98 p = subprocess.Popen([extract] + args, cwd=osp.dirname(fname),
99 stdout=subprocess.PIPE)
100 p.communicate()
101 p.stdout.close()
102 retcode = p.returncode
103 if retcode != 0:
104 raise RuntimeError("Failed to extract %s (return code: %d),\nCMD: %s\nCMD*: %s\nin %s"
105 % (fname, retcode, str([extract] + args), " ".join([extract] + args), targetdir))
106 return targetdir
109def extract_archive(fname, targetdir=None, verbose=False, fLOG=print):
110 """
111 Extract .zip, .exe (considered to be a zip archive) or .tar.gz archive
112 to a temporary directory (if targetdir is None).
113 Return the temporary directory path
115 @param fname zip file or exe file
116 @param targetdir where to install
117 @param verbose verbose
118 @param fLOG logging function
119 @return targetdir
120 """
121 if osp.splitext(fname)[1] in ('.zip', '.exe'):
122 obj = zipfile.ZipFile(fname, mode="r")
123 elif osp.splitext(fname)[1] in ('.7z'):
124 unzip7_files(fname, fLOG=fLOG, dest=targetdir)
125 return targetdir
126 elif fname.endswith('.tar.gz'):
127 obj = tarfile.open(fname, mode='r:gz')
128 else:
129 raise RuntimeError("Unsupported archive filename %s" % fname)
130 obj.extractall(path=targetdir)
131 return targetdir
134def clean_msi(folder, pattern, verbose=False, fLOG=print):
135 """
136 clean all files follwing a specific pattern
138 @param folder folder
139 @param pattern files to remove
140 @param verbose display more information
141 @param fLOG logging function
142 @return removed files (as operation)
143 """
144 def find(loc, pattern):
145 exes = []
146 for root, dirnames, filenames in os.walk(loc):
147 for filename in fnmatch.filter(filenames, pattern):
148 exes.append(os.path.join(root, filename))
149 return exes
150 remove = find(folder, pattern)
151 operations = []
152 for r in remove:
153 if verbose:
154 fLOG("[pymy] remove", r)
155 os.remove(r)
156 operations.append(("remove", r))
157 return operations
160def extract_copy(fname, targetdir=None, verbose=False, fLOG=print, szip=None):
161 """
162 Copy *.exe* to targetdir
164 @param fname local installer (exe)
165 @param targetdir where to install
166 @param verbose verbose
167 @param fLOG logging function
168 @param szip unused
169 @return targetdir
170 """
171 shutil.copy(fname, targetdir)