Exemplo n.º 1
0
def install(project):
    """Installs a project.

    Returns True on success, False on failure
    """
    if is_python_build():
        # Python would try to install into the site-packages directory under
        # $PREFIX, but when running from an uninstalled code checkout we don't
        # want to create directories under the installation root
        message = ('installing third-party projects from an uninstalled '
                   'Python is not supported')
        logger.error(message)
        return False

    logger.info('Checking the installation location...')
    purelib_path = get_path('purelib')

    # trying to write a file there
    try:
        testfile = tempfile.NamedTemporaryFile(suffix=project,
                                               dir=purelib_path)
        try:
            testfile.write('test')
        finally:
            testfile.close()
    except OSError:
        # FIXME this should check the errno, or be removed altogether (race
        # condition: the directory permissions could be changed between here
        # and the actual install)
        logger.info('Unable to write in "%s". Do you have the permissions ?'
                    % purelib_path)
        return False

    logger.info('Getting information about %r...', project)
    try:
        info = get_infos(project)
    except InstallationException:
        logger.info('Cound not find %r', project)
        return False

    if info['install'] == []:
        logger.info('Nothing to install')
        return False

    install_path = get_config_var('base')
    try:
        install_from_infos(install_path,
                           info['install'], info['remove'], info['conflict'])

    except InstallationConflict, e:
        if logger.isEnabledFor(logging.INFO):
            projects = ('%r %s' % (p.name, p.version) for p in e.args[0])
            logger.info('%r conflicts with %s', project, ','.join(projects))
Exemplo n.º 2
0
def install(project):
    """Installs a project.

    Returns True on success, False on failure
    """
    if is_python_build():
        # Python would try to install into the site-packages directory under
        # $PREFIX, but when running from an uninstalled code checkout we don't
        # want to create directories under the installation root
        message = ('installing third-party projects from an uninstalled '
                   'Python is not supported')
        logger.error(message)
        return False

    logger.info('Checking the installation location...')
    purelib_path = get_path('purelib')

    # trying to write a file there
    try:
        with tempfile.NamedTemporaryFile(suffix=project,
                                         dir=purelib_path) as testfile:
            testfile.write(b'test')
    except OSError:
        # FIXME this should check the errno, or be removed altogether (race
        # condition: the directory permissions could be changed between here
        # and the actual install)
        logger.info('Unable to write in "%s". Do you have the permissions ?' %
                    purelib_path)
        return False

    logger.info('Getting information about %r...', project)
    try:
        info = get_infos(project)
    except InstallationException:
        logger.info('Cound not find %r', project)
        return False

    if info['install'] == []:
        logger.info('Nothing to install')
        return False

    install_path = get_config_var('base')
    try:
        install_from_infos(install_path, info['install'], info['remove'],
                           info['conflict'])

    except InstallationConflict as e:
        if logger.isEnabledFor(logging.INFO):
            projects = ('%r %s' % (p.name, p.version) for p in e.args[0])
            logger.info('%r conflicts with %s', project, ','.join(projects))

    return True
Exemplo n.º 3
0
def fixup_build_ext(cmd):
    """Function needed to make build_ext tests pass.

    When Python was built with --enable-shared on Unix, -L. is not enough to
    find libpython<blah>.so, because regrtest runs in a tempdir, not in the
    source directory where the .so lives.  (Mac OS X embeds absolute paths
    to shared libraries into executables, so the fixup is a no-op on that
    platform.)

    When Python was built with in debug mode on Windows, build_ext commands
    need their debug attribute set, and it is not done automatically for
    some reason.

    This function handles both of these things, and also fixes
    cmd.distribution.include_dirs if the running Python is an uninstalled
    build.  Example use:

        cmd = build_ext(dist)
        support.fixup_build_ext(cmd)
        cmd.ensure_finalized()
    """
    if os.name == 'nt':
        cmd.debug = sys.executable.endswith('_d.exe')
    elif sysconfig.get_config_var('Py_ENABLE_SHARED'):
        # To further add to the shared builds fun on Unix, we can't just add
        # library_dirs to the Extension() instance because that doesn't get
        # plumbed through to the final compiler command.
        runshared = sysconfig.get_config_var('RUNSHARED')
        if runshared is None:
            cmd.library_dirs = ['.']
        else:
            if sys.platform == 'darwin':
                cmd.library_dirs = []
            else:
                # FIXME no partition in 2.4
                name, equals, value = runshared.partition('=')
                cmd.library_dirs = value.split(os.pathsep)

    # Allow tests to run with an uninstalled Python
    if sysconfig.is_python_build():
        pysrcdir = sysconfig.get_config_var('projectbase')
        cmd.distribution.include_dirs.append(os.path.join(pysrcdir, 'Include'))
Exemplo n.º 4
0
def fixup_build_ext(cmd):
    """Function needed to make build_ext tests pass.

    When Python was built with --enable-shared on Unix, -L. is not enough to
    find libpython<blah>.so, because regrtest runs in a tempdir, not in the
    source directory where the .so lives.  (Mac OS X embeds absolute paths
    to shared libraries into executables, so the fixup is a no-op on that
    platform.)

    When Python was built with in debug mode on Windows, build_ext commands
    need their debug attribute set, and it is not done automatically for
    some reason.

    This function handles both of these things, and also fixes
    cmd.distribution.include_dirs if the running Python is an uninstalled
    build.  Example use:

        cmd = build_ext(dist)
        support.fixup_build_ext(cmd)
        cmd.ensure_finalized()
    """
    if os.name == 'nt':
        cmd.debug = sys.executable.endswith('_d.exe')
    elif sysconfig.get_config_var('Py_ENABLE_SHARED'):
        # To further add to the shared builds fun on Unix, we can't just add
        # library_dirs to the Extension() instance because that doesn't get
        # plumbed through to the final compiler command.
        runshared = sysconfig.get_config_var('RUNSHARED')
        if runshared is None:
            cmd.library_dirs = ['.']
        else:
            if sys.platform == 'darwin':
                cmd.library_dirs = []
            else:
                # FIXME no partition in 2.4
                name, equals, value = runshared.partition('=')
                cmd.library_dirs = value.split(os.pathsep)

    # Allow tests to run with an uninstalled Python
    if sysconfig.is_python_build():
        pysrcdir = sysconfig.get_config_var('projectbase')
        cmd.distribution.include_dirs.append(os.path.join(pysrcdir, 'Include'))
Exemplo n.º 5
0
    def test_install_permission_denied(self):
        # if we don't have access to the installation path, we should abort
        # immediately
        project = os.path.join(os.path.dirname(__file__), 'package.tgz')

        # when running from an uninstalled build, a warning is emitted and the
        # installation is not attempted
        if is_python_build():
            self.assertFalse(install.install(project))
            self.assertEqual(1, len(self.get_logs(logging.ERROR)))
            return

        install_path = self.mkdtemp()
        old_get_path = install.get_path
        install.get_path = lambda path: install_path
        old_mod = os.stat(install_path).st_mode
        os.chmod(install_path, 0)
        try:
            self.assertFalse(install.install(project))
        finally:
            os.chmod(install_path, old_mod)
            install.get_path = old_get_path
Exemplo n.º 6
0
    def test_install_permission_denied(self):
        # if we don't have access to the installation path, we should abort
        # immediately
        project = os.path.join(os.path.dirname(__file__), "package.tgz")

        # when running from an uninstalled build, a warning is emitted and the
        # installation is not attempted
        if is_python_build():
            self.assertFalse(install.install(project))
            self.assertEqual(1, len(self.get_logs(logging.ERROR)))
            return

        install_path = self.mkdtemp()
        old_get_path = install.get_path
        install.get_path = lambda path: install_path
        old_mod = os.stat(install_path).st_mode
        os.chmod(install_path, 0)
        try:
            self.assertFalse(install.install(project))
        finally:
            os.chmod(install_path, old_mod)
            install.get_path = old_get_path
Exemplo n.º 7
0
    def copy_scripts(self):
        """Copy each script listed in 'self.scripts'; if it's marked as a
        Python script in the Unix way (first line matches 'first_line_re',
        ie. starts with "\#!" and contains "python"), then adjust the first
        line to refer to the current Python interpreter as we copy.
        """
        # XXX use self.execute(shutil.rmtree, ...)
        self.rmpath(self.build_dir)
        self.mkpath(self.build_dir)
        outfiles = []
        for script in self.scripts:
            adjust = False
            script = convert_path(script)
            outfile = os.path.join(self.build_dir, os.path.basename(script))
            outfiles.append(outfile)

            # Always open the file, but ignore failures in dry-run mode --
            # that way, we'll get accurate feedback if we can read the
            # script.
            try:
                f = open(script, "rb")
            except IOError:
                if not self.dry_run:
                    raise
                f = None
            else:
                encoding, lines = detect_encoding(f.readline)
                f.seek(0)
                first_line = f.readline()
                if not first_line:
                    logger.warning('%s: %s is an empty file (skipping)',
                                   self.get_command_name(),  script)
                    continue

                match = first_line_re.match(first_line)
                if match:
                    adjust = True
                    post_interp = match.group(1) or ''

            if adjust:
                logger.info("copying and adjusting %s -> %s", script,
                         self.build_dir)
                if not self.dry_run:
                    if not sysconfig.is_python_build():
                        executable = self.executable
                    else:
                        executable = os.path.join(
                            sysconfig.get_config_var("BINDIR"),
                           "python%s%s" % (sysconfig.get_config_var("VERSION"),
                                           sysconfig.get_config_var("EXE")))
                    executable = fsencode(executable)
                    shebang = "#!" + executable + post_interp + "\n"
                    # Python parser starts to read a script using UTF-8 until
                    # it gets a #coding:xxx cookie. The shebang has to be the
                    # first line of a file, the #coding:xxx cookie cannot be
                    # written before. So the shebang has to be decodable from
                    # UTF-8.
                    try:
                        shebang.decode('utf-8')
                    except UnicodeDecodeError:
                        raise ValueError(
                            "The shebang (%r) is not decodable "
                            "from utf-8" % shebang)
                    # If the script is encoded to a custom encoding (use a
                    # #coding:xxx cookie), the shebang has to be decodable from
                    # the script encoding too.
                    try:
                        shebang.decode(encoding)
                    except UnicodeDecodeError:
                        raise ValueError(
                            "The shebang (%r) is not decodable "
                            "from the script encoding (%s)" % (
                                shebang, encoding))
                    outf = open(outfile, "wb")
                    try:
                        outf.write(shebang)
                        outf.writelines(f.readlines())
                    finally:
                        outf.close()
                if f:
                    f.close()
            else:
                if f:
                    f.close()
                self.copy_file(script, outfile)

        if os.name == 'posix':
            for file in outfiles:
                if self.dry_run:
                    logger.info("changing mode of %s", file)
                else:
                    oldmode = os.stat(file).st_mode & 07777
                    newmode = (oldmode | 0555) & 07777
                    if newmode != oldmode:
                        logger.info("changing mode of %s from %o to %o",
                                 file, oldmode, newmode)
                        os.chmod(file, newmode)
        return outfiles
Exemplo n.º 8
0
    def copy_scripts(self):
        """Copy each script listed in 'self.scripts'; if it's marked as a
        Python script in the Unix way (first line matches 'first_line_re',
        ie. starts with "\#!" and contains "python"), then adjust the first
        line to refer to the current Python interpreter as we copy.
        """
        # XXX use self.execute(shutil.rmtree, ...)
        self.rmpath(self.build_dir)
        self.mkpath(self.build_dir)
        outfiles = []
        for script in self.scripts:
            adjust = False
            script = convert_path(script)
            outfile = os.path.join(self.build_dir, os.path.basename(script))
            outfiles.append(outfile)

            # Always open the file, but ignore failures in dry-run mode --
            # that way, we'll get accurate feedback if we can read the
            # script.
            try:
                f = open(script, "rb")
            except IOError:
                if not self.dry_run:
                    raise
                f = None
            else:
                encoding, lines = detect_encoding(f.readline)
                f.seek(0)
                first_line = f.readline()
                if not first_line:
                    logger.warning('%s: %s is an empty file (skipping)',
                                   self.get_command_name(), script)
                    continue

                match = first_line_re.match(first_line)
                if match:
                    adjust = True
                    post_interp = match.group(1) or b''

            if adjust:
                logger.info("copying and adjusting %s -> %s", script,
                            self.build_dir)
                if not self.dry_run:
                    if not sysconfig.is_python_build():
                        executable = self.executable
                    else:
                        executable = os.path.join(
                            sysconfig.get_config_var("BINDIR"), "python%s%s" %
                            (sysconfig.get_config_var("VERSION"),
                             sysconfig.get_config_var("EXE")))
                    executable = fsencode(executable)
                    shebang = b"#!" + executable + post_interp + b"\n"
                    # Python parser starts to read a script using UTF-8 until
                    # it gets a #coding:xxx cookie. The shebang has to be the
                    # first line of a file, the #coding:xxx cookie cannot be
                    # written before. So the shebang has to be decodable from
                    # UTF-8.
                    try:
                        shebang.decode('utf-8')
                    except UnicodeDecodeError:
                        raise ValueError("The shebang (%r) is not decodable "
                                         "from utf-8" % shebang)
                    # If the script is encoded to a custom encoding (use a
                    # #coding:xxx cookie), the shebang has to be decodable from
                    # the script encoding too.
                    try:
                        shebang.decode(encoding)
                    except UnicodeDecodeError:
                        raise ValueError("The shebang (%r) is not decodable "
                                         "from the script encoding (%s)" %
                                         (shebang, encoding))
                    with open(outfile, "wb") as outf:
                        outf.write(shebang)
                        outf.writelines(f.readlines())
                if f:
                    f.close()
            else:
                if f:
                    f.close()
                self.copy_file(script, outfile)

        if os.name == 'posix':
            for file in outfiles:
                if self.dry_run:
                    logger.info("changing mode of %s", file)
                else:
                    oldmode = os.stat(file).st_mode & 0o7777
                    newmode = (oldmode | 0o555) & 0o7777
                    if newmode != oldmode:
                        logger.info("changing mode of %s from %o to %o", file,
                                    oldmode, newmode)
                        os.chmod(file, newmode)
        return outfiles