text:
"""
WinPython build script

Created on Sun Aug 12 11:17:50 2012
"""

from __future__ import print_function

import os
# import os.path as osp
from pathlib import Path
import re
import subprocess
import shutil
import sys

# Local imports
from winpython import wppm, utils
import diff

# CHANGELOGS_DIR = osp.join(
#     osp.dirname(__file__), 'changelogs'
# )
CHANGELOGS_DIR = str(Path(__file__).parent / 'changelogs')
# assert osp.isdir(CHANGELOGS_DIR)
assert Path(CHANGELOGS_DIR).is_dir()

def get_drives():
    """Return all active drives"""
    import win32api

    return win32api.GetLogicalDriveStrings().split('\000')[
        :-1
    ]

def get_nsis_exe():
    """Return NSIS executable"""
    # localdir = osp.join(sys.prefix, os.pardir, os.pardir)
    localdir = str(Path(sys.prefix).parent.parent)
    for drive in get_drives():
        for dirname in (
            r'C:\Program Files',
            r'C:\Program Files (x86)',
            drive + r'PortableApps\NSISPortableANSI',
            drive + r'PortableApps\NSISPortable',
            # osp.join(localdir, 'NSISPortableANSI'),
            str(Path(localdir) / 'NSISPortableANSI'),
            # osp.join(localdir, 'NSISPortable'),
            str(Path(localdir) / 'NSISPortable'),
        ):
            for subdirname in ('.', 'App'):
                #exe = osp.join(
                #    dirname,
                #    subdirname,
                #    'NSIS',
                #    'makensis.exe',
                #)
                exe = str(Path(dirname) / subdirname / 'NSIS' / 'makensis.exe')
                # if osp.isfile(exe):
                if Path(exe).is_file():
                    return exe
    else:
        raise RuntimeError(
            "NSIS is not installed on this computer."
        )

NSIS_EXE = get_nsis_exe()  # NSIS Compiler

def get_iscc_exe():
    """Return ISCC executable"""
    # localdir = osp.join(sys.prefix, os.pardir, os.pardir)
    localdir = str(Path(sys.prefix).parent.parent)
    for drive in get_drives():
        for dirname in (
            r'C:\Program Files',
            r'C:\Program Files (x86)',
            # drive+r'PortableApps\NSISPortableANSI',
            # drive+r'PortableApps\NSISPortable',
            # osp.join(localdir, 'NSISPortableANSI'),
            # osp.join(localdir, 'Inno Setup 5'),
            str(Path(localdir) / 'Inno Setup 5'),
        ):
            for subdirname in ('.', 'App'):
                #exe = osp.join(
                #    dirname,
                #    subdirname,
                #    'Inno Setup 5',
                #    'iscc.exe',
                #)
                exe = str(Path(dirname) / subdirname / 'Inno Setup 5' / 'iscc.exe')
                # if osp.isfile(exe):
                if Path(exe).is_file():
                    return exe
    else:
        #raise RuntimeError(
        print(    "Inno Setup 5 is not installed on this computer."
        )

ISCC_EXE = get_iscc_exe()  # Inno Setup Compiler (iscc.exe)

def get_7zip_exe():
    """Return 7zip executable"""
    # localdir = osp.join(sys.prefix, os.pardir, os.pardir)
    localdir = str(Path(sys.prefix).parent.parent)
    for drive in get_drives():
        for dirname in (
            r'C:\Program Files',
            r'C:\Program Files (x86)',
            # osp.join(localdir, '7-Zip'),
            str(Path(localdir) / '7-Zip'),
        ):
            for subdirname in ('.', 'App'):
                #exe = osp.join(
                #    dirname, subdirname, '7-Zip', '7z.exe'
                #)
                exe = str(Path(dirname) / subdirname / '7-Zip' / '7z.exe')
                # include = osp.join(dirname, subdirname, '7-Zip', 'include')
                # if osp.isfile(exe):
                if Path(exe).is_file():
                    return exe
    else:
        raise RuntimeError(
            "7-Zip is not installed on this computer."
        )

SEVENZIP_EXE = (
    get_7zip_exe()
)  # Inno Setup Compiler (iscc.exe)

def replace_in_nsis_file(fname, data):
    """Replace text in line starting with *start*, from this position:
    data is a list of (start, text) tuples"""
    fd = open(fname, 'U')
    lines = fd.readlines()
    fd.close()
    for idx, line in enumerate(lines):
        for start, text in data:
            if start not in (
                'Icon',
                'OutFile',
            ) and not start.startswith('!'):
                start = '!define ' + start
            if line.startswith(start + ' '):
                lines[idx] = (
                    line[: len(start) + 1]
                    + ('"%s"' % text)
                    + '\n'
                )
    fd = open(fname, 'w')
    fd.writelines(lines)
    print('iss for ', fname, 'is', lines)
    fd.close()

def replace_in_iss_file(fname, data):
    """Replace text in line starting with *start*, from this position:
    data is a list of (start, text) tuples"""
    fd = open(fname, 'U')
    lines = fd.readlines()
    fd.close()
    for idx, line in enumerate(lines):
        for start, text in data:
            if start not in (
                'Icon',
                'OutFile',
            ) and not start.startswith('!'):
                start = '#define ' + start
            if line.startswith(start + ' '):
                lines[idx] = (
                    line[: len(start) + 1]
                    + ('"%s"' % text)
                    + '\n'
                )
    fd = open(fname, 'w')
    fd.writelines(lines)
    print('Inno Setup for ', fname, 'is', lines)
    fd.close()

def replace_in_7zip_file(fname, data):
    """Replace text in line starting with *start*, from this position:
    data is a list of (start, text) tuples"""
    fd = open(fname, 'U')
    lines = fd.readlines()
    fd.close()
    for idx, line in enumerate(lines):
        for start, text in data:
            if start not in (
                'Icon',
                'OutFile',
            ) and not start.startswith('!'):
                start = 'set ' + start
            if line.startswith(start + '='):
                lines[idx] = (
                    line[: len(start) + 1]
                    + ('%s' % text)
                    + '\n'
                )
    fd = open(fname, 'w')
    fd.writelines(lines)
    print('7-zip for ', fname, 'is', lines)
    fd.close()

def build_nsis(srcname, dstname, data):
    """Build NSIS script"""
    #portable_dir = osp.join(
    #    osp.dirname(osp.abspath(__file__)), 'portable'
    #)
    portable_dir = str(Path(__file__).resolve().parent / 'portable')
    # shutil.copy(osp.join(portable_dir, srcname), dstname)
    shutil.copy(str(Path(portable_dir) / srcname), dstname)
    data = [
        (
            '!addincludedir',
            # osp.join(portable_dir, 'include'),
            str(Path(portable_dir) / 'include'),
        )
    ] + list(data)
    replace_in_nsis_file(dstname, data)
    try:
        retcode = subprocess.call(
            '"%s" -V2 "%s"' % (NSIS_EXE, dstname),
            shell=True,
            stdout=sys.stderr,
        )
        if retcode < 0:
            print(
                "Child was terminated by signal",
                -retcode,
                file=sys.stderr,
            )
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)
    os.remove(dstname)

def build_iss(srcname, dstname, data):
    """Build Inno Setup Script"""
    #portable_dir = osp.join(
    #    osp.dirname(osp.abspath(__file__)), 'portable'
    #)
    portable_dir = str(Path(__file__).resolve().parent / 'portable')
    # shutil.copy(osp.join(portable_dir, srcname), dstname)
    shutil.copy(str(Path(portable_dir) / srcname), dstname)
    data = [('PORTABLE_DIR', portable_dir)] + list(data)
    replace_in_iss_file(dstname, data)
    try:
        retcode = subprocess.call(
            '"%s"  "%s"' % (ISCC_EXE, dstname),
            shell=True,
            stdout=sys.stderr,
        )
        if retcode < 0:
            print(
                "Child was terminated by signal",
                -retcode,
                file=sys.stderr,
            )
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)
    # os.remove(dstname)

def build_7zip(srcname, dstname, data):
    """7-Zip Setup Script"""
    #portable_dir = osp.join(
    #    osp.dirname(osp.abspath(__file__)), 'portable'
    #)
    portable_dir = str(Path(__file__).resolve().parent / 'portable')
    #shutil.copy(osp.join(portable_dir, srcname), dstname)
    shutil.copy(str(Path(portable_dir) / srcname), dstname)
    data = [
        ('PORTABLE_DIR', portable_dir),
        ('SEVENZIP_EXE', SEVENZIP_EXE),
    ] + list(data)
    replace_in_7zip_file(dstname, data)
    try:
        # insted of a 7zip command line, we launch a script that does it
        # retcode = subprocess.call('"%s"  "%s"' % (SEVENZIP_EXE, dstname),
        retcode = subprocess.call(
            '"%s"  ' % (dstname),
            shell=True,
            stdout=sys.stderr,
        )
        if retcode < 0:
            print(
                "Child was terminated by signal",
                -retcode,
                file=sys.stderr,
            )
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)
    # os.remove(dstname)

class WinPythonDistribution(object):
    """WinPython distribution"""

    MINGW32_PATH = r'\t\mingw32\bin'
    R_PATH = r'\t\R\bin'
    JULIA_PATH = r'\t\Julia\bin'
    NODEJS_PATH = r'\n'  # r'\t\n'

    def __init__(
        self,
        build_number,
        release_level,
        target,
        wheeldir,
        toolsdirs=None,
        verbose=False,
        simulation=False,
        basedir=None,
        install_options=None,
        flavor='',
        docsdirs=None,
    ):
        assert isinstance(build_number, int)
        assert isinstance(release_level, str)
        self.build_number = build_number
        self.release_level = release_level
        self.target = target
        self.wheeldir = wheeldir
        if toolsdirs is None:
            toolsdirs = []
        self._toolsdirs = toolsdirs
        if docsdirs is None:
            docsdirs = []
        self._docsdirs = docsdirs
        self.verbose = verbose
        self.winpydir = None  # new WinPython BaseDirectory
        self.distribution = None
        self.installed_packages = []
        self.simulation = simulation
        self.basedir = (
            basedir
        )  # added to build from winpython
        self.install_options = install_options
        self.flavor = flavor

        # python_fname = the .zip of the python interpreter PyPy !
        # impot re
        # re.match(r'(pypy3*-v|python-)([0-9\.rcba]*)((\.|\-)(amd64|win64)?\.zip')
        try:  # PyPy
            self.python_fname = self.get_package_fname(
             r'(pypy3|python-)([0-9]|[a-zA-Z]|.)*.zip'
             )
        except:  # normal Python
            self.python_fname = self.get_package_fname(
            r'python-([0-9\.rcba]*)((\.|\-)amd64)?\.(zip|zip)'
             )

        # osp.join(self.winpydir, self.python_name) = Directory of Python exec
        # self.pythondir =osp.join(self.winpydir, self.python_name)
        # self.python_name = osp.basename(self.python_fname)[
        self.python_name = Path(self.python_fname).name[
            :-4
        ]
        self.distname = 'winUNKNOWN' #win%s' % self.python_name #  PyPy ?
        #vlst = (
        #    re.match(r'winpython-([0-9\.]*)', self.distname)
        #    .groups()[0]
        #    .split('.')
        #)
        self.python_fullversion = 'winUNKNOWN' # '.'.join(vlst[:3])

    @property
    def package_index_wiki(self):
        """Return Package Index page in Wiki format"""
        installed_tools = []

        def get_tool_path_file(relpath):
            if self.simulation:
                for dirname in self.toolsdirs:
                    path = dirname + relpath.replace(
                        r'\t', ''
                    )
                    if Path(path).is_file():
                        return path
            else:
                path = self.winpydir + relpath
                if Path(path).is_file():
                    return path

        def get_tool_path_dir(relpath):
            if self.simulation:
                for dirname in self.toolsdirs:
                    path = dirname + relpath.replace(
                        r'\t', ''
                    )
                    if Path(path).is_dir():
                        return path
            else:
                path = self.winpydir + relpath
                if Path(path).is_dir():
                    return path

        if get_tool_path_file(r'\t\SciTE.exe'):
            installed_tools += [('SciTE', '3.3.7')]

        rpath = get_tool_path_dir(self.R_PATH)
        if rpath is not None:
            rver = utils.get_r_version(rpath)
            installed_tools += [('R', rver)]

        juliapath = get_tool_path_dir(self.JULIA_PATH)
        if juliapath is not None:
            juliaver = utils.get_julia_version(juliapath)
            installed_tools += [('Julia', juliaver)]

        nodepath = get_tool_path_dir(self.NODEJS_PATH)
        if nodepath is not None:
            nodever = utils.get_nodejs_version(nodepath)
            installed_tools += [('Nodejs', nodever)]
            npmver = utils.get_npmjs_version(nodepath)
            installed_tools += [('npmjs', npmver)]

        pandocexe = get_tool_path_file(r'\t\pandoc.exe')
        if pandocexe is not None:
            pandocver = utils.get_pandoc_version(
                #osp.dirname(pandocexe)
                str(Path(pandocexe).parent)
            )
            installed_tools += [('Pandoc', pandocver)]

        vscodeexe = get_tool_path_file(r'\t\VSCode\Code.exe')
        if vscodeexe is not None:
            installed_tools += [('VSCode',
                           utils.getFileProperties(vscodeexe)['FileVersion'])]

        tools = []
        for name, ver in installed_tools:
            metadata = wppm.get_package_metadata(
                'tools.ini', name
            )
            url, desc = (
                metadata['url'],
                metadata['description'],
            )
            tools += [
                '[%s](%s) | %s | %s'
                % (name, url, ver, desc)
            ]
        # get all packages installed in the changelog, whatever the method
        self.installed_packages = (
            self.distribution.get_installed_packages(update=True)
        )

        packages = [
            '[%s](%s) | %s | %s'
            % (
                pack.name,
                pack.url,
                pack.version,
                pack.description,
            )
            for pack in sorted(
                self.installed_packages,
                key=lambda p: p.name.lower(),
            )
        ]
        python_desc = 'Python programming language with standard library'
        return """## WinPython %s

The following packages are included in WinPython-%sbit v%s%s.

<details>

### Tools

Name | Version | Description
-----|---------|------------
%s

### Python packages

Name | Version | Description
-----|---------|------------
[Python](http://www.python.org/) | %s | %s
%s""" % (
            self.winpyver2 + self.flavor,
            self.winpy_arch,
            self.winpyver2 + self.flavor,
            (' %s' % self.release_level),
            '\n'.join(tools),
            self.python_fullversion,
            python_desc,
            '\n'.join(packages),
        ) + '\n\n</details>\n'

    # @property makes self.winpyver becomes a call to self.winpyver()
    @property
    def winpyver(self):
        """Return WinPython version (with flavor and release level!)"""
        return '%s.%d%s%s' % (
            self.python_fullversion,
            self.build_number,
            self.flavor,
            self.release_level,
        )

    @property
    def python_dir(self):
        """Return Python dirname (full path) of the target distribution"""
        # return osp.join(self.winpydir, self.python_name)  # python.exe path
        return str(Path(self.winpydir) / self.python_name)  # python.exe path

    @property
    def winpy_arch(self):
        """Return WinPython architecture"""
        return '%d' % self.distribution.architecture

    @property
    def py_arch(self):
        """Return distribution architecture, in Python distutils format:
        win-amd64 or win32"""
        if self.distribution.architecture == 64:
            return 'win-amd64'
        else:
            return 'win32'

    @property
    def prepath(self):
        """Return PATH contents to be prepend to the environment variable"""
        path = [
            r"Lib\site-packages\PyQt5",
            r"Lib\site-packages\PySide2",
            "",  # Python root directory
            "DLLs",
            "Scripts",
            r"..\t",
            #r"..\t\mingw32\bin",
        ]
        #if (
        #    self.distribution.architecture == 32
        #    and osp.isdir(self.winpydir + self.MINGW32_PATH)
        #):
        #    path += [r".." + self.MINGW32_PATH]
        #if self.distribution.architecture == 32:
        #    path += [r".." + self.R_PATH + r"\i386"]
        #if self.distribution.architecture == 64:
        #    path += [r".." + self.R_PATH + r"\x64"]
        path += [r".." + self.JULIA_PATH]

        path += [r".." + self.NODEJS_PATH]

        return path

    @property
    def postpath(self):
        """Return PATH contents to be append to the environment variable"""
        path = []
        # if osp.isfile(self.winpydir + self.THG_PATH):
        #     path += [r"..\t\TortoiseHg"]
        return path

    @property
    def toolsdirs(self):
        """Return tools directory list"""
        # formerly was joining prepared tool dir + the one of building env..
        return [
        #    osp.join(
        #        osp.dirname(osp.abspath(__file__)), 't'
        #    )
        ] + self._toolsdirs

    @property
    def docsdirs(self):
        """Return docs directory list"""
        #if osp.isdir(
        #    osp.join(
        #        osp.dirname(osp.abspath(__file__)), 'docs'
        #    )
        #):
        if (Path(__file__).resolve().parent / 'docs').is_dir():
            return [
                #osp.join(
                #    osp.dirname(osp.abspath(__file__)),
                #    'docs',
                #)
                str(Path(__file__).resolve().parent / 'docs')
            ] + self._docsdirs
        else:
            return self._docsdirs

    def get_package_fname(self, pattern):
        """Get package matching pattern in wheeldir"""
        path = self.wheeldir
        for fname in os.listdir(path):
            match = re.match(pattern, fname)
            if match is not None or pattern == fname:
                # return osp.abspath(osp.join(path, fname))
                return str((Path(path) / fname).resolve())
        else:
            raise RuntimeError(
                'Could not find required package matching %s'
                % pattern
            )

    def create_batch_script(self, name, contents,
                            do_changes=None):
        """Create batch script %WINPYDIR%/name"""
        # scriptdir = osp.join(self.winpydir, 'scripts')
        scriptdir = str(Path(self.winpydir) / 'scripts')
        # if not osp.isdir(scriptdir):
        if not Path(scriptdir).is_dir():
            os.mkdir(scriptdir)
        print ('dochanges for %s %', name, do_changes)
        # live patch pypy3
        contents_final = contents
        if do_changes != None:
           for i in do_changes:
               contents_final = contents_final.replace(i[0], i[1])

        # fd = open(osp.join(scriptdir, name), 'w')
        fd = open(str(Path(scriptdir) / name), 'w')
        fd.write(contents_final)
        fd.close()

    def create_launcher(
        self,
        name,
        icon,
        command=None,
        args=None,
        workdir=r'$EXEDIR\scripts',
        launcher='launcher_basic.nsi',
    ):
        """Create exe launcher with NSIS"""
        assert name.endswith('.exe')
        #portable_dir = osp.join(
        #    osp.dirname(osp.abspath(__file__)), 'portable'
        #)
        portable_dir = str(Path(__file__).resolve().parent / 'portable')
        # icon_fname = osp.join(portable_dir, 'icons', icon)
        icon_fname = str(Path(portable_dir) / 'icons' / icon)
        # assert osp.isfile(icon_fname)
        assert Path(icon_fname).is_file()

        # Customizing NSIS script
        if command is None:
            if args is not None and '.pyw' in args:
                command = '${WINPYDIR}\pythonw.exe'
            else:
                command = '${WINPYDIR}\python.exe'
        if args is None:
            args = ''
        if workdir is None:
            workdir = ''
        #fname = osp.join(
        #    self.winpydir, osp.splitext(name)[0] + '.nsi'
        #)
        fname = str(Path(self.winpydir) / (Path(name).stem + '.nsi'))

        data = [
            ('WINPYDIR', '$EXEDIR\%s' % self.python_name),
            ('WINPYVER', self.winpyver),
            ('COMMAND', command),
            ('PARAMETERS', args),
            ('WORKDIR', workdir),
            ('Icon', icon_fname),
            ('OutFile', name),
        ]

        build_nsis(launcher, fname, data)

    def create_python_batch(
        self,
        name,
        script_name,
        workdir=None,
        options=None,
        command=None,
    ):
        """Create batch file to run a Python script"""
        if options is None:
            options = ''
        else:
            options = ' ' + options
        if command is None:
            if script_name.endswith('.pyw'):
                command = 'start "%WINPYDIR%\pythonw.exe"'
            else:
                command = '"%WINPYDIR%\python.exe"'
        changedir = ''
        if workdir is not None:
            workdir = workdir
            changedir = (
                r"""cd/D %s
"""
                % workdir
            )
        if script_name != "":
            script_name = ' ' + script_name
        self.create_batch_script(
            name,
            r"""@echo off
call "%~dp0env_for_icons.bat"
"""
            + changedir
            + command
            + script_name
            + options
            + " %*",
        )

    def create_installer(self):
        """Create installer with NSIS"""
        self._print("Creating WinPython installer")
        #portable_dir = osp.join(
        #    osp.dirname(osp.abspath(__file__)), 'portable'
        #)
        portable_dir = str(Path(__file__).resolve().parent /  'portable')
        # fname = osp.join(portable_dir, 'installer-tmp.nsi')
        fname = str(Path(portable_dir) / 'installer-tmp.nsi')
        data = (
            ('DISTDIR', self.winpydir),
            ('ARCH', self.winpy_arch),
            (
                'VERSION',
                '%s.%d%s'
                % (
                    self.python_fullversion,
                    self.build_number,
                    self.flavor,
                ),
            ),
            (
                'VERSION_INSTALL',
                '%s%d'
                % (
                    self.python_fullversion.replace(
                        '.', ''
                    ),
                    self.build_number,
                ),
            ),
            ('RELEASELEVEL', self.release_level),
        )
        build_nsis('installer.nsi', fname, data)
        self._print_done()

    def create_installer_inno(self):
        """Create installer with INNO"""
        self._print("Creating WinPython installer INNO")
        #portable_dir = osp.join(
        #    osp.dirname(osp.abspath(__file__)), 'portable'
        #)
        portable_dir = str(Path(__file__).resolve().parent /  'portable')
        #fname = osp.join(
        #    portable_dir, 'installer_INNO-tmp.iss'
        #)
        fname = str(Path(portable_dir) / 'installer_INNO-tmp.iss')
        data = (
            ('DISTDIR', self.winpydir),
            ('ARCH', self.winpy_arch),
            (
                'VERSION',
                '%s.%d%s'
                % (
                    self.python_fullversion,
                    self.build_number,
                    self.flavor,
                ),
            ),
            (
                'VERSION_INSTALL',
                '%s%d'
                % (
                    self.python_fullversion.replace(
                        '.', ''
                    ),
                    self.build_number,
                ),
            ),
            ('RELEASELEVEL', self.release_level),
        )
        build_iss('installer_INNO.iss', fname, data)
        self._print_done()

    def create_installer_7zip(self, installer_option=''):
        """Create installer with 7-ZIP"""
        self._print("Creating WinPython installer 7-ZIP")
        #portable_dir = osp.join(
        #    osp.dirname(osp.abspath(__file__)), 'portable'
        #)
        portable_dir = str(Path(__file__).parent / 'portable')
        #fname = osp.join(
        #    portable_dir, 'installer_7zip-tmp.bat'
        #)
        fname = str(Path(portable_dir) / 'installer_7zip-tmp.bat')
        data = (
            ('DISTDIR', self.winpydir),
            ('ARCH', self.winpy_arch),
            (
                'VERSION',
                '%s.%d%s'
                % (
                    self.python_fullversion,
                    self.build_number,
                    self.flavor,
                ),
            ),
            (
                'VERSION_INSTALL',
                '%s%d'
                % (
                    self.python_fullversion.replace(
                        '.', ''
                    ),
                    self.build_number,
                ),
            ),
            ('RELEASELEVEL', self.release_level),
        )
        data += (('INSTALLER_OPTION', installer_option),)
        build_7zip('installer_7zip.bat', fname, data)
        self._print_done()

    def _print(self, text):
        """Print action text indicating progress"""
        if self.verbose:
            utils.print_box(text)
        else:
            print(text + '...', end=" ")

    def _print_done(self):
        """Print OK at the end of a process"""
        if not self.verbose:
            print("OK")

    def _extract_python(self):
        """Extracting Python installer, creating distribution object"""
        self._print("Extracting Python .zip version")
        utils.extract_archive(
            self.python_fname,
            targetdir=self.python_dir + r'\..',
        )
        self._print_done()

    def _copy_dev_tools(self):
        """Copy dev tools"""
        self._print(f"Copying tools from {self.toolsdirs} to {self.winpydir}/t")
        # toolsdir = osp.join(self.winpydir, 't')
        toolsdir = str(Path(self.winpydir) / 't')
        os.mkdir(toolsdir)
        for (
            dirname
        ) in (
            #[ok_dir for ok_dir in self.toolsdirs if osp.isdir(ok_dir)]
            [ok_dir for ok_dir in self.toolsdirs if Path(ok_dir).is_dir()]
        ):  # the ones in the make.py script environment
            for name in os.listdir(dirname):
                # path = osp.join(dirname, name)
                path = str(Path(dirname) / name)
                copy = (
                    shutil.copytree
                    # if osp.isdir(path)
                    if Path(path).is_dir()
                    else shutil.copyfile
                )
                if self.verbose:
                    print(
                        path
                        + ' --> '
                        # + osp.join(toolsdir, name)
                        + str(Path(toolsdir) / name)
                    )
                # copy(path, osp.join(toolsdir, name))
                copy(path, str(Path(toolsdir) / name))
        self._print_done()
        # move node higher
        # nodejs_current = osp.join(toolsdir, 'n')
        nodejs_current = str(Path(toolsdir) / 'n')
        nodejs_target = self.winpydir + self.NODEJS_PATH
        #if nodejs_current != nodejs_target and osp.isdir(
        #    nodejs_current
        #):
        if nodejs_current != nodejs_target and Path(nodejs_current).is_dir():
            shutil.move(nodejs_current, nodejs_target)

    def _copy_dev_docs(self):
        """Copy dev docs"""
        # docsdir = osp.join(self.winpydir, 'notebooks')
        docsdir = str(Path(self.winpydir) / 'notebooks')
        self._print(f"Copying Noteebook docs from {self.docsdirs} to {docsdir}")
        # if not osp.isdir(docsdir):
        if not Path(docsdir).is_dir():
            os.mkdir(docsdir)
        #docsdir = osp.join(
        #    self.winpydir, 'notebooks', 'docs'
        #)
        docsdir = str(Path(self.winpydir) / 'notebooks' / 'docs')
        # if not osp.isdir(docsdir):
        if not Path(docsdir).is_dir():
            os.mkdir(docsdir)
        for dirname in self.docsdirs:
            for name in os.listdir(dirname):
                # path = osp.join(dirname, name)
                path = str(Path(dirname) / name)
                copy = (
                    shutil.copytree
                    # if osp.isdir(path)
                    if Path(path).is_dir()
                    else shutil.copyfile
                )
                #copy(path,  osp.join(docsdir, name))
                copy(path, str(Path(docsdir) / name))
                if self.verbose:
                    print(
                        path
                        + ' --> '
                        # + osp.join(docsdir, name)
                        + str(Path(docsdir) / name)
                    )
        self._print_done()

    def _create_launchers(self):
        """Create launchers"""

        self._print("Creating launchers")
        self.create_launcher(
            'WinPython Command Prompt.exe',
            'cmd.ico',
            command='$SYSDIR\cmd.exe',
            args=r'/k cmd.bat',
        )
        self.create_launcher(
            'WinPython Powershell Prompt.exe',
            'powershell.ico',
            command='$SYSDIR\cmd.exe',
            args=r'/k cmd_ps.bat',
        )

        self.create_launcher(
            'WinPython Terminal.exe',
            'terminal.ico',
            command='wscript.exe',
            args=r'Noshell.vbs WinPython_Terminal.bat',
        )

        self.create_launcher(
            'WinPython Interpreter.exe',
            'python.ico',
            command='$SYSDIR\cmd.exe',
            args=r'/k winpython.bat',
        )

        self.create_launcher(
            'IDLEX.exe',
            'python.ico',
            command='wscript.exe',
            args=r'Noshell.vbs winidlex.bat',
        )

        self.create_launcher(
            'IDLE (Python GUI).exe',
            'python.ico',
            command='wscript.exe',
            args=r'Noshell.vbs winidle.bat',
        )

        self.create_launcher(
            'Spyder.exe',
            'spyder.ico',
            command='wscript.exe',
            args=r'Noshell.vbs winspyder.bat',
        )

        self.create_launcher(
            'Spyder reset.exe',
            'spyder_reset.ico',
            command='wscript.exe',
            args=r'Noshell.vbs spyder_reset.bat',
        )

        self.create_launcher(
            'WinPython Control Panel.exe',
            'winpython.ico',
            command='wscript.exe',
            args=r'Noshell.vbs wpcp.bat',
        )

        # Multi-Qt launchers
        self.create_launcher(
            'Qt Designer.exe',
            'qtdesigner.ico',
            command='wscript.exe',
            args=r'Noshell.vbs qtdesigner.bat',
        )

        self.create_launcher(
            'Qt Linguist.exe',
            'qtlinguist.ico',
            command='wscript.exe',
            args=r'Noshell.vbs qtlinguist.bat',
        )

        self.create_launcher(
            'Qt Assistant.exe',
            'qtassistant.ico',
            command='wscript.exe',
            args=r'Noshell.vbs qtassistant.bat',
        )

        # Jupyter launchers
        self.create_launcher(
            'IPython Qt Console.exe',
            'ipython.ico',
            command='wscript.exe',
            args=r'Noshell.vbs winqtconsole.bat',
        )

        # this one needs a shell to kill fantom processes
        self.create_launcher(
            'Jupyter Notebook.exe',
            'jupyter.ico',
            command='$SYSDIR\cmd.exe',
            args=r'/k winipython_notebook.bat',  # like VSCode + Rise way
            # args=r'/k winjupyter_nbclassic.bat',  # Jupyterlab in classic look
        )

        self.create_launcher(
            'Jupyter Lab.exe',
            'jupyter.ico',
            command='$SYSDIR\cmd.exe',
            args=r'/k winjupyter_lab.bat',
        )

        self.create_launcher(
            'Pyzo.exe',
            'pyzologo.ico',
            command='wscript.exe',
            args=r'Noshell.vbs winpyzo.bat',
        )

        # VSCode launcher
        self.create_launcher(
            'VS Code.exe',
            'code.ico',
            command='wscript.exe',
            args=r'Noshell.vbs winvscode.bat',
        )

        self._print_done()

    def _create_batch_scripts_initial(self):
        """Create batch scripts"""
        self._print("Creating batch scripts initial")
        conv = lambda path: ";".join(
            ['%WINPYDIR%\\' + pth for pth in path]
        )
        path = (
            conv(self.prepath)
            + ";%PATH%;"
            + conv(self.postpath)
        )

        convps = lambda path: ";".join(
            ["$env:WINPYDIR\\" + pth for pth in path]
        )
        pathps = (
            convps(self.prepath)
            + ";$env:path;"
            + convps(self.postpath)
        )

        # PyPy3
        shorty =self.distribution.short_exe
        changes=(
               (r'DIR%\python.exe' , r'DIR%' + "\\" + shorty),
               (r'DIR%\PYTHON.EXE' , r'DIR%' + "\\" + shorty),
                )
        #if osp.isdir(osp.join(self.distribution.target,
        #                       r'lib-python\3\idlelib')):
        if (Path(self.distribution.target) / r'lib-python\3\idlelib').is_dir():
            changes += ((r'\Lib\idlelib' , r'\lib-python\3\idlelib'),)
        self.create_batch_script(
            'env.bat',
            r"""@echo off
set WINPYDIRBASE=%~dp0..

rem get a normalize path
set WINPYDIRBASETMP=%~dp0..
pushd %WINPYDIRBASETMP%
set WINPYDIRBASE=%__CD__%
if "%WINPYDIRBASE:~-1%"=="\" set WINPYDIRBASE=%WINPYDIRBASE:~0,-1%
set WINPYDIRBASETMP=
popd

set WINPYDIR=%WINPYDIRBASE%"""
            + "\\"
            + self.python_name
            + r"""
rem 2019-08-25 pyjulia needs absolutely a variable PYTHON=%WINPYDIR%python.exe
set PYTHON=%WINPYDIR%\python.exe
set WINPYVER="""
            + self.winpyver
            + r"""
set HOME=%WINPYDIRBASE%\settings
rem read https://github.com/winpython/winpython/issues/839
rem set USERPROFILE=%HOME%
rem set WINPYDIRBASE=
set JUPYTER_DATA_DIR=%HOME%
set JUPYTER_CONFIG_DIR=%WINPYDIR%\etc\jupyter
set JUPYTER_CONFIG_PATH=%WINPYDIR%\etc\jupyter
set WINPYARCH=WIN32
if  "%WINPYDIR:~-5%"=="amd64" set WINPYARCH=WIN-AMD64
set FINDDIR=%WINDIR%\system32
echo ";%PATH%;" | %FINDDIR%\find.exe /C /I ";%WINPYDIR%\;" >nul
if %ERRORLEVEL% NEQ 0 (
   set "PATH="""
            + path
            + r""""
   cd .
)

rem force default pyqt5 kit for Spyder if PyQt5 module is there
if exist "%WINPYDIR%\Lib\site-packages\PyQt5\__init__.py" set QT_API=pyqt5

rem ******************
rem handle R if included
rem ******************
if not exist "%WINPYDIRBASE%\t\R\bin" goto r_bad
set R_HOME=%WINPYDIRBASE%\t\R
if     "%WINPYARCH%"=="WIN32" set R_HOMEbin=%R_HOME%\bin\i386
if not "%WINPYARCH%"=="WIN32" set R_HOMEbin=%R_HOME%\bin\x64
:r_bad

rem ******************
rem handle Julia if included
rem ******************
if not exist "%WINPYDIRBASE%\t\Julia\bin" goto julia_bad
set JULIA_HOME=%WINPYDIRBASE%\t\Julia\bin\
set JULIA_EXE=julia.exe
set JULIA=%JULIA_HOME%%JULIA_EXE%
set JULIA_PKGDIR=%WINPYDIRBASE%\settings\.julia
:julia_bad

rem ******************
rem handle PySide2 if included
rem ******************
set tmp_pyz=%WINPYDIR%\Lib\site-packages\PySide2
if not exist "%tmp_pyz%" goto pyside2_conf_exist
set tmp_pyz=%tmp_pyz%\qt.conf
if not exist "%tmp_pyz%" (
    echo [Paths]
    echo Prefix = .
    echo Binaries = .
)>> "%tmp_pyz%"
:pyside2_conf_exist

rem ******************
rem handle PyQt5 if included
rem ******************
set tmp_pyz=%WINPYDIR%\Lib\site-packages\PyQt5
if not exist "%tmp_pyz%" goto pyqt5_conf_exist
set tmp_pyz=%tmp_pyz%\qt.conf
if not exist "%tmp_pyz%" (
    echo [Paths]
    echo Prefix = .
    echo Binaries = .
)>> "%tmp_pyz%"
:pyqt5_conf_exist

rem ******************
rem handle pyqt5_tools if included
rem ******************
set tmp_pyz=%WINPYDIR%\Lib\site-packages\pyqt5_tools
if not exist "%tmp_pyz%" goto end_pyqt5_tools_conf
set QT_PLUGIN_PATH=%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\plugins
:end_pyqt5_tools_conf

rem ******************
rem handle Pyzo configuration part
rem ******************
if not exist "%HOME%\.pyzo" mkdir %HOME%\.pyzo
if exist "%HOME%\.pyzo\config.ssdf"  goto after_pyzo_conf
set tmp_pyz="%HOME%\.pyzo\config.ssdf"
(
    echo shellConfigs2 = list:
    echo  dict:
    echo    name = 'Python'
    echo    exe = '.\\python.exe'
    echo    ipython = 'no'
    echo    gui = 'none'
)>> "%tmp_pyz%"

:after_pyzo_conf

rem ******************
rem WinPython.ini part (removed from nsis)
rem ******************
if not exist "%WINPYDIRBASE%\settings" mkdir "%WINPYDIRBASE%\settings"
if not exist "%WINPYDIRBASE%\settings\AppData" mkdir "%WINPYDIRBASE%\settings\AppData"
if not exist "%WINPYDIRBASE%\settings\AppData\Roaming" mkdir "%WINPYDIRBASE%\settings\AppData\Roaming"
set winpython_ini=%WINPYDIRBASE%\settings\winpython.ini
if not exist "%winpython_ini%" (
    echo [debug]
    echo state = disabled
    echo [environment]
    echo ## <?> Uncomment lines to override environment variables
    echo #HOME = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%
    echo #USERPROFILE = %%HOME%%
    echo #JUPYTER_DATA_DIR = %%HOME%%
    echo #JUPYTERLAB_SETTINGS_DIR = %%HOME%%\.jupyter\lab
    echo #JUPYTERLAB_WORKSPACES_DIR = %%HOME%%\.jupyter\lab\workspaces
    echo #WINPYWORKDIR = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\Notebooks
)>> "%winpython_ini%"

""",
            do_changes=changes,
        )

        self.create_batch_script(
            'WinPython_PS_Prompt.ps1',
            r"""
###############################
### WinPython_PS_Prompt.ps1 ###
###############################
$0 = $myInvocation.MyCommand.Definition
$dp0 = [System.IO.Path]::GetDirectoryName($0)

$env:WINPYDIRBASE = "$dp0\.."
# get a normalize path
# http://stackoverflow.com/questions/1645843/resolve-absolute-path-from-relative-path-and-or-file-name
$env:WINPYDIRBASE = [System.IO.Path]::GetFullPath( $env:WINPYDIRBASE )

# avoid double_init (will only resize screen)
if (-not ($env:WINPYDIR -eq [System.IO.Path]::GetFullPath( $env:WINPYDIRBASE+"""
            + '"\\'
            + self.python_name
            + '"'
            + r""")) ) {

$env:WINPYDIR = $env:WINPYDIRBASE+"""
            + '"'
            + '\\'
            + self.python_name
            + '"'
            + r"""
# 2019-08-25 pyjulia needs absolutely a variable PYTHON=%WINPYDIR%python.exe
$env:PYTHON = "%WINPYDIR%\python.exe"

$env:WINPYVER = '"""
            + self.winpyver
            + r"""'
$env:HOME = "$env:WINPYDIRBASE\settings"

# rem read https://github.com/winpython/winpython/issues/839
# $env:USERPROFILE = "$env:HOME"

$env:WINPYDIRBASE = ""
$env:JUPYTER_DATA_DIR = "$env:HOME"
$env:WINPYARCH = 'WIN32'
if ($env:WINPYARCH.subString($env:WINPYARCH.length-5, 5) -eq 'amd64')  {
   $env:WINPYARCH = 'WIN-AMD64' }

if (-not $env:PATH.ToLower().Contains(";"+ $env:WINPYDIR.ToLower()+ ";"))  {
 $env:PATH = """
            + '"'
            + pathps
            + '"'
            + r""" }

#rem force default pyqt5 kit for Spyder if PyQt5 module is there
if (Test-Path "$env:WINPYDIR\Lib\site-packages\PyQt5\__init__.py") { $env:QT_API = "pyqt5" }

#####################
### handle R if included
#####################
if (Test-Path "$env:WINPYDIR\..\t\R\bin") {
    $env:R_HOME = "$env:WINPYDIR\..\t\R"
    $env:R_HOMEbin = "$env:R_HOME\bin\x64"
    if ("$env:WINPYARCH" -eq "WIN32") {
        $env:R_HOMEbin = "$env:R_HOME\bin\i386"
    }
}

#####################
### handle Julia if included
#####################
if (Test-Path "$env:WINPYDIR\..\t\Julia\bin") {
    $env:JULIA_HOME = "$env:WINPYDIR\..\t\Julia\bin\"
    $env:JULIA_EXE = "julia.exe"
    $env:JULIA = "$env:JULIA_HOME$env:JULIA_EXE"
    $env:JULIA_PKGDIR = "$env:WINPYDIR\..\settings\.julia"
}

#####################
### handle PySide2 if included
#####################

$env:tmp_pyz = "$env:WINPYDIR\Lib\site-packages\PySide2"
if (Test-Path "$env:tmp_pyz") {
   $env:tmp_pyz = "$env:tmp_pyz\qt.conf"
   if (-not (Test-Path "$env:tmp_pyz")) {
      "[Paths]"| Add-Content -Path $env:tmp_pyz
      "Prefix = ."| Add-Content -Path $env:tmp_pyz
      "Binaries = ."| Add-Content -Path $env:tmp_pyz
   }
}

#####################
### handle PyQt5 if included
#####################
$env:tmp_pyz = "$env:WINPYDIR\Lib\site-packages\PyQt5"
if (Test-Path "$env:tmp_pyz") {
   $env:tmp_pyz = "$env:tmp_pyz\qt.conf"
   if (-not (Test-Path "$env:tmp_pyz")) {
      "[Paths]"| Add-Content -Path $env:tmp_pyz
      "Prefix = ."| Add-Content -Path $env:tmp_pyz
      "Binaries = ."| Add-Content -Path $env:tmp_pyz
   }
}

#####################
### handle pyqt5_tools if included
#####################
$env:tmp_pyz = "$env:WINPYDIR\Lib\site-packages\pyqt5_tools"
if (Test-Path "$env:tmp_pyz") {
   $env:QT_PLUGIN_PATH = "WINPYDIR\Lib\site-packages\pyqt5_tools\Qt\plugins"
}

#####################
### handle Pyzo configuration part
#####################
$env:tmp_pyz = "$env:HOME\.pyzo"
if (-not (Test-Path "$env:tmp_pyz")) { md -Path "$env:tmp_pyz" }
$env:tmp_pyz = "$env:HOME\.pyzo\config.ssdf"
if (-not (Test-Path "$env:tmp_pyz")) {
shellConfigs2 = list:| Add-Content -Path $env:tmp_pyz
 dict:| Add-Content -Path $env:tmp_pyz
   name = 'Python'| Add-Content -Path $env:tmp_pyz
   exe = '.\\python.exe'| Add-Content -Path $env:tmp_pyz
   ipython = 'no'| Add-Content -Path $env:tmp_pyz
   gui = 'none'| Add-Content -Path $env:tmp_pyz
}

#####################
### WinPython.ini part (removed from nsis)
#####################
if (-not (Test-Path "$env:WINPYDIR\..\settings")) { md -Path "$env:WINPYDIR\..\settings" }
if (-not (Test-Path "$env:WINPYDIR\..\settings\AppData")) { md -Path "$env:WINPYDIR\..\settings\AppData" }
if (-not (Test-Path "$env:WINPYDIR\..\settings\AppData\Roaming")) { md -Path "$env:WINPYDIR\..\settings\AppData\Roaming" }
$env:winpython_ini = "$env:WINPYDIR\..\settings\winpython.ini"
if (-not (Test-Path $env:winpython_ini)) {
    "[debug]" | Add-Content -Path $env:winpython_ini
    "state = disabled" | Add-Content -Path $env:winpython_ini
    "[environment]" | Add-Content -Path $env:winpython_ini
    "## <?> Uncomment lines to override environment variables" | Add-Content -Path $env:winpython_ini
    "#HOME = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%" | Add-Content -Path $env:winpython_ini
    "#USERPROFILE = %%HOME%%" | Add-Content -Path $env:winpython_ini
    "#JUPYTER_DATA_DIR = %%HOME%%" | Add-Content -Path $env:winpython_ini
    "#JUPYTERLAB_SETTINGS_DIR = %%HOME%%\.jupyter\lab" | Add-Content -Path $env:winpython_ini
    "#JUPYTERLAB_WORKSPACES_DIR = %%HOME%%\.jupyter\lab\workspaces" | Add-Content -Path $env:winpython_ini
    "#WINPYWORKDIR = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\Notebooks" | Add-Content -Path $env:winpython_ini
}

}
###############################
### Set-WindowSize
###############################
Function Set-WindowSize {
Param([int]$x=$host.ui.rawui.windowsize.width,
      [int]$y=$host.ui.rawui.windowsize.heigth,
      [int]$buffer=$host.UI.RawUI.BufferSize.heigth)

    $buffersize = new-object System.Management.Automation.Host.Size($x,$buffer)
    $host.UI.RawUI.BufferSize = $buffersize
    $size = New-Object System.Management.Automation.Host.Size($x,$y)
    $host.ui.rawui.WindowSize = $size
}
# Windows10 yelling at us with 150 40 6000
# no more needed ?
# Set-WindowSize 195 40 6000

### Colorize to distinguish
#$host.ui.RawUI.BackgroundColor = "DarkBlue"
$host.ui.RawUI.BackgroundColor = "Black"
$host.ui.RawUI.ForegroundColor = "White"

""",
            do_changes=changes,
        )

        self.create_batch_script(
            'cmd_ps.bat',
            r"""@echo off
rem safe bet
call "%~dp0env_for_icons.bat"
Powershell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy RemoteSigned -noexit -File ""%~dp0WinPython_PS_Prompt.ps1""'}"
exit
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'WinPython_Interpreter_PS.bat',
            r"""@echo off
rem no safe bet (for comparisons)
Powershell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy RemoteSigned -noexit -File ""%~dp0WinPython_PS_Prompt.ps1""'}"
exit
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'env_for_icons.bat',
            r"""@echo off
call "%~dp0env.bat"
set WINPYWORKDIR=%WINPYDIRBASE%\Notebooks

rem default is as before: Winpython ..\Notebooks
set WINPYWORKDIR1=%WINPYWORKDIR%

rem if we have a file or directory in %1 parameter, we use that directory
if not "%~1"=="" (
   if exist "%~1" (
      if exist "%~1\" (
         rem echo it is a directory %~1
	     set WINPYWORKDIR1=%~1
	  ) else (
	  rem echo  it is a file %~1, so we take the directory %~dp1
	  set WINPYWORKDIR1=%~dp1
	  )
   )
) else (
rem if it is launched from another directory , we keep it that one echo %__CD__%
if not "%__CD__%"=="%~dp0" set  WINPYWORKDIR1="%__CD__%"
)
rem remove potential doublequote
set WINPYWORKDIR1=%WINPYWORKDIR1:"=%
rem remove some potential last \
if "%WINPYWORKDIR1:~-1%"=="\" set WINPYWORKDIR1=%WINPYWORKDIR1:~0,-1%

FOR /F "delims=" %%i IN ('cscript /nologo "%~dp0WinpythonIni.vbs"') DO set winpythontoexec=%%i
%winpythontoexec%set winpythontoexec=

rem ******************
rem missing student directory part
rem ******************

if not exist "%WINPYWORKDIR%" mkdir "%WINPYWORKDIR%"

if not exist "%HOME%\.spyder-py%WINPYVER:~0,1%"  mkdir "%HOME%\.spyder-py%WINPYVER:~0,1%"
if not exist "%HOME%\.spyder-py%WINPYVER:~0,1%\workingdir" echo %HOME%\Notebooks>"%HOME%\.spyder-py%WINPYVER:~0,1%\workingdir"

rem ******* make cython use mingwpy part *******
if not exist "%WINPYDIRBASE%\settings\pydistutils.cfg" goto no_cython
if not exist "%HOME%\pydistutils.cfg" xcopy   "%WINPYDIRBASE%\settings\pydistutils.cfg" "%HOME%"
:no_cython
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'Noshell.vbs',
            r"""
'from http://superuser.com/questions/140047/how-to-run-a-batch-file-without-launching-a-command-window/390129
If WScript.Arguments.Count >= 1 Then
    ReDim arr(WScript.Arguments.Count-1)
    For i = 0 To WScript.Arguments.Count-1
        Arg = WScript.Arguments(i)
        If InStr(Arg, " ") > 0 or InStr(Arg, "&") > 0 Then Arg = chr(34) & Arg & chr(34)
      arr(i) = Arg
    Next

    RunCmd = Join(arr)
    CreateObject("Wscript.Shell").Run RunCmd, 0 , True
End If
        """,
        )

        self.create_batch_script(
            'WinPythonIni.vbs',
            r"""
Set colArgs = WScript.Arguments
If colArgs.Count> 0 Then
  Filename=colArgs(0)
else
  Filename="..\settings\winpython.ini"
end if
my_lines = Split(GetFile(FileName) & vbNewLine , vbNewLine )
segment = "environment"
txt=""
Set objWSH =  CreateObject("WScript.Shell")
For each l in my_lines
    if left(l, 1)="[" then
        segment=split(mid(l, 2, 999) & "]","]")(0)
    ElseIf left(l, 1) <> "#" and instr(l, "=")>0  then
        data = Split(l & "=", "=")
        if segment="debug" and trim(data(0))="state" then data(0)= "WINPYDEBUG"
        if segment="environment" or segment= "debug" then
            txt= txt & "set " & rtrim(data(0)) & "=" & translate(ltrim(data(1))) & "&& "
            objWSH.Environment("PROCESS").Item(rtrim(data(0))) = translate(ltrim(data(1)))
        end if
        if segment="debug" and trim(data(0))="state" then txt= txt & "set WINPYDEBUG=" & trim(data(1)) & "&&"
    End If
Next
wscript.echo txt

Function GetFile(ByVal FileName)
    Set FS = CreateObject("Scripting.FileSystemObject")
    If Left(FileName,3)="..\" then FileName = FS.GetParentFolderName(FS.GetParentFolderName(Wscript.ScriptFullName)) & mid(FileName,3,9999)
    If Left(FileName,3)=".\" then FileName = FS.GetParentFolderName(FS.GetParentFolderName(Wscript.ScriptFullName)) & mid(FileName,3,9999)
    On Error Resume Next
    GetFile = FS.OpenTextFile(FileName).ReadAll
End Function

Function translate(line)
    set dos = objWSH.Environment("PROCESS")
    tab = Split(line & "%", "%")
    for i = 1 to Ubound(tab) step 2
       if tab(i)& "" <> "" and dos.Item(tab(i)) & "" <> "" then tab(i) =  dos.Item(tab(i))
    next
    translate =  Join(tab, "")
end function
        """,
        )

    def _create_batch_scripts(self):
        """Create batch scripts"""
        self._print("Creating batch scripts")

        # PyPy3
        shorty =self.distribution.short_exe
        changes=(
               (r'DIR%\python.exe' , r'DIR%' + "\\" + shorty),
               (r'DIR%\PYTHON.EXE' , r'DIR%' + "\\" + shorty),
                )
        #if osp.isdir(osp.join(self.distribution.target,
        #                       r'lib-python\3\idlelib')):
        if (Path(self.distribution.target) / r'lib-python\3\idlelib').is_dir():
            changes += ((r'\Lib\idlelib' , r'\lib-python\3\idlelib'),)

        self.create_batch_script(
            'readme.txt',
            r"""These batch files are required to run WinPython icons.

These files should help the user writing his/her own
specific batch file to call Python scripts inside WinPython.
The environment variables are set-up in 'env_.bat' and 'env_for_icons.bat'.""",
        )

        self.create_batch_script(
            'make_cython_use_mingw.bat',
            r"""@echo off
call "%~dp0env.bat"

rem ******************
rem mingw part
rem ******************

set pydistutils_cfg=%WINPYDIRBASE%\settings\pydistutils.cfg

set tmp_blank=
(
    echo [config]
    echo compiler=mingw32
    echo.
    echo [build]
    echo compiler=mingw32
    echo.
    echo [build_ext]
    echo compiler=mingw32
) > "%pydistutils_cfg%"

echo cython has been set to use mingw32
echo to remove this, remove file "%pydistutils_cfg%"

rem pause

""",
        )

        self.create_batch_script(
            'make_cython_use_vc.bat',
            r"""@echo off
call "%~dp0env.bat"
set pydistutils_cfg=%WINPYDIRBASE%\settings\pydistutils.cfg
echo [config]>%pydistutils_cfg%
        """,
        )

        self.create_batch_script(
            'make_winpython_movable.bat',
            r"""@echo off
call "%~dp0env.bat"
echo patch pip and current launchers for move

"%WINPYDIR%\python.exe" -c "from winpython import wppm;dist=wppm.Distribution(r'%WINPYDIR%');dist.patch_standard_packages('pip', to_movable=True)"
pause
        """,
            do_changes=changes,
        )

        self.create_batch_script(
            'make_winpython_fix.bat',
            r"""@echo off
call "%~dp0env.bat"
echo patch pip and current launchers for non-move

"%WINPYDIR%\python.exe" -c "from winpython import wppm;dist=wppm.Distribution(r'%WINPYDIR%');dist.patch_standard_packages('pip', to_movable=False)"
pause
        """,
            do_changes=changes,
        )

        self.create_batch_script(
            'make_working_directory_be_not_winpython.bat',
            r"""@echo off
set winpython_ini=%~dp0..\\settings\winpython.ini
(
    echo [debug]
    echo state = disabled
    echo [environment]
    echo ## <?> Uncomment lines to override environment variables
    echo HOME = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\settings
    echo USERPROFILE = %%HOME%%
    echo JUPYTER_DATA_DIR = %%HOME%%
    echo #JUPYTERLAB_SETTINGS_DIR = %%HOME%%\.jupyter\lab
    echo #JUPYTERLAB_WORKSPACES_DIR = %%HOME%%\.jupyter\lab\workspaces
    echo WINPYWORKDIR = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\Notebooks
) > "%winpython_ini%"
    call "%~dp0env_for_icons.bat"
    mkdir %HOMEDRIVE%%HOMEPATH%\Documents\WinPython%WINPYVER%\settings
    mkdir %HOMEDRIVE%%HOMEPATH%\Documents\WinPython%WINPYVER%\settings\AppData
    mkdir %HOMEDRIVE%%HOMEPATH%\Documents\WinPython%WINPYVER%\settings\AppData\Roaming
""",
        )

        self.create_batch_script(
            'make_working_directory_be_winpython.bat',
            r"""@echo off
set winpython_ini=%~dp0..\\settings\winpython.ini
(
    echo [debug]
    echo state = disabled
    echo [environment]
    echo ## <?> Uncomment lines to override environment variables
    echo #HOME = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\settings
    echo #USERPROFILE = %%HOME%%
    echo #JUPYTER_DATA_DIR = %%HOME%%
    echo #JUPYTERLAB_SETTINGS_DIR = %%HOME%%\.jupyter\lab
    echo #JUPYTERLAB_WORKSPACES_DIR = %%HOME%%\.jupyter\lab\workspaces
    echo #WINPYWORKDIR = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\Notebooks
) > "%winpython_ini%"
""",
        )

        self.create_batch_script(
            'make_working_directory_and_userprofile_be_winpython.bat',
            r"""@echo off
set winpython_ini=%~dp0..\\settings\winpython.ini
(
    echo [debug]
    echo state = disabled
    echo [environment]
    echo ## <?> Uncomment lines to override environment variables
    echo #HOME = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\settings
    echo USERPROFILE = %%HOME%%
    echo #JUPYTER_DATA_DIR = %%HOME%%
    echo #JUPYTERLAB_SETTINGS_DIR = %%HOME%%\.jupyter\lab
    echo #JUPYTERLAB_WORKSPACES_DIR = %%HOME%%\.jupyter\lab\workspaces
    echo #WINPYWORKDIR = %%HOMEDRIVE%%%%HOMEPATH%%\Documents\WinPython%%WINPYVER%%\Notebooks
) > "%winpython_ini%"
""",
        )

        self.create_batch_script(
            'cmd.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
if not "%WINPYWORKDIR%"=="%WINPYWORKDIR1%" cd %WINPYWORKDIR1%
cmd.exe /k""",
        )

        self.create_batch_script(
            'WinPython_Terminal.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
if not "%WINPYWORKDIR%"=="%WINPYWORKDIR1%" cd %WINPYWORKDIR1%
%USERPROFILE%\AppData\Local\Microsoft\WindowsApps\wt.exe
exit
""",
        )

        self.create_batch_script(
            'python.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
rem backward compatibility for  python command-line users
if not "%WINPYWORKDIR%"=="%WINPYWORKDIR1%" cd %WINPYWORKDIR1%
"%WINPYDIR%\python.exe"  %*
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'winpython.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
cd/D "%WINPYWORKDIR1%"
rem backward compatibility for non-ptpython users
if exist "%WINPYDIR%\scripts\ptpython.exe" (
    "%WINPYDIR%\scripts\ptpython.exe" %*
) else (
    "%WINPYDIR%\python.exe"  %*
)
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'idlex.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
rem backward compatibility for non-IDLEX users
if exist "%WINPYDIR%\scripts\idlex.pyw" (
    "%WINPYDIR%\python.exe" "%WINPYDIR%\scripts\idlex.pyw" %*
) else (
    "%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\idlelib\idle.pyw" %*
)
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'idle.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
"%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\idlelib\idle.pyw" %*

""",
            do_changes=changes,
        )
        self.create_batch_script(
            'winidlex.bat',
            r"""@echo off

call "%~dp0env_for_icons.bat"  %*
cd/D "%WINPYWORKDIR1%"
rem backward compatibility for non-IDLEX users
if exist "%WINPYDIR%\scripts\idlex.pyw" (
    "%WINPYDIR%\python.exe" "%WINPYDIR%\scripts\idlex.pyw" %*
) else (
    "%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\idlelib\idle.pyw" %*
)
""",
            do_changes=changes,
        )
        self.create_batch_script(
            'winidle.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\idlelib\idle.pyw" %*
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'spyder.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
rem cd/D "%WINPYWORKDIR%"
if exist "%WINPYDIR%\scripts\spyder3.exe" (
   "%WINPYDIR%\scripts\spyder3.exe" %* -w "%WINPYWORKDIR1%"
) else (
   "%WINPYDIR%\scripts\spyder.exe" %* -w "%WINPYWORKDIR1%"
)
""",
        )
        self.create_batch_script(
            'winspyder.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
rem cd/D "%WINPYWORKDIR%"
if exist "%WINPYDIR%\scripts\spyder3.exe" (
   "%WINPYDIR%\scripts\spyder3.exe" %* -w "%WINPYWORKDIR1%"
) else (
   "%WINPYDIR%\scripts\spyder.exe" %* -w "%WINPYWORKDIR1%"
)
""",
        )

        self.create_batch_script(
            'spyder_reset.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
if exist "%WINPYDIR%\scripts\spyder3.exe" (
    "%WINPYDIR%\scripts\spyder3.exe" --reset %*
) else (
    "%WINPYDIR%\scripts\spyder.exe" --reset %*
)
""",
        )

        self.create_batch_script(
            'ipython_notebook.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\scripts\jupyter-notebook.exe" %*
""",
        )

        self.create_batch_script(
            'winipython_notebook.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\scripts\jupyter-notebook.exe" %*
""",
        )

        self.create_batch_script(
            'winjupyter_nbclassic.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\scripts\jupyter-nbclassic.exe" %*
""",
        )

        self.create_batch_script(
            'winjupyter_lab.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\scripts\jupyter-lab.exe" %*
""",
        )

        self.create_batch_script(
            'qtconsole.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\scripts\jupyter-qtconsole.exe" %*
""",
        )

        self.create_batch_script(
            'winqtconsole.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\scripts\jupyter-qtconsole.exe" %*
""",
        )

        self.create_batch_script(
            'qtdemo.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
if exist "%WINPYDIR%\Lib\site-packages\PyQt5\examples\qtdemo\qtdemo.py" (
    "%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\site-packages\PyQt5\examples\qtdemo\qtdemo.py"
)
if exist "%WINPYDIR%\Lib\site-packages\PySide2\examples\datavisualization\bars3d.py" (
    "%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\site-packages\PySide2\examples\datavisualization\bars3d.py"
)
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'qtdesigner.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
if "%QT_API%"=="" ( set QT_API=pyqt5 )
if "%QT_API%"=="pyqt5" (
    if exist "%WINPYDIR%\Scripts\designer.exe" (
        "%WINPYDIR%\Scripts\designer.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\qt5_applications\Qt\bin\designer.exe" (
        "%WINPYDIR%\Lib\site-packages\qt5_applications\Qt\bin\designer.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\bin\designer.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\bin\designer.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5-tools\designer.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5-tools\designer.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\PyQt5\designer.exe" (
        "%WINPYDIR%\Lib\site-packages\PyQt5\designer.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\PySide2\designer.exe" (
        "%WINPYDIR%\Lib\site-packages\PySide2\designer.exe" %*
    ) else (
        "%WINPYDIR%\Lib\site-packages\PySide6\designer.exe" %*
    )
) else (
    "%WINPYDIR%\Lib\site-packages\PySide6\designer.exe" %*
)
""",
        )

        self.create_batch_script(
            'qtassistant.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
if "%QT_API%"=="" ( set QT_API=pyqt5 )
if "%QT_API%"=="pyqt5" (
    if exist "%WINPYDIR%\Scripts\assistant.exe" (
        "%WINPYDIR%\Scripts\assistant.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\qt5_applications\Qt\bin\assistant.exe" (
        "%WINPYDIR%\Lib\site-packages\qt5_applications\Qt\bin\assistant.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\bin\assistant.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\bin\assistant.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5-tools\assistant.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5-tools\assistant.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\PyQt5\assistant.exe" (
        "%WINPYDIR%\Lib\site-packages\PyQt5\assistant.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\PySide2\assistant.exe" (
        "%WINPYDIR%\Lib\site-packages\PySide2\assistant.exe" %*
    ) else (
        "%WINPYDIR%\Lib\site-packages\PySide6\assistant.exe" %*
    )
) else (
    "%WINPYDIR%\Lib\site-packages\PySide6\assistant.exe" %*
)
""",
        )

        self.create_batch_script(
            'qtlinguist.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
if "%QT_API%"=="" ( set QT_API=pyqt5 )
if "%QT_API%"=="pyqt5" (
    if exist "%WINPYDIR%\Scripts\linguist.exe" (
        "%WINPYDIR%\Scripts\linguist.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\qt5_applications\Qt\bin\linguist.exe" (
        "%WINPYDIR%\Lib\site-packages\qt5_applications\Qt\bin\linguist.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\bin\linguist.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5_tools\Qt\bin\linguist.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5-tools\linguist.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5-tools\linguist.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\pyqt5_tools\linguist.exe" (
        "%WINPYDIR%\Lib\site-packages\pyqt5_tools\linguist.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\PyQt5\linguist.exe" (
        cd/D "%WINPYDIR%\Lib\site-packages\PyQt5"
        "%WINPYDIR%\Lib\site-packages\PyQt5\linguist.exe" %*
        "%WINPYDIR%\Lib\site-packages\pyqt5_tools\linguist.exe" %*
    ) else if exist "%WINPYDIR%\Lib\site-packages\PySide2\linguist.exe" (
        "%%WINPYDIR%\Lib\site-packages\PySide2\linguist.exe" %*
    ) else (
        "%WINPYDIR%\Lib\site-packages\PySide6\linguist.exe" %*
    )
) else (
    "%WINPYDIR%\Lib\site-packages\PySide6\linguist.exe" %*
)

""",
        )

        self.create_python_batch(
            'register_python.bat',
            r'"%WINPYDIR%\Lib\site-packages\winpython\register_python.py"',
            workdir=r'"%WINPYDIR%\Scripts"',
        )

        self.create_python_batch(
            'unregister_python.bat',
            r'"%WINPYDIR%\Lib\site-packages\winpython\unregister_python.py"',
            workdir=r'"%WINPYDIR%\Scripts"',
        )

        self.create_batch_script(
            'register_python_for_all.bat',
            r"""@echo off
call "%~dp0env.bat"
call "%~dp0register_python.bat" --all""",
        )

        self.create_batch_script(
            'unregister_python_for_all.bat',
            r"""@echo off
call "%~dp0env.bat"
call "%~dp0unregister_python.bat" --all""",
        )

        self.create_batch_script(
            'wpcp.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat" %*
cd/D "%WINPYWORKDIR1%"
"%WINPYDIR%\python.exe" -m winpython.controlpanel %*
""",
            do_changes=changes,
        )

        # self.create_python_batch('wpcp.bat', '-m winpython.controlpanel',
        #                         workdir=r'"%WINPYDIR%\Scripts"')

        self.create_batch_script(
            'upgrade_pip.bat',
            r"""@echo off
call "%~dp0env.bat"
echo this will upgrade pip with latest version, then patch it for WinPython portability ok ?
pause
"%WINPYDIR%\python.exe" -m pip install --upgrade pip
"%WINPYDIR%\python.exe" -c "from winpython import wppm;dist=wppm.Distribution(r'%WINPYDIR%');dist.patch_standard_packages('pip', to_movable=True)
pause
""",
            do_changes=changes,
        )

        self.create_batch_script(
            'winpyzo.bat',
            r"""@echo off
call "%~dp0env_for_icons.bat"  %*
cd/D "%WINPYDIR%"
"%WINPYDIR%\scripts\pyzo.exe" %*
""",
        )

        # pre-run mingw batch
        print('now pre-running extra mingw')
        #filepath = osp.join(
        #    self.winpydir,
        #    'scripts',
        #    'make_cython_use_mingw.bat',
        #)
        filepath = str(Path(self.winpydir) / 'scripts' /
            'make_cython_use_mingw.bat')
        p = subprocess.Popen(
            filepath, shell=True, stdout=subprocess.PIPE
        )
        stdout, stderr = p.communicate()

        self._print_done()

        self.create_batch_script(
            'winvscode.bat',
            r"""@echo off
rem launcher for VScode
call "%~dp0env_for_icons.bat" %*
rem cd/D "%WINPYWORKDIR1%"
if exist "%WINPYDIR%\..\t\vscode\code.exe" (
    "%WINPYDIR%\..\t\vscode\code.exe" %*
) else (
if exist "%LOCALAPPDATA%\Programs\Microsoft VS Code\code.exe" (
    "%LOCALAPPDATA%\Programs\Microsoft VS Code\code.exe"  %*
) else (
    "code.exe" %*
))

""",
        )
    def _run_complement_batch_scripts(
        self, this_batch="run_complement.bat"
    ):
        """ tools\..\run_complement.bat for final complements"""
        print('now %s in tooldirs\..' % this_batch)
        for post_complement in list(
            #set([osp.dirname(s) for s in self._toolsdirs])
            set([str(Path(s).parent) for s in self._toolsdirs])
        ):
            #filepath = osp.join(post_complement, this_batch)
            filepath = str(Path(post_complement) / this_batch)
            #if osp.isfile(filepath):
            if Path(filepath).is_file():
                print(
                    'launch "%s"  for  "%s"'
                    % (filepath, self.winpydir)
                )
                self._print(
                    'launch "%s"  for  "%s" !'
                    % (filepath, self.winpydir)
                )
                try:
                    retcode = subprocess.call(
                        '"%s"   "%s"'
                        % (filepath, self.winpydir),
                        shell=True,
                        stdout=sys.stderr,
                    )
                    if retcode < 0:
                        print(
                            "Child was terminated by signal",
                            -retcode,
                            file=sys.stderr,
                        )
                        self._print(
                            "Child was terminated by signal ! ",
                            -retcode,
                            file=sys.stderr,
                        )
                except OSError as e:
                    print(
                        "Execution failed:",
                        e,
                        file=sys.stderr,
                    )
                    self._print(
                        "Execution failed !:",
                        e,
                        file=sys.stderr,
                    )
        self._print_done()

    def make(
        self,
        remove_existing=True,
        requirements=None,
        my_winpydir=None,
    ):  # , find_links=None):
        """Make WinPython distribution in target directory from the installers
        located in wheeldir

        remove_existing=True: (default) install all from scratch
        remove_existing=False: only for test purpose (launchers/scripts)
        requirements=file(s) of requirements (separated by space if several)"""
        if self.simulation:
            print(
                "WARNING: this is just a simulation!",
                file=sys.stderr,
            )
        print(
            self.python_fname,
            self.python_name,
            self.distname,
            self.python_fullversion,  # PyPy to delete or move
        )
        if my_winpydir is None:
            #self.winpydir = osp.join(
            #    self.target, self.distname  # PyPy to delete
            #)
            self.winpydir = str(Path(self.target) / self.distname)  # PyPy to delete
        else:
            #self.winpydir = osp.join(
            #    self.target, my_winpydir
            #)        # Create/re-create the WinPython base directory
            self.winpydir = str(Path(self.target) / my_winpydir)  # Create/re-create the WinPython base directory
        self._print(
            "Creating WinPython %s base directory"
            % my_winpydir
        )
        if (
            # osp.isdir(self.winpydir)
            Path(self.winpydir).is_dir()
            and remove_existing
            and not self.simulation
        ):
            shutil.rmtree(
                self.winpydir, onerror=utils.onerror
            )
        # if not osp.isdir(self.winpydir):
        if not Path(self.winpydir).is_dir():
            os.mkdir(self.winpydir)
        if remove_existing and not self.simulation:
            # Create settings directory
            # (only necessary if user is starting an application with a batch
            #  scripts before using an executable launcher, because the latter
            #  is creating the directory automatically)
            # os.mkdir(osp.join(self.winpydir, 'settings'))
            os.mkdir(str(Path(self.winpydir) / 'settings'))
            # os.mkdir(osp.join(self.winpydir, 'settings', 'AppData'))
            os.mkdir(str(Path(self.winpydir) / 'settings' / 'AppData'))
            # os.mkdir(osp.join(self.winpydir, 'settings', 'AppData', 'Roaming'))
            os.mkdir(str(Path(self.winpydir) / 'settings' / 'AppData' / 'Roaming'))
        self._print_done()

        if remove_existing and not self.simulation:
            self._extract_python()  # unzip Python interpreter

        self.distribution = wppm.Distribution(
            self.python_dir,
            verbose=self.verbose,
            indent=True,
        )

        # PyPy: get Fullversion from the executable
        self.python_fullversion = utils.get_python_long_version(
                self.distribution.target)

        # PyPY: Assert that WinPython version and real python version do match
        self._print(f"Python version{self.python_fullversion.replace('.','')}"+
                      f"\nDistro Name {self.distribution.target}")
        assert self.python_fullversion.replace('.','') in \
            self.distribution.target, \
            "Distro Directory doesn't match the Python version it ships" + \
            f"\nPython version: {self.python_fullversion.replace('.','')}"+ \
            f"\nDistro Name: {self.distribution.target}"

        if remove_existing:
            if not self.simulation:
                # self._add_msvc_files()  # replaced per msvc_runtime package
                self._create_batch_scripts_initial()
                self._create_batch_scripts()
                # always create all launchers (as long as it is NSIS-based)
                self._create_launchers()
            # pre-patch current pip (until default python has pip 8.0.3)

            # PyPY must ensure pip
            # "pypy3.exe -m ensurepip"
            utils.python_execmodule('ensurepip', self.distribution.target)

            self.distribution.patch_standard_packages('pip')
            # not forced update of pip (FIRST) and setuptools here
            for req in ('pip', 'setuptools', 'wheel', 'winpython'):
                actions = ["install", "--upgrade", "--pre", req]
                if self.install_options is not None:
                    actions += self.install_options
                print("piping %s" % ' '.join(actions))
                self._print("piping %s" % ' '.join(actions))
                self.distribution.do_pip_action(actions)
                self.distribution.patch_standard_packages(
                    req
                )
            # no more directory base package install: use requirements.txt
            # 2019-05-03 removed self._install_all_other_packages()
            print('self.simulation zz', self.simulation)
            if not self.simulation:
                self._copy_dev_tools()
                self._copy_dev_docs()
        if not self.simulation:

            if requirements:
                if not list(requirements) == requirements:
                    requirements = requirements.split()
                for req in requirements:
                    actions = ["install", "-r", req]
                    if self.install_options is not None:
                        actions += self.install_options
                    print("piping %s" % ' '.join(actions))
                    self._print(
                        "piping %s" % ' '.join(actions)
                    )
                    self.distribution.do_pip_action(actions)
                    # actions=["install","-r", req, "--no-index",
                    #         "--trusted-host=None"]+ links,
                    #         install_options=None)
            self._run_complement_batch_scripts()
            self.distribution.patch_standard_packages()
        if remove_existing and not self.simulation:
            self._print("Cleaning up distribution")
            self.distribution.clean_up()
            self._print_done()
        # Writing package index
        self._print("Writing package index")
        # winpyver2 = need the version without build part
        # but with self.distribution.architecture
        self.winpyver2 = '%s.%s' % (
            self.python_fullversion,
            self.build_number,
        )
        #fname = osp.join(
        #    self.winpydir,
        #    os.pardir,
        #    'WinPython%s-%sbit-%s.md'
        #    % (
        #        self.flavor,
        #        self.distribution.architecture,
        #        self.winpyver2,
        #    ),
        #)
        fname = str(Path(self.winpydir).parent / (
                f'WinPython{self.flavor}-' +
                f'{self.distribution.architecture}bit-'+
                f'{self.winpyver2}.md'))
        open(fname, 'w').write(self.package_index_wiki)
        # Copy to winpython/changelogs
        shutil.copyfile(
            fname,
            #osp.join(CHANGELOGS_DIR, osp.basename(fname)),
            str(Path(CHANGELOGS_DIR) / Path(fname).name),
        )
        self._print_done()

        # Writing changelog
        self._print("Writing changelog")
        diff.write_changelog(
            self.winpyver2,
            basedir=self.basedir,
            flavor=self.flavor,
            release_level=self.release_level,
            architecture=self.distribution.architecture,
        )
        self._print_done()

def rebuild_winpython(
    basedir, targetdir, architecture=64, verbose=False
):
    """Rebuild winpython package from source"""
    basedir = basedir
    packdir = targetdir
    for name in os.listdir(packdir):
        if name.startswith('winpython-') and name.endswith(
            ('.exe', '.whl')
        ):
            # os.remove(osp.join(packdir, name))
            os.remove(str(Path(packdir) / name))
    utils.build_wininst(
        # osp.dirname(osp.abspath(__file__)),
        str(Path(__file__).resolve().parent),
        copy_to=packdir,
        architecture=architecture,
        verbose=verbose,
        installer='bdist_wheel',
    )

def transform_in_list(list_in, list_type=None):
    """Transform a 'String or List' in List"""
    if list_in is None:
        list_in = ''
    if not list_in == list(list_in):
        list_in = list_in.split()
    if list_type:
        print(list_type, list_in)
    return list_in

def make_all(
    build_number,
    release_level,
    pyver,
    architecture,
    basedir,
    verbose=False,
    remove_existing=True,
    create_installer=True,
    simulation=False,
    install_options=['--no-index'],
    flavor='',
    requirements=None,
    find_links=None,
    source_dirs=None,
    toolsdirs=None,
    docsdirs=None,
    python_target_release=None, # 37101 for 3.7.10
):
    """Make WinPython distribution, for a given base directory and
    architecture:
    `build_number`: build number [int]
    `release_level`: release level (e.g. 'beta1', '') [str]
    `pyver`: python version ('3.4' or 3.5')
    `architecture`: [int] (32 or 64)
    `basedir`: where will be created tmp_wheel and Winpython build
              r'D:\Winpython\basedir34'.
    `requirements`: the package list for pip r'D:\requirements.txt',
    `install_options`: pip options r'--no-index --pre --trusted-host=None',
    `find_links`: package directories r'D:\Winpython\packages.srcreq',
    `source_dirs`: the python.zip + rebuilt winpython wheel package directory,
    `toolsdirs`: r'D:\WinPython\basedir34\t.Slim',
    `docsdirs`: r'D:\WinPython\basedir34\docs.Slim'    """

    assert (
        basedir is not None
    ), "The *basedir* directory must be specified"
    assert architecture in (32, 64)
    utils.print_box(
         # "Making WinPython %dbits at %s" % (architecture,
         # osp.join(basedir, 'bu' + flavor))
        "Making WinPython %dbits at %s" % (architecture,
                                    str(Path(basedir) / ('bu' + flavor))))

    # Create Build director, where Winpython will be constructed
    # builddir = osp.join(basedir, 'bu' + flavor)
    builddir = str(Path(basedir) / ('bu' + flavor) )
    # if not osp.isdir(builddir):
    if not Path(builddir).is_dir():
        os.mkdir(builddir)
    # use source_dirs as the directory to re-build Winpython wheel
    wheeldir = source_dirs

    # Rebuild Winpython in this wheel dir
    rebuild_winpython(
        basedir=basedir,
        targetdir=wheeldir,
        architecture=architecture,
    )

    # Optional pre-defined toolsdirs
    toolsdirs = transform_in_list(toolsdirs, 'toolsdirs=')

    # Optional pre-defined toolsdirs
    print('docsdirs input', docsdirs)
    docsdirs = transform_in_list(docsdirs, 'docsdirs=')
    print('docsdirs output', docsdirs)

    # install_options = ['--no-index', '--pre', '--find-links=%s' % wheeldir]
    install_options = transform_in_list(
        install_options, 'install_options'
    )

    find_links = transform_in_list(find_links, 'find_links')

    find_list = [
        '--find-links=%s' % l
        for l in find_links + [wheeldir]
    ]
    dist = WinPythonDistribution(
        build_number,
        release_level,
        builddir,
        wheeldir,
        toolsdirs,
        verbose=verbose,
        simulation=simulation,
        basedir=basedir,
        install_options=install_options + find_list,
        flavor=flavor,
        docsdirs=docsdirs,
    )
    # define a pre-defined winpydir, instead of having to guess

    # extract the python subversion to get WPy64-3671b1
    my_x = ''.join(
        dist.python_fname.replace('.amd64', '').split('.')[
            -2:-1
        ]
    )
    while not my_x.isdigit() and len(my_x) > 0:
        my_x = my_x[:-1]

    # simplify for PyPy
    if not python_target_release == None :
        my_winpydir = (
        'WPy'
        + ('%s' % architecture)
        + '-'
        + python_target_release
        + ''
        + ('%s' % build_number)
    ) + release_level
    # + flavor
    else:
        my_winpydir = (
        'WPy'
        + ('%s' % architecture)
        + '-'
        + pyver.replace('.', '')
        + ''
        + my_x
        + ''
        + ('%s' % build_number)
    ) + release_level
    # + flavor

    dist.make(
        remove_existing=remove_existing,
        requirements=requirements,
        my_winpydir=my_winpydir,
    )
    #          ,find_links=osp.join(basedir, 'packages.srcreq'))
    if (
        str(create_installer).lower() != 'false'
        and not simulation
    ):
        if 'nsis' in str(create_installer).lower():
            dist.create_installer()  # NSIS installer (can't handle big build)
        if 'inno' in str(create_installer).lower() or (
            str(create_installer).lower() == 'true'
        ):
            dist.create_installer_inno()  # INNO Setup 5 (not 7zip friendly)
        if '7zip' in str(create_installer).lower():
            dist.create_installer_7zip(
                '.exe'
            )  # 7-zip (no licence splash screen)
        if '.7z' in str(create_installer).lower():
            dist.create_installer_7zip(
                '.7z'
            )  # 7-zip (no licence splash screen)
        if '.zip' in str(create_installer).lower():
            dist.create_installer_7zip(
                '.zip'
            )  # 7-zip (no licence splash screen)
    return dist

if __name__ == '__main__':
    # DO create only one version at a time
    # You may have to manually delete previous build\winpython-.. directory

    make_all(
        1,
        release_level='build3',
        pyver='3.4',
        basedir=r'D:\Winpython\basedir34',
        verbose=True,
        architecture=64,
        flavor='Barebone',
        requirements=r'D:\Winpython\basedir34\barebone_requirements.txt',
        install_options=r'--no-index --pre --trusted-host=None',
        find_links=r'D:\Winpython\packages.srcreq',
        source_dirs=r'D:\WinPython\basedir34\packages.win-amd64',
        toolsdirs=r'D:\WinPython\basedir34\t.Slim',
        docsdirs=r'D:\WinPython\basedir34\docs.Slim',
    )


text:
Thomas Fuchs (* 10. Januar 1957 in Zürich) ist ein ehemaliger Schweizer Springreiter.

Leben
Fuchs wuchs gemeinsam mit seinem zwei Jahre älteren Bruder Markus in Bietenholz auf, wo sein Vater ab Mitte der 1960er Jahre einen Reitstall aufbaute.
Große Erfolge feierte er zwischen 1981 und 1991 auf der Stute Dollar Girl. Mit der Schweizer Equipe wurde er 1983 Europameister, 1981 Vize-Europameister und 1989 sowie 1991 jeweils Europameisterschafts-Dritter. Nachdem Dollar Girl von ihrem Besitzer Ende 1991 verkauft wurde, war der belgische Wallach Major sein Spitzenpferd.
Fuchs errang zwei weitere Team-Europameisterschaften in den Jahren 1993 und 1995. Bei den Weltreiterspielen 1994 gewann er mit der Mannschaft die Bronzemedaille. Im Einzel stehen ein siebter Platz bei den Olympischen Spielen 1988 in Seoul, ein vierter Platz im Weltcup-Finale 1992, zahlreiche Grand-Prix-Siege sowie drei Schweizer Meisterschaften zu Buche. Fuchs bestritt ca. 100 Nationenpreise. Sein Sohn Martin ist ebenfalls ein erfolgreicher Springreiter.

Thomas Fuchs ist mit der ehemaligen Springreiterin und Trabrennfahrerin Renata Fuchs verheiratet. Er handelt erfolgreich mit Pferden.

Größte Erfolge
 Olympische Spiele
 5. Rang Team, Barcelona 1992, mit Dylano
 7. Rang Einzel und Team, Seoul 1988, mit Dollar Girl

 Weltmeisterschaften
 Bronze Team, Den Haag 1994, mit Major AC Folien

 Europameisterschaften
 Gold Team, St. Gallen 1995, mit Major AC Folien
 Gold Team, Gijón 1993, mit Dylano
 Bronze Team, La Baule 1991, mit Dollar Girl
 Bronze Team, Rotterdam 1989, mit Dollar Girl
 Gold Team, Hickstead 1983, mit Willora Swiss
 Silber Team, München 1981, mit Willora Carpets

 Schweizer Meisterschaften
 1. Rang, 1995, mit Major AC Folien
 1. Rang, 1993, mit Dylano
 1. Rang, 1986, mit El Lute

 Weltcupfinales
 4. Rang, Del Mar 1992

Weblinks

 Pferdehandel – die Basis für erfolgreichen Springsport: Filmbeitrag über Thomas Fuchs in der SRF-sportlounge

Einzelnachweise

Springreiter
Olympiateilnehmer (Schweiz)
Teilnehmer der Olympischen Sommerspiele 1988
Teilnehmer der Olympischen Sommerspiele 1992
Reiter (Schweiz)
Schweizer Meister (Springreiten)
Schweizer
Geboren 1957
Mann

redpajama_set_name: RedPajamaWikipedia


In the first post of the series, I talked about what continuous integration is and why you should use it. In this post, I'm going to start by describing what Jenkins is and the steps on how to set it up. Next, we'll add plugins that will allow you to checkout a repository using Mercurial and to build the project using MSBuild. Finally, we'll configure a means of notifying you if a build fails by using Gmail.
Jenkins is a stand-alone continuous integration server that listens to a repository for changes. Once Jenkins sees that a check-in has occurred, it begins to perform a series of steps (called a build). These steps can range from building the solution, running tests, deploying databases, copying artifacts, building installers, creating documentation, or deploying software. Jenkins (and it's predecessor Hudson) have been around for quite a while now and is one of most commonly used CI servers around. One of the reasons I like Jenkins is that I can set it up on a virtual machine and have it running all the time.
How Do I Setup Jenkins?
The Jenkins server is pretty easy to setup. First, we will need to install the Java Runtime Environment (JRE). After installing the JRE, we will install the Jenkins tool. Once Jenkins is up and running we can proceed to install the plugins and start configuring the Jenkins instance.
The only dependency you need to run Jenkins is to install the Java JRE. You can download the latest run time from here. During the install, choose the defaults. After the JRE installs, you're ready to install Jenkins.
After downloading and installing the JRE, you will need to install the Jenkins server by going to http://jenkins-ci.org/ and choosing the appropriate download option for your system. After downloading, extract the zip folder and run the setup application. After the install you will now have a Jenkins service running at http://localhost:8080.
Now that we have Jenkins up and running, it's time to extend Jenkins by installing plugins that will allow us checkout out our source code and build the solution. These plugins make Jenkins very powerful since you can install which ones you need for your jobs. The following sections will detail how to install plugins in general and how to install the MSBuild and Mercurial plugins in detail.
As mentioned earlier, before we can create a job, we need to install the plugins required for said job. At the bare minimum for our example, you will need to install a plugin for your source control and a plugin for compilation.
In order to install a plugin, on the Jenkins machine, navigate to http://localhost:8080 and go to Manage Jenkins -> Manage Plugins (next to the green puzzle piece).
On this screen, you can see which plugins have updates, which plugins you have installed, and which plugins that are available for download. When adding/removing plugins, you will come to this area often.
After selecting the MSBuild plugin, it's time to install the plugins by clicking on the Download now and install after restart button. After clicking the button, click the check box and then Jenkins will restart.
After Jenkins restarts, it's time to configure the plugins to be able to use them in a job.
At this point, we have Jenkins up and running and our plugins installed. However, we need to configure these plugins so we can use them in a job. To configure plugins, we need to configure the system-wide settings of Jenkins. To get to this menu, navigate to http://localhost:8080 and click Manage Jenkins -> Configure System.
On this screen, every plugin installed with Jenkins is listed with some global settings for that plugin. In general, a plugin will need to know where the tool it uses resides at. For example, the Mercurial plugin needs to know where the mercurial executable is on the machine.
Before you can configure the plugin, you will need to have Mercurial installed (Need to install Mercurial?, look no further). Not sure if Mercurial is installed? Open up a command prompt and enter "hg version". If Mercurial has been installed, then you should see the version of Mercurial installed, otherwise, you probably don't have it installed.
To configure the plugin, navigate to the Configure System screen and look for the Mercurial section. After finding the section, click the Mercurial Installations button.
After clicking this button, there will be some options to configure. For this setup, the most important ones are Name, Installation Directory, and Executable.
The Name field is what's shown when selecting the source control for a build, so make sure it's descriptive. I usually include the version number as part of the name.
The Installation Directory field is where the Mercurial executable is located. If you Mercurial is part of your path, then you don't need to specify this, otherwise, just enter the directory that the executable is located.
The Executable field is where you specify what the name of your mercurial executable is. The majority of the time, hg.exe is the name you want, so shouldn't have to change this.
Configuring the MSBuild plugin is similar to configuring the Mercurial plugin. As before, navigate to the Configure System screen and find the MSBuild section. From here, find the MSBuild section and click the MSBuild Installations button.
After clicking this button, there will be some options to configure. For this setup, the most important ones are Name, Path To MSBuild, and Default Parameters.
The Name field is what's shown when selecting the compiler for a build, so make sure it's descriptive. I usually include the version number as part of the name.
The Path To MSBuild field is where the MSBuild executable is located. By clicking the ? button, it will tell you what the default path is for MSBuild. Since the MSBuild is included in every Windows machine, this location should be the one to use. Make sure you add msbuild.exe to the end of the path (even though you will get a warning message, you need to provide the full path).
The Default Parameters field is where you can specify additional command switches to MSBuild. This can be helpful if you have a certain configuration you want used when building (like build in release mode). It's not necessary to add any switches for MSBuild to work out of the box, so I'm omitting it here.
At this point, we have the source control and compiler plugins configured, but the last big thing that we need to do is setup some way to be notified if a build fails. In this example, we'll be setting up email notifications, however, there are plugins for many popular communication tools (Slack, HipChat, etc..).
To configure the email notifications, go to the System Configuration screen and find the Jenkins Location section. Here, specify the System Admin e-mail address for Jenkins (this does not have to be a valid email address, but it does need to be entered).
After entering an email for Jenkins, find the E-mail Notification section. This is where we will specify what mail server and other options to send out the notifications.
Since we're using Gmail for our communications, we need to specify that in the SMTP server field and we need to click the Advanced… button to have some more configuration.
To ensure that the email notification is configured correctly, click the Test Configuration by sending test e-mail button and enter a valid email address.
When you click the button, you should get a success message. If, however, you get the following message, it's probably due to Google locking down access to less secure 3rd party applications.
If that's the case, you will need to tweak your Gmail settings (http://accounts.google.com/security) so that less secure applications can access your account (see below).
In this post, we installed Jenkins, a continuous integration server. Next, we installed the Mercurial and MSBuild plugins. After installing the plugins, we configured them to work with the installed tools. Finally, we configured Jenkins to send emails notifications through Gmail that allows Jenkins to alert us when a build fails.
In the final post for the series, we will be creating a simple job that will checkout a .NET solution, compile it, and deploying it to a different server.


An interactive sticker board to commemorate the miniature hawker centre diorama I've made in collaboration with AICLAY and MSPARKPARK. You can watch the whole process for most of the miniatures featured in the sticker pack HERE!
・Lotsa fun and a decoration piece at the end!
These sticker board and stickers pack are illustrated, cut, assembled, packed, and delivered by handxmade! As a result products may have subtle variations or imperfections.


It observes particles of solar, interplanetary, interstellar, and galactic origins, spanning the energy range from solar wind ions to galactic cosmic ray nuclei.
Exploring Polar Mesospheric Clouds (PMCs), also called noctilucent clouds, to find out why they form and why they are changing.
Investigated and forecasted scintillations in the Earth's ionosphere.
An international and multi-agency space mission that studies the cosmos in the energy range 10 rev-300GeV.
Is a space telescope that was launched into low Earth orbit in 1009, and remains in operation. Although not the first space telescope, Hubble is one of the largest and most versatile, and is well known as both a vital research tool and a public relations boon for astronomy.
Will investigate the forces at play in the near-space environment, leading the way in understanding disturbances that can lead to severe interference with communications and GPS signals.
Observes how solar material moves, gathers energy, and heats up as it travels through a little-understood region in the sun's lower atmosphere.
It will study every phase in the history of our Universe, ranging from the first luminous glows after the Big Band, to the formation of solar systems capable of supporting life on planets like Earth, to the evolution of our own Solar System.
Robotic spacecraft currently orbiting the Moon in an eccentric polar mapping orbit. Data collected by LRO has been described as essential for planing NASA's future human and robotic missions to the moon.
Investigated how the Sun's and Earth's magnetic fields connect and disconnect, explosively transferring energy from one to the other in a process that is important to the Sun, other planets, and everywhere in the Universe.
Harvests measurements of asteroids and comets from WISE images and provides a rich archive for searching WISE data for solar system objects.
The first orbiting telescopes to focus light in the high energy X-ray (6-79keV) region of the electromagnetic spectrum.
To explore the basic physics of particle acceleration and explosive energy release in solar flares.
To understand the causes of solar variability and it's impacts on Earth. SDO is designed to help us understand the Sun's influence on Earth and Near-Earth space by studying the solar atmosphere on small scales of space and time and in many wavelengths simultaneously.
Designed to study the internal structure of the Sun, its extensive outer atmosphere and the origin of the solar wind, the stream of highly ionized gas that blows continuously outward through the Solar System.
A highly sophisticated observational satellite equipped with three advanced solar telescopes to explore the magnetic fields of the Sun. It consists of a coordinated set of optical, extreme ultraviolet (EUV), and x-ray instruments to investigate the interaction between the Sun's magnetic field and it's corona.
A first-of-its-kind multi-wavelength observatory dedicated to the study of gamma-ray burst (GRB) science. Its three instruments work together to observe GRBs and afterglows in the gamma-ray, S-ray, ultraviolet, and optical wavebands.
On orbit, geosynchronous telecommunications satellites that support NASA Missions with the transmission of data to the ground.
Identifies planets ranging from Earth-sized to gas giants, orbiting a wider range of stellar types and orbital distances. The principal goal is to detect small planets with bright host starts in the solar neighborhood, so that detailed characterizations of the planets and their atmospheres can be performed.
Aims to resolve one of the oldest mysteries in space physics, namely to determine what physical process in near-Earth space initiates the violent eruptions if the aurora that occur during substorms in the Earth's magnetosphere.
Is an orbiter mission dedicated to study the dynamics of the Mesosphere and Lower Therosphere portion of the Earth's atmosphere.
Will study two extreme and dynamic regions of space known as the Van Allen Radiation Belts that surround Earth.