Exemplo n.º 1
0
 def test_user_similar(self):
     # Issue 8759 : make sure the posix scheme for the users
     # is similar to the global posix_prefix one
     base = get_config_var('base')
     user = get_config_var('userbase')
     for name in ('stdlib', 'platstdlib', 'purelib', 'platlib'):
         global_path = get_path(name, 'posix_prefix')
         user_path = get_path(name, 'posix_user')
         self.assertEqual(user_path, global_path.replace(base, user))
Exemplo n.º 2
0
    def test_user_site(self):
        # site.USER_SITE was introduced in 2.6
        if sys.version < '2.6':
            return

        # preparing the environment for the test
        self.old_user_base = get_config_var('userbase')
        self.old_user_site = get_path('purelib', '%s_user' % os.name)
        self.tmpdir = self.mkdtemp()
        self.user_base = os.path.join(self.tmpdir, 'B')
        self.user_site = os.path.join(self.tmpdir, 'S')
        _CONFIG_VARS['userbase'] = self.user_base
        scheme = '%s_user' % os.name
        _SCHEMES.set(scheme, 'purelib', self.user_site)
        def _expanduser(path):
            if path[0] == '~':
                path = os.path.normpath(self.tmpdir) + path[1:]
            return path
        self.old_expand = os.path.expanduser
        os.path.expanduser = _expanduser

        try:
            # this is the actual test
            self._test_user_site()
        finally:
            _CONFIG_VARS['userbase'] = self.old_user_base
            _SCHEMES.set(scheme, 'purelib', self.old_user_site)
            os.path.expanduser = self.old_expand
Exemplo n.º 3
0
 def test_user_similar(self):
     # Issue #8759: make sure the posix scheme for the users
     # is similar to the global posix_prefix one
     base = get_config_var('base')
     user = get_config_var('userbase')
     # the global scheme mirrors the distinction between prefix and
     # exec-prefix but not the user scheme, so we have to adapt the paths
     # before comparing (issue #9100)
     adapt = sys.prefix != sys.exec_prefix
     for name in ('stdlib', 'platstdlib', 'purelib', 'platlib'):
         global_path = get_path(name, 'posix_prefix')
         if adapt:
             global_path = global_path.replace(sys.exec_prefix, sys.prefix)
             base = base.replace(sys.exec_prefix, sys.prefix)
         user_path = get_path(name, 'posix_user')
         self.assertEqual(user_path, global_path.replace(base, user, 1))
Exemplo n.º 4
0
    def runtime_library_dir_option(self, dir):
        # XXX Hackish, at the very least.  See Python bug #445902:
        # http://sourceforge.net/tracker/index.php
        #   ?func=detail&aid=445902&group_id=5470&atid=105470
        # Linkers on different platforms need different options to
        # specify that directories need to be added to the list of
        # directories searched for dependencies when a dynamic library
        # is sought.  GCC on GNU systems (Linux, FreeBSD, ...) has to
        # be told to pass the -R option through to the linker, whereas
        # other compilers and gcc on other systems just know this.
        # Other compilers may need something slightly different.  At
        # this time, there's no way to determine this information from
        # the configuration data stored in the Python installation, so
        # we use this hack.

        compiler = os.path.basename(sysconfig.get_config_var("CC"))
        if sys.platform[:6] == "darwin":
            # MacOSX's linker doesn't understand the -R flag at all
            return "-L" + dir
        elif sys.platform[:5] == "hp-ux":
            if self._is_gcc(compiler):
                return ["-Wl,+s", "-L" + dir]
            return ["+s", "-L" + dir]
        elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
            return ["-rpath", dir]
        elif self._is_gcc(compiler):
            # gcc on non-GNU systems does not need -Wl, but can
            # use it anyway.  Since distutils has always passed in
            # -Wl whenever gcc was used in the past it is probably
            # safest to keep doing so.
            if sysconfig.get_config_var("GNULD") == "yes":
                # GNU ld needs an extra option to get a RUNPATH
                # instead of just an RPATH.
                return "-Wl,--enable-new-dtags,-R" + dir
            else:
                return "-Wl,-R" + dir
        elif sys.platform[:3] == "aix":
            return "-blibpath:" + dir
        else:
            # No idea how --enable-new-dtags would be passed on to
            # ld if this system was using GNU ld.  Don't know if a
            # system like this even exists.
            return "-R" + dir
    def test_user_site(self):
        # test install with --user
        # preparing the environment for the test
        self.old_user_base = get_config_var('userbase')
        self.old_user_site = get_path('purelib', '%s_user' % os.name)
        self.tmpdir = self.mkdtemp()
        self.user_base = os.path.join(self.tmpdir, 'B')
        self.user_site = os.path.join(self.tmpdir, 'S')
        _CONFIG_VARS['userbase'] = self.user_base
        scheme = '%s_user' % os.name
        _SCHEMES.set(scheme, 'purelib', self.user_site)

        def _expanduser(path):
            if path[0] == '~':
                path = os.path.normpath(self.tmpdir) + path[1:]
            return path

        self.old_expand = os.path.expanduser
        os.path.expanduser = _expanduser

        def cleanup():
            _CONFIG_VARS['userbase'] = self.old_user_base
            _SCHEMES.set(scheme, 'purelib', self.old_user_site)
            os.path.expanduser = self.old_expand

        self.addCleanup(cleanup)

        schemes = get_scheme_names()
        for key in ('nt_user', 'posix_user', 'os2_home'):
            self.assertIn(key, schemes)

        dist = Distribution({'name': 'xx'})
        cmd = install_dist(dist)

        # making sure the user option is there
        options = [name for name, short, lable in
                   cmd.user_options]
        self.assertIn('user', options)

        # setting a value
        cmd.user = True

        # user base and site shouldn't be created yet
        self.assertFalse(os.path.exists(self.user_base))
        self.assertFalse(os.path.exists(self.user_site))

        # let's run finalize
        cmd.ensure_finalized()

        # now they should
        self.assertTrue(os.path.exists(self.user_base))
        self.assertTrue(os.path.exists(self.user_site))

        self.assertIn('userbase', cmd.config_vars)
        self.assertIn('usersite', cmd.config_vars)
Exemplo n.º 6
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.º 7
0
 def test_deployment_target_higher_ok(self):
     # Issue 9516: Test that an extension module can be compiled with a
     # deployment target higher than that of the interpreter: the ext
     # module may depend on some newer OS feature.
     deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
     if deptarget:
         # increment the minor version number (i.e. 10.6 -> 10.7)
         deptarget = [int(x) for x in deptarget.split('.')]
         deptarget[-1] += 1
         deptarget = '.'.join(str(i) for i in deptarget)
         self._try_compile_deployment_target('<', deptarget)
Exemplo n.º 8
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.º 9
0
    def _try_compile_deployment_target(self, operator, target):
        orig_environ = os.environ
        os.environ = orig_environ.copy()
        self.addCleanup(setattr, os, 'environ', orig_environ)

        if target is None:
            if os.environ.get('MACOSX_DEPLOYMENT_TARGET'):
                del os.environ['MACOSX_DEPLOYMENT_TARGET']
        else:
            os.environ['MACOSX_DEPLOYMENT_TARGET'] = target

        deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c')

        fp = open(deptarget_c, 'w')
        try:
            fp.write(textwrap.dedent('''\
                #include <AvailabilityMacros.h>

                int dummy;

                #if TARGET %s MAC_OS_X_VERSION_MIN_REQUIRED
                #else
                #error "Unexpected target"
                #endif

            ''' % operator))
        finally:
            fp.close()

        # get the deployment target that the interpreter was built with
        target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
        target = tuple(map(int, target.split('.')))
        target = '%02d%01d0' % target

        deptarget_ext = Extension(
            'deptarget',
            [deptarget_c],
            extra_compile_args=['-DTARGET=%s' % (target,)],
        )
        dist = Distribution({
            'name': 'deptarget',
            'ext_modules': [deptarget_ext],
        })
        dist.package_dir = self.tmp_dir
        cmd = build_ext(dist)
        cmd.build_lib = self.tmp_dir
        cmd.build_temp = self.tmp_dir

        try:
            cmd.ensure_finalized()
            cmd.run()
        except CompileError:
            self.fail("Wrong deployment target during compilation")
Exemplo n.º 10
0
 def get_ext_filename(self, ext_name):
     r"""Convert the name of an extension (eg. "foo.bar") into the name
     of the file from which it will be loaded (eg. "foo/bar.so", or
     "foo\bar.pyd").
     """
     ext_path = ext_name.split('.')
     # OS/2 has an 8 character module (extension) limit :-(
     if os.name == "os2":
         ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
     # extensions in debug_mode are named 'module_d.pyd' under windows
     so_ext = sysconfig.get_config_var('SO')
     if os.name == 'nt' and self.debug:
         return os.path.join(*ext_path) + '_d' + so_ext
     return os.path.join(*ext_path) + so_ext
Exemplo n.º 11
0
    def test_solaris_enable_shared(self):
        dist = Distribution({'name': 'xx'})
        cmd = build_ext(dist)
        old = sys.platform

        sys.platform = 'sunos'  # fooling finalize_options

        old_var = sysconfig.get_config_var('Py_ENABLE_SHARED')
        sysconfig._CONFIG_VARS['Py_ENABLE_SHARED'] = 1
        try:
            cmd.ensure_finalized()
        finally:
            sys.platform = old
            if old_var is None:
                del sysconfig._CONFIG_VARS['Py_ENABLE_SHARED']
            else:
                sysconfig._CONFIG_VARS['Py_ENABLE_SHARED'] = old_var

        # make sure we get some library dirs under solaris
        self.assertGreater(len(cmd.library_dirs), 0)
Exemplo n.º 12
0
    def test_ldshared_value(self):
        ldflags = sysconfig.get_config_var('LDFLAGS')
        ldshared = sysconfig.get_config_var('LDSHARED')

        self.assertIn(ldflags, ldshared)
Exemplo n.º 13
0
    def test_get_outputs(self):
        tmp_dir = self.mkdtemp()
        c_file = os.path.join(tmp_dir, 'foo.c')
        self.write_file(c_file, 'void PyInit_foo(void) {}\n')
        ext = Extension('foo', [c_file], optional=False)
        dist = Distribution({'name': 'xx',
                             'ext_modules': [ext]})
        cmd = build_ext(dist)
        support.fixup_build_ext(cmd)
        cmd.ensure_finalized()
        self.assertEqual(len(cmd.get_outputs()), 1)

        cmd.build_lib = os.path.join(self.tmp_dir, 'build')
        cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')

        # issue #5977 : distutils build_ext.get_outputs
        # returns wrong result with --inplace
        other_tmp_dir = os.path.realpath(self.mkdtemp())
        old_wd = os.getcwd()
        os.chdir(other_tmp_dir)
        try:
            cmd.inplace = True
            cmd.run()
            so_file = cmd.get_outputs()[0]
        finally:
            os.chdir(old_wd)
        self.assertTrue(os.path.exists(so_file))
        so_ext = sysconfig.get_config_var('SO')
        self.assertTrue(so_file.endswith(so_ext))
        so_dir = os.path.dirname(so_file)
        self.assertEqual(so_dir, other_tmp_dir)

        cmd.inplace = False
        cmd.run()
        so_file = cmd.get_outputs()[0]
        self.assertTrue(os.path.exists(so_file))
        self.assertTrue(so_file.endswith(so_ext))
        so_dir = os.path.dirname(so_file)
        self.assertEqual(so_dir, cmd.build_lib)

        # inplace = False, cmd.package = 'bar'
        build_py = cmd.get_finalized_command('build_py')
        build_py.package_dir = 'bar'
        path = cmd.get_ext_fullpath('foo')
        # checking that the last directory is the build_dir
        path = os.path.split(path)[0]
        self.assertEqual(path, cmd.build_lib)

        # inplace = True, cmd.package = 'bar'
        cmd.inplace = True
        other_tmp_dir = os.path.realpath(self.mkdtemp())
        old_wd = os.getcwd()
        os.chdir(other_tmp_dir)
        try:
            path = cmd.get_ext_fullpath('foo')
        finally:
            os.chdir(old_wd)
        # checking that the last directory is bar
        path = os.path.split(path)[0]
        lastdir = os.path.split(path)[-1]
        self.assertEqual(lastdir, 'bar')
Exemplo n.º 14
0
    def initialize_options(self):
        # High-level options: these select both an installation base
        # and scheme.
        self.prefix = None
        self.exec_prefix = None
        self.home = None
        if HAS_USER_SITE:
            self.user = False

        # These select only the installation base; it's up to the user to
        # specify the installation scheme (currently, that means supplying
        # the --install-{platlib,purelib,scripts,data} options).
        self.install_base = None
        self.install_platbase = None
        self.root = None

        # These options are the actual installation directories; if not
        # supplied by the user, they are filled in using the installation
        # scheme implied by prefix/exec-prefix/home and the contents of
        # that installation scheme.
        self.install_purelib = None     # for pure module distributions
        self.install_platlib = None     # non-pure (dists w/ extensions)
        self.install_headers = None     # for C/C++ headers
        self.install_lib = None         # set to either purelib or platlib
        self.install_scripts = None
        self.install_data = None
        if HAS_USER_SITE:
            self.install_userbase = get_config_var('userbase')
            self.install_usersite = get_path('purelib', '%s_user' % os.name)

        self.compile = None
        self.optimize = None

        # These two are for putting non-packagized distributions into their
        # own directory and creating a .pth file if it makes sense.
        # 'extra_path' comes from the setup file; 'install_path_file' can
        # be turned off if it makes no sense to install a .pth file.  (But
        # better to install it uselessly than to guess wrong and not
        # install it when it's necessary and would be used!)  Currently,
        # 'install_path_file' is always true unless some outsider meddles
        # with it.
        self.extra_path = None
        self.install_path_file = True

        # 'force' forces installation, even if target files are not
        # out-of-date.  'skip_build' skips running the "build" command,
        # handy if you know it's not necessary.  'warn_dir' (which is *not*
        # a user option, it's just there so the bdist_* commands can turn
        # it off) determines whether we warn about installing to a
        # directory not in sys.path.
        self.force = False
        self.skip_build = False
        self.warn_dir = True

        # These are only here as a conduit from the 'build' command to the
        # 'install_*' commands that do the real work.  ('build_base' isn't
        # actually used anywhere, but it might be useful in future.)  They
        # are not user options, because if the user told the install
        # command where the build directory is, that wouldn't affect the
        # build command.
        self.build_base = None
        self.build_lib = None

        # Not defined yet because we don't know anything about
        # documentation yet.
        #self.install_man = None
        #self.install_html = None
        #self.install_info = None

        self.record = None
        self.resources = None

        # .dist-info related options
        self.no_distinfo = None
        self.installer = None
        self.requested = None
        self.no_record = None
Exemplo n.º 15
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.º 16
0
    def get_libraries(self, ext):
        """Return the list of libraries to link against when building a
        shared extension.  On most platforms, this is just 'ext.libraries';
        on Windows and OS/2, we add the Python library (eg. python20.dll).
        """
        # The python library is always needed on Windows.  For MSVC, this
        # is redundant, since the library is mentioned in a pragma in
        # pyconfig.h that MSVC groks.  The other Windows compilers all seem
        # to need it mentioned explicitly, though, so that's what we do.
        # Append '_d' to the python import library on debug builds.
        if sys.platform == "win32":
            from distutils2.compiler.msvccompiler import MSVCCompiler
            if not isinstance(self.compiler_obj, MSVCCompiler):
                template = "python%d%d"
                if self.debug:
                    template = template + '_d'
                pythonlib = template % sys.version_info[:2]
                # don't extend ext.libraries, it may be shared with other
                # extensions, it is a reference to the original list
                return ext.libraries + [pythonlib]
            else:
                return ext.libraries
        elif sys.platform == "os2emx":
            # EMX/GCC requires the python library explicitly, and I
            # believe VACPP does as well (though not confirmed) - AIM Apr01
            template = "python%d%d"
            # debug versions of the main DLL aren't supported, at least
            # not at this time - AIM Apr01
            #if self.debug:
            #    template = template + '_d'
            pythonlib = template % sys.version_info[:2]
            # don't extend ext.libraries, it may be shared with other
            # extensions, it is a reference to the original list
            return ext.libraries + [pythonlib]
        elif sys.platform[:6] == "cygwin":
            template = "python%d.%d"
            pythonlib = template % sys.version_info[:2]
            # don't extend ext.libraries, it may be shared with other
            # extensions, it is a reference to the original list
            return ext.libraries + [pythonlib]
        elif sys.platform[:6] == "atheos":
            template = "python%d.%d"
            pythonlib = template % sys.version_info[:2]
            # Get SHLIBS from Makefile
            extra = []
            for lib in sysconfig.get_config_var('SHLIBS').split():
                if lib.startswith('-l'):
                    extra.append(lib[2:])
                else:
                    extra.append(lib)
            # don't extend ext.libraries, it may be shared with other
            # extensions, it is a reference to the original list
            return ext.libraries + [pythonlib, "m"] + extra

        elif sys.platform == 'darwin':
            # Don't use the default code below
            return ext.libraries

        else:
            if sysconfig.get_config_var('Py_ENABLE_SHARED'):
                template = 'python%d.%d'
                pythonlib = template % sys.version_info[:2]
                return ext.libraries + [pythonlib]
            else:
                return ext.libraries
Exemplo n.º 17
0
    def finalize_options(self):
        self.set_undefined_options('build',
                                   'build_lib', 'build_temp', 'compiler',
                                   'debug', 'force', 'plat_name')

        if self.package is None:
            self.package = self.distribution.ext_package

        # Ensure that the list of extensions is valid, i.e. it is a list of
        # Extension objects.
        self.extensions = self.distribution.ext_modules
        if self.extensions:
            if not isinstance(self.extensions, (list, tuple)):
                type_name = (self.extensions is None and 'None'
                            or type(self.extensions).__name__)
                raise PackagingSetupError(
                    "'ext_modules' must be a sequence of Extension instances,"
                    " not %s" % (type_name,))
            for i, ext in enumerate(self.extensions):
                if isinstance(ext, Extension):
                    continue                # OK! (assume type-checking done
                                            # by Extension constructor)
                type_name = (ext is None and 'None' or type(ext).__name__)
                raise PackagingSetupError(
                    "'ext_modules' item %d must be an Extension instance,"
                    " not %s" % (i, type_name))

        # Make sure Python's include directories (for Python.h, pyconfig.h,
        # etc.) are in the include search path.
        py_include = sysconfig.get_path('include')
        plat_py_include = sysconfig.get_path('platinclude')
        if self.include_dirs is None:
            self.include_dirs = self.distribution.include_dirs or []
        if isinstance(self.include_dirs, basestring):
            self.include_dirs = self.include_dirs.split(os.pathsep)

        # Put the Python "system" include dir at the end, so that
        # any local include dirs take precedence.
        self.include_dirs.append(py_include)
        if plat_py_include != py_include:
            self.include_dirs.append(plat_py_include)

        self.ensure_string_list('libraries')

        # Life is easier if we're not forever checking for None, so
        # simplify these options to empty lists if unset
        if self.libraries is None:
            self.libraries = []
        if self.library_dirs is None:
            self.library_dirs = []
        elif isinstance(self.library_dirs, basestring):
            self.library_dirs = self.library_dirs.split(os.pathsep)

        if self.rpath is None:
            self.rpath = []
        elif isinstance(self.rpath, basestring):
            self.rpath = self.rpath.split(os.pathsep)

        # for extensions under windows use different directories
        # for Release and Debug builds.
        # also Python's library directory must be appended to library_dirs
        if os.name == 'nt':
            # the 'libs' directory is for binary installs - we assume that
            # must be the *native* platform.  But we don't really support
            # cross-compiling via a binary install anyway, so we let it go.
            self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
            if self.debug:
                self.build_temp = os.path.join(self.build_temp, "Debug")
            else:
                self.build_temp = os.path.join(self.build_temp, "Release")

            # Append the source distribution include and library directories,
            # this allows distutils on windows to work in the source tree
            self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
            if MSVC_VERSION == 9:
                # Use the .lib files for the correct architecture
                if self.plat_name == 'win32':
                    suffix = ''
                else:
                    # win-amd64 or win-ia64
                    suffix = self.plat_name[4:]
                new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
                if suffix:
                    new_lib = os.path.join(new_lib, suffix)
                self.library_dirs.append(new_lib)

            elif MSVC_VERSION == 8:
                self.library_dirs.append(os.path.join(sys.exec_prefix,
                                         'PC', 'VS8.0'))
            elif MSVC_VERSION == 7:
                self.library_dirs.append(os.path.join(sys.exec_prefix,
                                         'PC', 'VS7.1'))
            else:
                self.library_dirs.append(os.path.join(sys.exec_prefix,
                                         'PC', 'VC6'))

        # OS/2 (EMX) doesn't support Debug vs Release builds, but has the
        # import libraries in its "Config" subdirectory
        if os.name == 'os2':
            self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config'))

        # for extensions under Cygwin and AtheOS Python's library directory must be
        # appended to library_dirs
        if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos':
            if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
                # building third party extensions
                self.library_dirs.append(os.path.join(sys.prefix, "lib",
                                  "python" + sysconfig.get_python_version(),
                                                      "config"))
            else:
                # building python standard extensions
                self.library_dirs.append(os.curdir)

        # for extensions under Linux or Solaris with a shared Python library,
        # Python's library directory must be appended to library_dirs
        sysconfig.get_config_var('Py_ENABLE_SHARED')
        if ((sys.platform.startswith('linux') or sys.platform.startswith('gnu')
             or sys.platform.startswith('sunos'))
            and sysconfig.get_config_var('Py_ENABLE_SHARED')):
            if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
                # building third party extensions
                self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
            else:
                # building python standard extensions
                self.library_dirs.append(os.curdir)

        # The argument parsing will result in self.define being a string, but
        # it has to be a list of 2-tuples.  All the preprocessor symbols
        # specified by the 'define' option will be set to '1'.  Multiple
        # symbols can be separated with commas.

        if self.define:
            defines = self.define.split(',')
            self.define = [(symbol, '1') for symbol in defines]

        # The option for macros to undefine is also a string from the
        # option parsing, but has to be a list.  Multiple symbols can also
        # be separated with commas here.
        if self.undef:
            self.undef = self.undef.split(',')

        if self.swig_opts is None:
            self.swig_opts = []
        else:
            self.swig_opts = self.swig_opts.split(' ')

        # Finally add the user include and library directories if requested
        if HAS_USER_SITE and self.user:
            user_include = os.path.join(site.USER_BASE, "include")
            user_lib = os.path.join(site.USER_BASE, "lib")
            if os.path.isdir(user_include):
                self.include_dirs.append(user_include)
            if os.path.isdir(user_lib):
                self.library_dirs.append(user_lib)
                self.rpath.append(user_lib)
    def test_record_basic(self):
        install_dir = self.mkdtemp()
        modules_dest = os.path.join(install_dir, 'lib')
        scripts_dest = os.path.join(install_dir, 'bin')
        project_dir, dist = self.create_dist(
            name='Spamlib', version='0.1',
            py_modules=['spam'], scripts=['spamd'],
            ext_modules=[Extension('_speedspam', ['_speedspam.c'])])

        # using a real install_dist command is too painful, so we use a mock
        # class that's only a holder for options to be used by install_distinfo
        # and we create placeholder files manually instead of using build_*.
        # the install_* commands will still be consulted by install_distinfo.
        os.chdir(project_dir)
        self.write_file('spam', '# Python module')
        self.write_file('spamd', '# Python script')
        extmod = '_speedspam' + sysconfig.get_config_var('SO')
        self.write_file(extmod, '')

        install = DummyInstallCmd(dist)
        install.outputs = ['spam', 'spamd', extmod]
        install.install_lib = modules_dest
        install.install_scripts = scripts_dest
        dist.command_obj['install_dist'] = install

        cmd = install_distinfo(dist)
        cmd.ensure_finalized()
        dist.command_obj['install_distinfo'] = cmd
        cmd.run()

        # checksum and size are not hard-coded for METADATA as it is
        # platform-dependent (line endings)
        metadata = os.path.join(modules_dest, 'Spamlib-0.1.dist-info',
                                'METADATA')
        fp = open(metadata, 'rb')
        try:
            content = fp.read()
        finally:
            fp.close()

        metadata_size = str(len(content))
        metadata_md5 = hashlib.md5(content).hexdigest()

        record = os.path.join(modules_dest, 'Spamlib-0.1.dist-info', 'RECORD')
        fp = codecs.open(record, encoding='utf-8')
        try:
            content = fp.read()
        finally:
            fp.close()

        found = []
        for line in content.splitlines():
            filename, checksum, size = line.split(',')
            filename = os.path.basename(filename)
            found.append((filename, checksum, size))

        expected = [
            ('spam', '6ab2f288ef2545868effe68757448b45', '15'),
            ('spamd', 'd13e6156ce78919a981e424b2fdcd974', '15'),
            (extmod, 'd41d8cd98f00b204e9800998ecf8427e', '0'),
            ('METADATA', metadata_md5, metadata_size),
            ('INSTALLER', '44e3fde05f3f537ed85831969acf396d', '9'),
            ('REQUESTED', 'd41d8cd98f00b204e9800998ecf8427e', '0'),
            ('RECORD', '', ''),
        ]
        self.assertEqual(found, expected)
Exemplo n.º 19
0
def _make_ext_name(modname):
    if os.name == 'nt' and sys.executable.endswith('_d.exe'):
        modname += '_d'
    return modname + get_config_var('SO')