Exemplo n.º 1
0
 def test_custom_executable(self):
     fn = os.path.join(HERE, 'dummy-0.1-py27-none-any.whl')
     for executable in 'mypython', None:
         dstdir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, dstdir)
         w = Wheel(fn)
         paths = {'prefix': dstdir}
         for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
             paths[key] = os.path.join(dstdir, key)
         maker = ScriptMaker(None, None)
         maker.variants = set([''])
         maker.executable = executable
         w.install(paths, maker)
         # On Windows there will be an exe file, and on POSIX a text file.
         # The test is structured to not care.
         p = paths['scripts']
         # there should be just one file in the directory - dummy.py/dummy.exe
         p = os.path.join(p, os.listdir(p)[0])
         with open(p, 'rb') as f:
             data = f.read()
         if executable is None:
             expected = fsencode(get_executable())
         else:
             expected = executable.encode('utf-8')
         expected = b'#!' + expected + b' -E'
         if not sysconfig.is_python_build():
             self.assertIn(expected, data)
Exemplo n.º 2
0
 def test_custom_executable(self):
     fn = os.path.join(HERE, "dummy-0.1-py27-none-any.whl")
     for executable in "mypython", None:
         dstdir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, dstdir)
         w = Wheel(fn)
         paths = {"prefix": dstdir}
         for key in ("purelib", "platlib", "headers", "scripts", "data"):
             paths[key] = os.path.join(dstdir, key)
         maker = ScriptMaker(None, None)
         maker.variants = set([""])
         maker.executable = executable
         w.install(paths, maker)
         # On Windows there will be an exe file, and on POSIX a text file.
         # The test is structured to not care.
         p = paths["scripts"]
         # there should be just one file in the directory - dummy.py/dummy.exe
         p = os.path.join(p, os.listdir(p)[0])
         with open(p, "rb") as f:
             data = f.read()
         if executable is None:
             expected = fsencode(get_executable())
         else:
             expected = executable.encode("utf-8")
         expected = b"#!" + expected + b" -E"
         if not sysconfig.is_python_build():
             self.assertIn(expected, data)
Exemplo n.º 3
0
 def test_custom_executable(self):
     fn = os.path.join(HERE, 'dummy-0.1-py27-none-any.whl')
     for executable in 'mypython', None:
         dstdir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, dstdir)
         w = Wheel(fn)
         paths = {'prefix': dstdir}
         for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
             paths[key] = os.path.join(dstdir, key)
         maker = ScriptMaker(None, None)
         maker.variants = set([''])
         maker.executable = executable
         w.install(paths, maker)
         # On Windows there will be an exe file, and on POSIX a text file.
         # The test is structured to not care.
         p = paths['scripts']
         # there should be just one file in the directory - dummy.py/dummy.exe
         p = os.path.join(p, os.listdir(p)[0])
         with open(p, 'rb') as f:
             data = f.read()
         if executable is None:
             expected = fsencode(get_executable())
         else:
             expected = executable.encode('utf-8')
         expected = b'#!' + expected + b' -E'
         self.assertIn(expected, data)
Exemplo n.º 4
0
 def update_shebangs(self, new_path: str) -> None:
     """Update the shebang lines"""
     scripts = self.get_paths()["scripts"]
     maker = ScriptMaker(None, None)
     maker.executable = new_path
     shebang = maker._get_shebang("utf-8").rstrip()
     for child in Path(scripts).iterdir():
         if not child.is_file() or child.suffix not in (".exe", ".py", ""):
             continue
         child.write_bytes(
             re.sub(rb"#!.+?python.*?$", shebang, child.read_bytes(), flags=re.M)
         )
Exemplo n.º 5
0
    def _create_console_entry_point(self, name, value, to_folder):
        result = []
        from distlib.scripts import ScriptMaker

        maker = ScriptMaker(None, str(to_folder))
        maker.clobber = True  # overwrite
        maker.variants = {"", "X", "X.Y"}  # create all variants
        maker.set_mode = True  # ensure they are executable
        maker.executable = str(self._creator.exe)
        specification = "{} = {}".format(name, value)
        new_files = maker.make(specification)
        result.extend(Path(i) for i in new_files)
        return result
Exemplo n.º 6
0
 def _create_console_entry_point(self, name, value, to_folder, version_info):
     result = []
     maker = ScriptMaker(None, str(to_folder))
     maker.clobber = True  # overwrite
     maker.variants = {""}  # set within patch_distlib_correct_variants
     maker.set_mode = True  # ensure they are executable
     # calling private until https://bitbucket.org/pypa/distlib/issues/135/expose-_enquote_executable-as-public
     maker.executable = _enquote_executable(str(self._creator.exe))
     specification = "{} = {}".format(name, value)
     with self.patch_distlib_correct_variants(version_info, maker):
         new_files = maker.make(specification)
     result.extend(Path(i) for i in new_files)
     return result
Exemplo n.º 7
0
    def _create_console_entry_point(self, name, value, to_folder):
        result = []
        if IS_WIN:
            # windows doesn't support simple script files, so fallback to more complicated exe generator
            from distlib.scripts import ScriptMaker

            maker = ScriptMaker(None, str(to_folder))
            maker.clobber = True  # overwrite
            maker.variants = {"", "X", "X.Y"}  # create all variants
            maker.set_mode = True  # ensure they are executable
            maker.executable = str(self._creator.exe)
            specification = "{} = {}".format(name, value)
            new_files = maker.make(specification)
            result.extend(Path(i) for i in new_files)
        else:
            module, func = value.split(":")
            content = (
                dedent(
                    """
            #!{0}
            # -*- coding: utf-8 -*-
            import re
            import sys

            from {1} import {2}

            if __name__ == "__main__":
                sys.argv[0] = re.sub(r"(-script.pyw?|.exe)?$", "", sys.argv[0])
                sys.exit({2}())
            """
                )
                .lstrip()
                .format(self._creator.exe, module, func)
            )

            version = self._creator.interpreter.version_info
            for new_name in (
                name,
                "{}{}".format(name, version.major),
                "{}-{}.{}".format(name, version.major, version.minor),
            ):
                exe = to_folder / new_name
                exe.write_text(content, encoding="utf-8")
                make_exe(exe)
                result.append(exe)
        return result
Exemplo n.º 8
0
 def test_custom_shebang(self):
     # Construct an executable with a space in it
     self.maker.executable = 'an executable with spaces'
     filenames = self.maker.make('script1.py')
     with open(filenames[0], 'rb') as f:
         first_line = f.readline()
         second_line = f.readline()
         third_line = f.readline()
     self.assertEqual(first_line, b'#!/bin/sh\n')
     self.assertEqual(second_line, b"'''exec' an executable with "
                      b'spaces "$0" "$@"\n')
     self.assertEqual(third_line, b"' '''\n")
     # Python 3.3 cannot create a venv in an existing directory
     if venv and sys.version_info[:2] >= (3, 4):
         if sys.platform == 'darwin':
             # Supposedly 512, but various symlinks mean that temp folder
             # names get larger than you'd expect ... might vary on different
             # OS versions, too
             dlen = 220
         else:
             dlen = 127
         dstdir = tempfile.mkdtemp(suffix='cataaaaaa' + 'a' * dlen)
         self.addCleanup(shutil.rmtree, dstdir)
         bindir = os.path.join(dstdir, 'bin')
         maker = ScriptMaker(self.maker.source_dir,
                             bindir,
                             add_launchers=False)
         venv.create(dstdir)
         maker.executable = os.path.join(bindir, 'python')
         filenames = maker.make('script8.py')
         p = subprocess.Popen(filenames[0],
                              shell=True,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
         stdout, stderr = p.communicate()
         self.assertEqual(p.returncode, 0)
         self.assertEqual(stderr, b'')
         expected = os.path.realpath(maker.executable)  # symlinks on OS X
         actual = os.path.realpath(stdout.strip())
         self.assertEqual(actual, expected.encode('utf-8'))
Exemplo n.º 9
0
 def test_shebangs_custom_executable(self):
     srcdir = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, srcdir)
     dstdir = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, dstdir)
     maker = ScriptMaker(srcdir, dstdir, add_launchers=False)
     maker.executable = 'this_should_appear_in_the_shebang_line'
     #let's create the script to be copied. It has a vanilla shebang line.
     fn = os.path.join(srcdir, 'copied')
     with open(fn, 'w') as f:
         f.write(COPIED_SCRIPT)
     # Let's ask the maker to copy the script, and see what the shebang is
     # in the copy.
     filenames = maker.make('copied')
     with open(filenames[0], 'r') as f:
         actual = f.readline()
     self.assertIn(maker.executable, actual)
     # Now let's make a script from a callable
     filenames = maker.make(MADE_SCRIPT)
     with open(filenames[0], 'r') as f:
         actual = f.readline()
     self.assertIn(maker.executable, actual)
Exemplo n.º 10
0
    def do_build_and_install(self, dist):
        srcdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, srcdir)
        dstdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, dstdir)

        paths = install_dist(dist, srcdir)
        paths['prefix'] = srcdir
        w = Wheel()
        w.name = paths.pop('name')
        w.version = paths.pop('version')
        w.dirname = srcdir
        pathname = w.build(paths)
        self.assertTrue(os.path.exists(pathname))

        paths = {'prefix': dstdir}
        for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
            paths[key] = os.path.join(dstdir, key)
        w = Wheel(pathname)
        maker = ScriptMaker(None, None, add_launchers=False)
        maker.executable = os.path.join(paths['scripts'], 'python')
        dist = w.install(paths, maker)
        self.assertIsNotNone(dist)
        self.assertEqual(dist.name, w.name)
        self.assertEqual(dist.version, w.version)
        shared = dist.shared_locations
        self.assertTrue(shared)
        os.remove(pathname)
        sm = Manifest(srcdir)
        sm.findall()
        sfiles = set([os.path.relpath(p, srcdir) for p in sm.allfiles])
        dm = Manifest(dstdir)
        dm.findall()
        dfiles = set([os.path.relpath(p, dstdir) for p in dm.allfiles])
        omitted = sfiles - dfiles
        omitted = omitted.pop()
        endings = os.path.join('.dist-info', 'WHEEL'), '.pyc', '.pyo'
        self.assertTrue(omitted.endswith(endings))
Exemplo n.º 11
0
    def do_build_and_install(self, dist):
        srcdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, srcdir)
        dstdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, dstdir)

        paths = install_dist(dist, srcdir)
        paths['prefix'] = srcdir
        w = Wheel()
        w.name = paths.pop('name')
        w.version = paths.pop('version')
        w.dirname = srcdir
        pathname = w.build(paths)
        self.assertTrue(os.path.exists(pathname))

        paths = {'prefix': dstdir}
        for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
            paths[key] = os.path.join(dstdir, key)
        w = Wheel(pathname)
        maker = ScriptMaker(None, None, add_launchers=False)
        maker.executable = os.path.join(paths['scripts'], 'python')
        dist = w.install(paths, maker)
        self.assertIsNotNone(dist)
        self.assertEqual(dist.name, w.name)
        self.assertEqual(dist.version, w.version)
        shared = dist.shared_locations
        self.assertTrue(shared)
        os.remove(pathname)
        sm = Manifest(srcdir)
        sm.findall()
        sfiles = set([os.path.relpath(p, srcdir) for p in sm.allfiles])
        dm = Manifest(dstdir)
        dm.findall()
        dfiles = set([os.path.relpath(p, dstdir) for p in dm.allfiles])
        omitted = sfiles - dfiles
        omitted = omitted.pop()
        endings = os.path.join('.dist-info', 'WHEEL'), '.pyc', '.pyo'
        self.assertTrue(omitted.endswith(endings))
Exemplo n.º 12
0
    def do_build_and_install(self, dist):
        srcdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, srcdir)
        dstdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, dstdir)

        paths = install_dist(dist, srcdir)
        paths["prefix"] = srcdir
        w = Wheel()
        w.name = paths.pop("name")
        w.version = paths.pop("version")
        w.dirname = srcdir
        pathname = w.build(paths)
        self.assertTrue(os.path.exists(pathname))

        paths = {"prefix": dstdir}
        for key in ("purelib", "platlib", "headers", "scripts", "data"):
            paths[key] = os.path.join(dstdir, key)
        w = Wheel(pathname)
        maker = ScriptMaker(None, None, add_launchers=False)
        maker.executable = os.path.join(paths["scripts"], "python")
        dist = w.install(paths, maker)
        self.assertIsNotNone(dist)
        self.assertEqual(dist.name, w.name)
        self.assertEqual(dist.version, w.version)
        shared = dist.shared_locations
        self.assertTrue(shared)
        os.remove(pathname)
        sm = Manifest(srcdir)
        sm.findall()
        sfiles = set([os.path.relpath(p, srcdir) for p in sm.allfiles])
        dm = Manifest(dstdir)
        dm.findall()
        dfiles = set([os.path.relpath(p, dstdir) for p in dm.allfiles])
        omitted = sfiles - dfiles
        omitted = omitted.pop()
        endings = os.path.join(".dist-info", "WHEEL"), ".pyc", ".pyo"
        self.assertTrue(omitted.endswith(endings))
Exemplo n.º 13
0
 def test_shebangs_custom_executable(self):
     srcdir = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, srcdir)
     dstdir = tempfile.mkdtemp()
     self.addCleanup(shutil.rmtree, dstdir)
     maker = ScriptMaker(srcdir, dstdir, add_launchers=False)
     maker.executable = 'this_should_appear_in_the_shebang_line(中文)'
     # let's create the script to be copied. It has a vanilla shebang line,
     # with some Unicode in it.
     fn = os.path.join(srcdir, 'copied')
     with open(fn, 'w') as f:
         f.write(COPIED_SCRIPT)
     # Let's ask the maker to copy the script, and see what the shebang is
     # in the copy.
     filenames = maker.make('copied')
     with open(filenames[0], 'rb') as f:
         actual = f.readline().decode('utf-8')
     self.assertIn(maker.executable, actual)
     # Now let's make a script from a callable
     filenames = maker.make(MADE_SCRIPT)
     with open(filenames[0], 'rb') as f:
         actual = f.readline().decode('utf-8')
     self.assertIn(maker.executable, actual)
Exemplo n.º 14
0
    def create_production_scripts(self, tool, venv_session):
        """Create Rez production used binary scripts

        The binary script will be executed with Python interpreter flag -E,
        which will ignore all PYTHON* env vars, e.g. PYTHONPATH and PYTHONHOME.

        """
        _log.info("Generating production scripts..")

        site_packages = venv_session.creator.purelib
        bin_path = venv_session.creator.bin_dir

        if tool.edit:
            egg_link = site_packages / ("%s.egg-link" % tool.name)
            if not egg_link.is_file():
                _log.error("Tool %r installed in edit mode, but unable "
                           "to find egg-link for generating production "
                           "scripts from source. File not exists: %s" %
                           (tool.name, egg_link))
                return

            with open(str(egg_link), "r") as f:
                package_location = f.readline().strip()
            path = [str(package_location)]
        else:
            path = [str(site_packages)]

        dists = Distribution.discover(name=tool.name, path=path)
        specifications = {
            ep.name: "{ep.name} = {ep.value}".format(ep=ep)
            for dist in dists for ep in dist.entry_points
            if ep.group == "console_scripts"
        }

        # delete bin files written into virtualenv
        # this also avoided naming conflict between script 'rez' and dir 'rez'
        for script_name in specifications.keys():
            script_path = bin_path / script_name
            if script_path.is_file():
                os.remove(str(script_path))

        venv_name = tool.name if tool.isolation else "rez"
        prod_bin_path = self._revision.production_bin_dir(venv_name)
        makedirs(prod_bin_path)

        maker = ScriptMaker(source_dir=None, target_dir=str(prod_bin_path))
        maker.executable = str(venv_session.creator.exe)

        # Align with wheel
        #
        # Ensure we don't generate any variants for scripts because this is
        # almost never what somebody wants.
        # See https://bitbucket.org/pypa/distlib/issue/35/
        maker.variants = {""}
        # Ensure old scripts are overwritten.
        # See https://github.com/pypa/pip/issues/1800
        maker.clobber = True
        # This is required because otherwise distlib creates scripts that are
        # not executable.
        # See https://bitbucket.org/pypa/distlib/issue/32/
        maker.set_mode = True

        if self._rez_in_edit:
            # Allow pre-caching rez_bin_path on script entry if environ var
            # `REZUP_EDIT_IN_PRODUCTION` is set with non-empty value.
            # See https://github.com/davidlatwe/rezup/pull/56
            maker.script_template = r'''# -*- coding: utf-8 -*-
import re
import os
import sys
from %(module)s import %(import_name)s
if os.getenv("REZUP_EDIT_IN_PRODUCTION"):
    from rez.system import system
    setattr(system, 'rez_bin_path', r'{rez_bin_path}')
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(%(func)s())
'''.format(rez_bin_path=str(prod_bin_path))

        scripts = maker.make_multiple(
            specifications=specifications.values(),
            options=dict(interpreter_args=list(tool.flags)))

        return scripts