Source code for pymyinstall.win_installer.win_extract

# -*- coding: utf-8 -*-
"""
Helpers, inspired from `utils.py <https://github.com/winpython/winpython/blob/master/winpython/utils.py>`_


:githublink:`%|py|6`
"""
from __future__ import print_function

import sys
import os
import os.path as osp
import subprocess
import tarfile
import zipfile
import fnmatch
# import winreg
import glob
import shutil
from ..installcustom.install_custom_python import unzip7_files

from .win_helper import patch_shebang_line

if sys.version_info[0] == 2:
    FileNotFoundError = Exception


[docs]def is_program_installed(basename): """ Return program absolute path if installed in PATH Otherwise, return None :param basename: base name :return: boolean :githublink:`%|py|33` """ if os.path.exists(basename): return True for path in os.environ["PATH"].split(os.pathsep): abspath = osp.join(path, basename) if osp.isfile(abspath): return abspath
[docs]def extract_msi(fname, targetdir=None, verbose=False, fLOG=print): """ Extract .msi installer to a temporary directory (if targetdir is None). Return the temporary directory path :param fname: local installer (exe) :param targetdir: where to install :param verbose: verbose :param fLOG: logging function :return: targetdir :githublink:`%|py|52` """ extract = 'msiexec.exe' bname = osp.basename(fname) args = ['/a', '%s' % bname] if not verbose: args += ['/quiet', '/qn'] args += ['TARGETDIR=%s' % targetdir] cmd = [extract] + args fLOG("[pymy] RUN: ", cmd) subprocess.call(cmd, cwd=osp.dirname(fname)) fLOG('fname=%s' % fname) fLOG('TARGETDIR=%s' % targetdir) if "python-3" in fname.lower(): subprocess.call( [r'%s\%s' % (targetdir, 'python.exe'), '-m', 'ensurepip'], cwd=osp.dirname(r'%s\%s' % (targetdir, 'pythons.exe'))) # We patch ensurepip live (shame) !!!! # rational: https://github.com/pypa/pip/issues/2328 for fname in glob.glob(r'%s\Scripts\*.exe' % targetdir): patch_shebang_line(fname) return targetdir
[docs]def extract_exe(fname, targetdir=None, verbose=False, fLOG=print, szip="7z.exe"): """ Extract *.exe* archive to a temporary directory (if targetdir is None). Return the temporary directory path :param fname: local installer (exe) :param targetdir: where to install :param verbose: verbose :param szip: path to 7z.exe :param fLOG: logging function :return: targetdir :githublink:`%|py|87` """ extract = szip if not is_program_installed(extract): pp = os.environ["PATH"].split(";") raise FileNotFoundError( "Required program '%s' was not found in PATH:\n %s" % (extract, "\n ".join(pp))) bname = osp.basename(fname) args = ['x', '-o%s' % targetdir, '-aos', bname] if verbose: retcode = subprocess.call([extract] + args, cwd=osp.dirname(fname)) else: p = subprocess.Popen([extract] + args, cwd=osp.dirname(fname), stdout=subprocess.PIPE) p.communicate() p.stdout.close() retcode = p.returncode if retcode != 0: raise RuntimeError("Failed to extract %s (return code: %d),\nCMD: %s\nCMD*: %s\nin %s" % (fname, retcode, str([extract] + args), " ".join([extract] + args), targetdir)) return targetdir
[docs]def extract_archive(fname, targetdir=None, verbose=False, fLOG=print): """ Extract .zip, .exe (considered to be a zip archive) or .tar.gz archive to a temporary directory (if targetdir is None). Return the temporary directory path :param fname: zip file or exe file :param targetdir: where to install :param verbose: verbose :param fLOG: logging function :return: targetdir :githublink:`%|py|120` """ if osp.splitext(fname)[1] in ('.zip', '.exe'): obj = zipfile.ZipFile(fname, mode="r") elif osp.splitext(fname)[1] in ('.7z'): unzip7_files(fname, fLOG=fLOG, dest=targetdir) return targetdir elif fname.endswith('.tar.gz'): obj = tarfile.open(fname, mode='r:gz') else: raise RuntimeError("Unsupported archive filename %s" % fname) obj.extractall(path=targetdir) return targetdir
[docs]def clean_msi(folder, pattern, verbose=False, fLOG=print): """ clean all files follwing a specific pattern :param folder: folder :param pattern: files to remove :param verbose: display more information :param fLOG: logging function :return: removed files (as operation) :githublink:`%|py|143` """ def find(loc, pattern): exes = [] for root, dirnames, filenames in os.walk(loc): for filename in fnmatch.filter(filenames, pattern): exes.append(os.path.join(root, filename)) return exes remove = find(folder, pattern) operations = [] for r in remove: if verbose: fLOG("[pymy] remove", r) os.remove(r) operations.append(("remove", r)) return operations
[docs]def extract_copy(fname, targetdir=None, verbose=False, fLOG=print, szip=None): """ Copy *.exe* to targetdir :param fname: local installer (exe) :param targetdir: where to install :param verbose: verbose :param fLOG: logging function :param szip: unused :return: targetdir :githublink:`%|py|170` """ shutil.copy(fname, targetdir)