Commit 07be9364 authored by Tarek Ziadé's avatar Tarek Ziadé

reverted distutils its 3.1 state. All new work is now happening in disutils2,...

reverted distutils its 3.1 state. All new work is now happening in disutils2, and distutils is now feature-frozen.
parent b97dbcf4
...@@ -14,55 +14,15 @@ from distutils.spawn import spawn ...@@ -14,55 +14,15 @@ from distutils.spawn import spawn
from distutils.dir_util import mkpath from distutils.dir_util import mkpath
from distutils import log from distutils import log
try: def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0):
from pwd import getpwnam
except ImportError:
getpwnam = None
try:
from grp import getgrnam
except ImportError:
getgrnam = None
def _get_gid(name):
"""Returns a gid, given a group name."""
if getgrnam is None or name is None:
return None
try:
result = getgrnam(name)
except KeyError:
result = None
if result is not None:
return result[2]
return None
def _get_uid(name):
"""Returns an uid, given a user name."""
if getpwnam is None or name is None:
return None
try:
result = getpwnam(name)
except KeyError:
result = None
if result is not None:
return result[2]
return None
def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
owner=None, group=None):
"""Create a (possibly compressed) tar file from all the files under """Create a (possibly compressed) tar file from all the files under
'base_dir'. 'base_dir'.
'compress' must be "gzip" (the default), "compress", "bzip2", or None. 'compress' must be "gzip" (the default), "compress", "bzip2", or None.
(compress will be deprecated in Python 3.2) Both "tar" and the compression utility named by 'compress' must be on
the default program search path, so this is probably Unix-specific.
'owner' and 'group' can be used to define an owner and a group for the
archive that is being built. If not provided, the current owner and group
will be used.
The output tar file will be named 'base_dir' + ".tar", possibly plus The output tar file will be named 'base_dir' + ".tar", possibly plus
the appropriate compression extension (".gz", ".bz2" or ".Z"). the appropriate compression extension (".gz", ".bz2" or ".Z").
Returns the output filename. Returns the output filename.
""" """
tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''} tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''}
...@@ -84,23 +44,10 @@ def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, ...@@ -84,23 +44,10 @@ def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
import tarfile # late import so Python build itself doesn't break import tarfile # late import so Python build itself doesn't break
log.info('Creating tar archive') log.info('Creating tar archive')
uid = _get_uid(owner)
gid = _get_gid(group)
def _set_uid_gid(tarinfo):
if gid is not None:
tarinfo.gid = gid
tarinfo.gname = group
if uid is not None:
tarinfo.uid = uid
tarinfo.uname = owner
return tarinfo
if not dry_run: if not dry_run:
tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
try: try:
tar.add(base_dir, filter=_set_uid_gid) tar.add(base_dir)
finally: finally:
tar.close() tar.close()
...@@ -190,7 +137,7 @@ def check_archive_formats(formats): ...@@ -190,7 +137,7 @@ def check_archive_formats(formats):
return None return None
def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
dry_run=0, owner=None, group=None): dry_run=0):
"""Create an archive file (eg. zip or tar). """Create an archive file (eg. zip or tar).
'base_name' is the name of the file to create, minus any format-specific 'base_name' is the name of the file to create, minus any format-specific
...@@ -203,9 +150,6 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, ...@@ -203,9 +150,6 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
ie. 'base_dir' will be the common prefix of all files and ie. 'base_dir' will be the common prefix of all files and
directories in the archive. 'root_dir' and 'base_dir' both default directories in the archive. 'root_dir' and 'base_dir' both default
to the current directory. Returns the name of the archive file. to the current directory. Returns the name of the archive file.
'owner' and 'group' are used when creating a tar archive. By default,
uses the current owner and group.
""" """
save_cwd = os.getcwd() save_cwd = os.getcwd()
if root_dir is not None: if root_dir is not None:
...@@ -227,11 +171,6 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, ...@@ -227,11 +171,6 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
func = format_info[0] func = format_info[0]
for arg, val in format_info[1]: for arg, val in format_info[1]:
kwargs[arg] = val kwargs[arg] = val
if format != 'zip':
kwargs['owner'] = owner
kwargs['group'] = group
try: try:
filename = func(base_name, base_dir, **kwargs) filename = func(base_name, base_dir, **kwargs)
finally: finally:
......
...@@ -13,11 +13,13 @@ for the Borland C++ compiler. ...@@ -13,11 +13,13 @@ for the Borland C++ compiler.
__revision__ = "$Id$" __revision__ = "$Id$"
import os
from distutils.errors import (DistutilsExecError, CompileError, LibError, import os
LinkError, UnknownFileError) from distutils.errors import \
from distutils.ccompiler import CCompiler, gen_preprocess_options DistutilsExecError, DistutilsPlatformError, \
CompileError, LibError, LinkError, UnknownFileError
from distutils.ccompiler import \
CCompiler, gen_preprocess_options, gen_lib_options
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.dep_util import newer from distutils.dep_util import newer
from distutils import log from distutils import log
......
...@@ -5,71 +5,15 @@ for the Distutils compiler abstraction model.""" ...@@ -5,71 +5,15 @@ for the Distutils compiler abstraction model."""
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, os, re
import os from distutils.errors import *
import re
from distutils.errors import (CompileError, LinkError, UnknownFileError,
DistutilsPlatformError, DistutilsModuleError)
from distutils.spawn import spawn from distutils.spawn import spawn
from distutils.file_util import move_file from distutils.file_util import move_file
from distutils.dir_util import mkpath from distutils.dir_util import mkpath
from distutils.dep_util import newer_group from distutils.dep_util import newer_pairwise, newer_group
from distutils.util import split_quoted, execute from distutils.util import split_quoted, execute
from distutils import log from distutils import log
_sysconfig = __import__('sysconfig')
def customize_compiler(compiler):
"""Do any platform-specific customization of a CCompiler instance.
Mainly needed on Unix, so we can plug in the information that
varies across Unices and is stored in Python's Makefile.
"""
if compiler.compiler_type == "unix":
(cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
_sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
'CCSHARED', 'LDSHARED', 'SO', 'AR',
'ARFLAGS')
if 'CC' in os.environ:
cc = os.environ['CC']
if 'CXX' in os.environ:
cxx = os.environ['CXX']
if 'LDSHARED' in os.environ:
ldshared = os.environ['LDSHARED']
if 'CPP' in os.environ:
cpp = os.environ['CPP']
else:
cpp = cc + " -E" # not always
if 'LDFLAGS' in os.environ:
ldshared = ldshared + ' ' + os.environ['LDFLAGS']
if 'CFLAGS' in os.environ:
cflags = opt + ' ' + os.environ['CFLAGS']
ldshared = ldshared + ' ' + os.environ['CFLAGS']
if 'CPPFLAGS' in os.environ:
cpp = cpp + ' ' + os.environ['CPPFLAGS']
cflags = cflags + ' ' + os.environ['CPPFLAGS']
ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
if 'AR' in os.environ:
ar = os.environ['AR']
if 'ARFLAGS' in os.environ:
archiver = ar + ' ' + os.environ['ARFLAGS']
else:
archiver = ar + ' ' + ar_flags
cc_cmd = cc + ' ' + cflags
compiler.set_executables(
preprocessor=cpp,
compiler=cc_cmd,
compiler_so=cc_cmd + ' ' + ccshared,
compiler_cxx=cxx,
linker_so=ldshared,
linker_exe=cc,
archiver=archiver)
compiler.shared_lib_extension = so_ext
class CCompiler: class CCompiler:
"""Abstract base class to define the interface that must be implemented """Abstract base class to define the interface that must be implemented
by real compiler classes. Also has some utility methods used by by real compiler classes. Also has some utility methods used by
...@@ -449,6 +393,22 @@ class CCompiler: ...@@ -449,6 +393,22 @@ class CCompiler:
return output_dir, macros, include_dirs return output_dir, macros, include_dirs
def _prep_compile(self, sources, output_dir, depends=None):
"""Decide which souce files must be recompiled.
Determine the list of object files corresponding to 'sources',
and figure out which ones really need to be recompiled.
Return a list of all object files and a dictionary telling
which source files can be skipped.
"""
# Get the list of expected output (object) files
objects = self.object_filenames(sources, output_dir=output_dir)
assert len(objects) == len(sources)
# Return an empty dict for the "which source files can be skipped"
# return value to preserve API compatibility.
return objects, {}
def _fix_object_args(self, objects, output_dir): def _fix_object_args(self, objects, output_dir):
"""Typecheck and fix up some arguments supplied to various methods. """Typecheck and fix up some arguments supplied to various methods.
Specifically: ensure that 'objects' is a list; if output_dir is Specifically: ensure that 'objects' is a list; if output_dir is
...@@ -650,15 +610,26 @@ class CCompiler: ...@@ -650,15 +610,26 @@ class CCompiler:
""" """
pass pass
# values for target_desc parameter in link() # values for target_desc parameter in link()
SHARED_OBJECT = "shared_object" SHARED_OBJECT = "shared_object"
SHARED_LIBRARY = "shared_library" SHARED_LIBRARY = "shared_library"
EXECUTABLE = "executable" EXECUTABLE = "executable"
def link(self, target_desc, objects, output_filename, output_dir=None, def link(self,
libraries=None, library_dirs=None, runtime_library_dirs=None, target_desc,
export_symbols=None, debug=0, extra_preargs=None, objects,
extra_postargs=None, build_temp=None, target_lang=None): output_filename,
output_dir=None,
libraries=None,
library_dirs=None,
runtime_library_dirs=None,
export_symbols=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
build_temp=None,
target_lang=None):
"""Link a bunch of stuff together to create an executable or """Link a bunch of stuff together to create an executable or
shared library file. shared library file.
...@@ -707,11 +678,19 @@ class CCompiler: ...@@ -707,11 +678,19 @@ class CCompiler:
# Old 'link_*()' methods, rewritten to use the new 'link()' method. # Old 'link_*()' methods, rewritten to use the new 'link()' method.
def link_shared_lib(self, objects, output_libname, output_dir=None, def link_shared_lib(self,
libraries=None, library_dirs=None, objects,
runtime_library_dirs=None, export_symbols=None, output_libname,
debug=0, extra_preargs=None, extra_postargs=None, output_dir=None,
build_temp=None, target_lang=None): libraries=None,
library_dirs=None,
runtime_library_dirs=None,
export_symbols=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
build_temp=None,
target_lang=None):
self.link(CCompiler.SHARED_LIBRARY, objects, self.link(CCompiler.SHARED_LIBRARY, objects,
self.library_filename(output_libname, lib_type='shared'), self.library_filename(output_libname, lib_type='shared'),
output_dir, output_dir,
...@@ -720,11 +699,19 @@ class CCompiler: ...@@ -720,11 +699,19 @@ class CCompiler:
extra_preargs, extra_postargs, build_temp, target_lang) extra_preargs, extra_postargs, build_temp, target_lang)
def link_shared_object(self, objects, output_filename, output_dir=None, def link_shared_object(self,
libraries=None, library_dirs=None, objects,
runtime_library_dirs=None, export_symbols=None, output_filename,
debug=0, extra_preargs=None, extra_postargs=None, output_dir=None,
build_temp=None, target_lang=None): libraries=None,
library_dirs=None,
runtime_library_dirs=None,
export_symbols=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
build_temp=None,
target_lang=None):
self.link(CCompiler.SHARED_OBJECT, objects, self.link(CCompiler.SHARED_OBJECT, objects,
output_filename, output_dir, output_filename, output_dir,
libraries, library_dirs, runtime_library_dirs, libraries, library_dirs, runtime_library_dirs,
...@@ -732,10 +719,17 @@ class CCompiler: ...@@ -732,10 +719,17 @@ class CCompiler:
extra_preargs, extra_postargs, build_temp, target_lang) extra_preargs, extra_postargs, build_temp, target_lang)
def link_executable(self, objects, output_progname, output_dir=None, def link_executable(self,
libraries=None, library_dirs=None, objects,
runtime_library_dirs=None, debug=0, extra_preargs=None, output_progname,
extra_postargs=None, target_lang=None): output_dir=None,
libraries=None,
library_dirs=None,
runtime_library_dirs=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
target_lang=None):
self.link(CCompiler.EXECUTABLE, objects, self.link(CCompiler.EXECUTABLE, objects,
self.executable_filename(output_progname), output_dir, self.executable_filename(output_progname), output_dir,
libraries, library_dirs, runtime_library_dirs, None, libraries, library_dirs, runtime_library_dirs, None,
...@@ -917,7 +911,7 @@ main (int argc, char **argv) { ...@@ -917,7 +911,7 @@ main (int argc, char **argv) {
def move_file(self, src, dst): def move_file(self, src, dst):
return move_file(src, dst, dry_run=self.dry_run) return move_file(src, dst, dry_run=self.dry_run)
def mkpath(self, name, mode=0o777): def mkpath (self, name, mode=0o777):
mkpath(name, mode, dry_run=self.dry_run) mkpath(name, mode, dry_run=self.dry_run)
...@@ -1085,14 +1079,12 @@ def gen_preprocess_options(macros, include_dirs): ...@@ -1085,14 +1079,12 @@ def gen_preprocess_options(macros, include_dirs):
return pp_opts return pp_opts
def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries): def gen_lib_options (compiler, library_dirs, runtime_library_dirs, libraries):
"""Generate linker options for searching library directories and """Generate linker options for searching library directories and
linking with specific libraries. linking with specific libraries. 'libraries' and 'library_dirs' are,
respectively, lists of library names (not filenames!) and search
'libraries' and 'library_dirs' are, respectively, lists of library names directories. Returns a list of command-line options suitable for use
(not filenames!) and search directories. Returns a list of command-line with some compiler (depending on the two format strings passed in).
options suitable for use with some compiler (depending on the two format
strings passed in).
""" """
lib_opts = [] lib_opts = []
...@@ -1102,7 +1094,7 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries): ...@@ -1102,7 +1094,7 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
for dir in runtime_library_dirs: for dir in runtime_library_dirs:
opt = compiler.runtime_library_dir_option(dir) opt = compiler.runtime_library_dir_option(dir)
if isinstance(opt, list): if isinstance(opt, list):
lib_opts.extend(opt) lib_opts = lib_opts + opt
else: else:
lib_opts.append(opt) lib_opts.append(opt)
...@@ -1113,14 +1105,14 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries): ...@@ -1113,14 +1105,14 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
# pretty nasty way to arrange your C code. # pretty nasty way to arrange your C code.
for lib in libraries: for lib in libraries:
lib_dir, lib_name = os.path.split(lib) (lib_dir, lib_name) = os.path.split(lib)
if lib_dir != '': if lib_dir:
lib_file = compiler.find_library_file([lib_dir], lib_name) lib_file = compiler.find_library_file([lib_dir], lib_name)
if lib_file is not None: if lib_file:
lib_opts.append(lib_file) lib_opts.append(lib_file)
else: else:
compiler.warn("no library file corresponding to " compiler.warn("no library file corresponding to "
"'%s' found (skipping)" % lib) "'%s' found (skipping)" % lib)
else: else:
lib_opts.append(compiler.library_option(lib)) lib_opts.append(compiler.library_option (lib))
return lib_opts return lib_opts
...@@ -367,11 +367,9 @@ class Command: ...@@ -367,11 +367,9 @@ class Command:
from distutils.spawn import spawn from distutils.spawn import spawn
spawn(cmd, search_path, dry_run=self.dry_run) spawn(cmd, search_path, dry_run=self.dry_run)
def make_archive(self, base_name, format, root_dir=None, base_dir=None, def make_archive(self, base_name, format, root_dir=None, base_dir=None):
owner=None, group=None): return archive_util.make_archive(base_name, format, root_dir, base_dir,
return archive_util.make_archive(base_name, format, root_dir, dry_run=self.dry_run)
base_dir, dry_run=self.dry_run,
owner=owner, group=group)
def make_file(self, infiles, outfile, func, args, def make_file(self, infiles, outfile, func, args,
exec_msg=None, skip_msg=None, level=1): exec_msg=None, skip_msg=None, level=1):
......
...@@ -6,10 +6,9 @@ distribution).""" ...@@ -6,10 +6,9 @@ distribution)."""
__revision__ = "$Id$" __revision__ = "$Id$"
import os import os
from distutils.util import get_platform
from distutils.core import Command from distutils.core import Command
from distutils.errors import DistutilsPlatformError, DistutilsOptionError from distutils.errors import *
from distutils.util import get_platform
def show_formats(): def show_formats():
...@@ -40,12 +39,6 @@ class bdist(Command): ...@@ -40,12 +39,6 @@ class bdist(Command):
"[default: dist]"), "[default: dist]"),
('skip-build', None, ('skip-build', None,
"skip rebuilding everything (for testing/debugging)"), "skip rebuilding everything (for testing/debugging)"),
('owner=', 'u',
"Owner name used when creating a tar file"
" [default: current user]"),
('group=', 'g',
"Group name used when creating a tar file"
" [default: current group]"),
] ]
boolean_options = ['skip-build'] boolean_options = ['skip-build']
...@@ -87,8 +80,6 @@ class bdist(Command): ...@@ -87,8 +80,6 @@ class bdist(Command):
self.formats = None self.formats = None
self.dist_dir = None self.dist_dir = None
self.skip_build = 0 self.skip_build = 0
self.group = None
self.owner = None
def finalize_options(self): def finalize_options(self):
# have to finalize 'plat_name' before 'bdist_base' # have to finalize 'plat_name' before 'bdist_base'
...@@ -134,11 +125,6 @@ class bdist(Command): ...@@ -134,11 +125,6 @@ class bdist(Command):
if cmd_name not in self.no_format_option: if cmd_name not in self.no_format_option:
sub_cmd.format = self.formats[i] sub_cmd.format = self.formats[i]
# passing the owner and group names for tar archiving
if cmd_name == 'bdist_dumb':
sub_cmd.owner = self.owner
sub_cmd.group = self.group
# If we're going to need to run this command again, tell it to # If we're going to need to run this command again, tell it to
# keep its temporary files around so subsequent runs go faster. # keep its temporary files around so subsequent runs go faster.
if cmd_name in commands[i+1:]: if cmd_name in commands[i+1:]:
......
...@@ -7,18 +7,16 @@ $exec_prefix).""" ...@@ -7,18 +7,16 @@ $exec_prefix)."""
__revision__ = "$Id$" __revision__ = "$Id$"
import os import os
from sysconfig import get_python_version
from distutils.util import get_platform
from distutils.core import Command from distutils.core import Command
from distutils.util import get_platform
from distutils.dir_util import remove_tree, ensure_relative from distutils.dir_util import remove_tree, ensure_relative
from distutils.errors import DistutilsPlatformError from distutils.errors import *
from distutils.sysconfig import get_python_version
from distutils import log from distutils import log
class bdist_dumb(Command): class bdist_dumb(Command):
description = 'create a "dumb" built distribution' description = "create a \"dumb\" built distribution"
user_options = [('bdist-dir=', 'd', user_options = [('bdist-dir=', 'd',
"temporary directory for creating the distribution"), "temporary directory for creating the distribution"),
...@@ -37,12 +35,6 @@ class bdist_dumb(Command): ...@@ -37,12 +35,6 @@ class bdist_dumb(Command):
('relative', None, ('relative', None,
"build the archive using relative paths" "build the archive using relative paths"
"(default: false)"), "(default: false)"),
('owner=', 'u',
"Owner name used when creating a tar file"
" [default: current user]"),
('group=', 'g',
"Group name used when creating a tar file"
" [default: current group]"),
] ]
boolean_options = ['keep-temp', 'skip-build', 'relative'] boolean_options = ['keep-temp', 'skip-build', 'relative']
...@@ -59,8 +51,6 @@ class bdist_dumb(Command): ...@@ -59,8 +51,6 @@ class bdist_dumb(Command):
self.dist_dir = None self.dist_dir = None
self.skip_build = 0 self.skip_build = 0
self.relative = 0 self.relative = 0
self.owner = None
self.group = None
def finalize_options(self): def finalize_options(self):
if self.bdist_dir is None: if self.bdist_dir is None:
...@@ -118,8 +108,7 @@ class bdist_dumb(Command): ...@@ -118,8 +108,7 @@ class bdist_dumb(Command):
# Make the archive # Make the archive
filename = self.make_archive(pseudoinstall_root, filename = self.make_archive(pseudoinstall_root,
self.format, root_dir=archive_root, self.format, root_dir=archive_root)
owner=self.owner, group=self.group)
if self.distribution.has_ext_modules(): if self.distribution.has_ext_modules():
pyversion = get_python_version() pyversion = get_python_version()
else: else:
......
...@@ -6,15 +6,15 @@ ...@@ -6,15 +6,15 @@
""" """
Implements the bdist_msi command. Implements the bdist_msi command.
""" """
import sys, os
from sysconfig import get_python_version, get_platform
import sys, os
from distutils.core import Command from distutils.core import Command
from distutils.dir_util import remove_tree from distutils.dir_util import remove_tree
from distutils.sysconfig import get_python_version
from distutils.version import StrictVersion from distutils.version import StrictVersion
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
from distutils.util import get_platform
from distutils import log from distutils import log
import msilib import msilib
from msilib import schema, sequence, text from msilib import schema, sequence, text
from msilib import Directory, Feature, Dialog, add_data from msilib import Directory, Feature, Dialog, add_data
...@@ -28,6 +28,7 @@ class PyDialog(Dialog): ...@@ -28,6 +28,7 @@ class PyDialog(Dialog):
default, cancel, bitmap=true)""" default, cancel, bitmap=true)"""
Dialog.__init__(self, *args) Dialog.__init__(self, *args)
ruler = self.h - 36 ruler = self.h - 36
bmwidth = 152*ruler/328
#if kw.get("bitmap", True): #if kw.get("bitmap", True):
# self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin") # self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin")
self.line("BottomLine", 0, ruler, self.w, 0) self.line("BottomLine", 0, ruler, self.w, 0)
...@@ -418,6 +419,7 @@ class bdist_msi(Command): ...@@ -418,6 +419,7 @@ class bdist_msi(Command):
# see "Dialog Style Bits" # see "Dialog Style Bits"
modal = 3 # visible | modal modal = 3 # visible | modal
modeless = 1 # visible modeless = 1 # visible
track_disk_space = 32
# UI customization properties # UI customization properties
add_data(db, "Property", add_data(db, "Property",
......
...@@ -5,14 +5,13 @@ distributions).""" ...@@ -5,14 +5,13 @@ distributions)."""
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, os
import os
from distutils.core import Command from distutils.core import Command
from distutils.debug import DEBUG from distutils.debug import DEBUG
from distutils.util import get_platform
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.errors import (DistutilsOptionError, DistutilsPlatformError, from distutils.errors import *
DistutilsFileError, DistutilsExecError) from distutils.sysconfig import get_python_version
from distutils import log from distutils import log
class bdist_rpm(Command): class bdist_rpm(Command):
......
...@@ -5,16 +5,13 @@ exe-program.""" ...@@ -5,16 +5,13 @@ exe-program."""
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, os
import os
from sysconfig import get_python_version
from distutils.core import Command from distutils.core import Command
from distutils.dir_util import remove_tree
from distutils.errors import DistutilsOptionError, DistutilsPlatformError
from distutils import log
from distutils.util import get_platform from distutils.util import get_platform
from distutils.dir_util import create_tree, remove_tree
from distutils.errors import *
from distutils.sysconfig import get_python_version
from distutils import log
class bdist_wininst(Command): class bdist_wininst(Command):
......
...@@ -5,15 +5,16 @@ Implements the Distutils 'build' command.""" ...@@ -5,15 +5,16 @@ Implements the Distutils 'build' command."""
__revision__ = "$Id$" __revision__ = "$Id$"
import sys, os import sys, os
from distutils.util import get_platform
from distutils.core import Command from distutils.core import Command
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
from distutils.util import get_platform
def show_compilers(): def show_compilers():
from distutils.ccompiler import show_compilers from distutils.ccompiler import show_compilers
show_compilers() show_compilers()
class build(Command): class build(Command):
description = "build everything needed to install" description = "build everything needed to install"
...@@ -126,6 +127,7 @@ class build(Command): ...@@ -126,6 +127,7 @@ class build(Command):
for cmd_name in self.get_sub_commands(): for cmd_name in self.get_sub_commands():
self.run_command(cmd_name) self.run_command(cmd_name)
# -- Predicates for the sub-command list --------------------------- # -- Predicates for the sub-command list ---------------------------
def has_pure_modules(self): def has_pure_modules(self):
...@@ -140,6 +142,7 @@ class build(Command): ...@@ -140,6 +142,7 @@ class build(Command):
def has_scripts(self): def has_scripts(self):
return self.distribution.has_scripts() return self.distribution.has_scripts()
sub_commands = [('build_py', has_pure_modules), sub_commands = [('build_py', has_pure_modules),
('build_clib', has_c_libraries), ('build_clib', has_c_libraries),
('build_ext', has_ext_modules), ('build_ext', has_ext_modules),
......
...@@ -18,8 +18,8 @@ __revision__ = "$Id$" ...@@ -18,8 +18,8 @@ __revision__ = "$Id$"
import os import os
from distutils.core import Command from distutils.core import Command
from distutils.errors import DistutilsSetupError from distutils.errors import *
from distutils.ccompiler import customize_compiler from distutils.sysconfig import customize_compiler
from distutils import log from distutils import log
def show_compilers(): def show_compilers():
......
...@@ -7,14 +7,12 @@ extensions ASAP).""" ...@@ -7,14 +7,12 @@ extensions ASAP)."""
__revision__ = "$Id$" __revision__ = "$Id$"
import sys, os, re import sys, os, re
from warnings import warn
from distutils.util import get_platform
from distutils.core import Command from distutils.core import Command
from distutils.errors import * from distutils.errors import *
from distutils.ccompiler import customize_compiler from distutils.sysconfig import customize_compiler, get_python_version
from distutils.dep_util import newer_group from distutils.dep_util import newer_group
from distutils.extension import Extension from distutils.extension import Extension
from distutils.util import get_platform
from distutils import log from distutils import log
# this keeps compatibility from 2.3 to 2.5 # this keeps compatibility from 2.3 to 2.5
...@@ -114,39 +112,6 @@ class build_ext(Command): ...@@ -114,39 +112,6 @@ class build_ext(Command):
"list available compilers", show_compilers), "list available compilers", show_compilers),
] ]
# making 'compiler' a property to deprecate
# its usage as something else than a compiler type
# e.g. like a compiler instance
def __init__(self, dist):
self._compiler = None
Command.__init__(self, dist)
def __setattr__(self, name, value):
# need this to make sure setattr() (used in distutils)
# doesn't kill our property
if name == 'compiler':
self._set_compiler(value)
else:
self.__dict__[name] = value
def _set_compiler(self, compiler):
if not isinstance(compiler, str) and compiler is not None:
# we don't want to allow that anymore in the future
warn("'compiler' specifies the compiler type in build_ext. "
"If you want to get the compiler object itself, "
"use 'compiler_obj'", DeprecationWarning)
self._compiler = compiler
def _get_compiler(self):
if not isinstance(self._compiler, str) and self._compiler is not None:
# we don't want to allow that anymore in the future
warn("'compiler' specifies the compiler type in build_ext. "
"If you want to get the compiler object itself, "
"use 'compiler_obj'", DeprecationWarning)
return self._compiler
compiler = property(_get_compiler, _set_compiler)
def initialize_options(self): def initialize_options(self):
self.extensions = None self.extensions = None
self.build_lib = None self.build_lib = None
...@@ -171,7 +136,8 @@ class build_ext(Command): ...@@ -171,7 +136,8 @@ class build_ext(Command):
self.user = None self.user = None
def finalize_options(self): def finalize_options(self):
_sysconfig = __import__('sysconfig') from distutils import sysconfig
self.set_undefined_options('build', self.set_undefined_options('build',
('build_lib', 'build_lib'), ('build_lib', 'build_lib'),
('build_temp', 'build_temp'), ('build_temp', 'build_temp'),
...@@ -188,8 +154,8 @@ class build_ext(Command): ...@@ -188,8 +154,8 @@ class build_ext(Command):
# Make sure Python's include directories (for Python.h, pyconfig.h, # Make sure Python's include directories (for Python.h, pyconfig.h,
# etc.) are in the include search path. # etc.) are in the include search path.
py_include = _sysconfig.get_path('include') py_include = sysconfig.get_python_inc()
plat_py_include = _sysconfig.get_path('platinclude') plat_py_include = sysconfig.get_python_inc(plat_specific=1)
if self.include_dirs is None: if self.include_dirs is None:
self.include_dirs = self.distribution.include_dirs or [] self.include_dirs = self.distribution.include_dirs or []
if isinstance(self.include_dirs, str): if isinstance(self.include_dirs, str):
...@@ -261,13 +227,13 @@ class build_ext(Command): ...@@ -261,13 +227,13 @@ class build_ext(Command):
if os.name == 'os2': if os.name == 'os2':
self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config')) self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config'))
# for extensions under Cygwin Python's library directory must be # for extensions under Cygwin and AtheOS Python's library directory must be
# appended to library_dirs # appended to library_dirs
if sys.platform[:6] == 'cygwin': if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos':
if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
# building third party extensions # building third party extensions
self.library_dirs.append(os.path.join(sys.prefix, "lib", self.library_dirs.append(os.path.join(sys.prefix, "lib",
"python" + _sysconfig.get_python_version(), "python" + get_python_version(),
"config")) "config"))
else: else:
# building python standard extensions # building python standard extensions
...@@ -275,13 +241,13 @@ class build_ext(Command): ...@@ -275,13 +241,13 @@ class build_ext(Command):
# for extensions under Linux or Solaris with a shared Python library, # for extensions under Linux or Solaris with a shared Python library,
# Python's library directory must be appended to library_dirs # Python's library directory must be appended to library_dirs
_sysconfig.get_config_var('Py_ENABLE_SHARED') sysconfig.get_config_var('Py_ENABLE_SHARED')
if ((sys.platform.startswith('linux') or sys.platform.startswith('gnu') if ((sys.platform.startswith('linux') or sys.platform.startswith('gnu')
or sys.platform.startswith('sunos')) or sys.platform.startswith('sunos'))
and _sysconfig.get_config_var('Py_ENABLE_SHARED')): and sysconfig.get_config_var('Py_ENABLE_SHARED')):
if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
# building third party extensions # building third party extensions
self.library_dirs.append(_sysconfig.get_config_var('LIBDIR')) self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
else: else:
# building python standard extensions # building python standard extensions
self.library_dirs.append('.') self.library_dirs.append('.')
...@@ -344,50 +310,38 @@ class build_ext(Command): ...@@ -344,50 +310,38 @@ class build_ext(Command):
# Setup the CCompiler object that we'll use to do all the # Setup the CCompiler object that we'll use to do all the
# compiling and linking # compiling and linking
self.compiler = new_compiler(compiler=self.compiler,
# used to prevent the usage of an existing compiler for the verbose=self.verbose,
# compiler option when calling new_compiler() dry_run=self.dry_run,
# this will be removed in 3.3 and 2.8 force=self.force)
if not isinstance(self._compiler, str): customize_compiler(self.compiler)
self._compiler = None
self.compiler_obj = new_compiler(compiler=self._compiler,
verbose=self.verbose,
dry_run=self.dry_run,
force=self.force)
# used to keep the compiler object reachable with
# "self.compiler". this will be removed in 3.3 and 2.8
self._compiler = self.compiler_obj
customize_compiler(self.compiler_obj)
# If we are cross-compiling, init the compiler now (if we are not # If we are cross-compiling, init the compiler now (if we are not
# cross-compiling, init would not hurt, but people may rely on # cross-compiling, init would not hurt, but people may rely on
# late initialization of compiler even if they shouldn't...) # late initialization of compiler even if they shouldn't...)
if os.name == 'nt' and self.plat_name != get_platform(): if os.name == 'nt' and self.plat_name != get_platform():
self.compiler_obj.initialize(self.plat_name) self.compiler.initialize(self.plat_name)
# And make sure that any compile/link-related options (which might # And make sure that any compile/link-related options (which might
# come from the command-line or from the setup script) are set in # come from the command-line or from the setup script) are set in
# that CCompiler object -- that way, they automatically apply to # that CCompiler object -- that way, they automatically apply to
# all compiling and linking done here. # all compiling and linking done here.
if self.include_dirs is not None: if self.include_dirs is not None:
self.compiler_obj.set_include_dirs(self.include_dirs) self.compiler.set_include_dirs(self.include_dirs)
if self.define is not None: if self.define is not None:
# 'define' option is a list of (name,value) tuples # 'define' option is a list of (name,value) tuples
for (name, value) in self.define: for (name, value) in self.define:
self.compiler_obj.define_macro(name, value) self.compiler.define_macro(name, value)
if self.undef is not None: if self.undef is not None:
for macro in self.undef: for macro in self.undef:
self.compiler_obj.undefine_macro(macro) self.compiler.undefine_macro(macro)
if self.libraries is not None: if self.libraries is not None:
self.compiler_obj.set_libraries(self.libraries) self.compiler.set_libraries(self.libraries)
if self.library_dirs is not None: if self.library_dirs is not None:
self.compiler_obj.set_library_dirs(self.library_dirs) self.compiler.set_library_dirs(self.library_dirs)
if self.rpath is not None: if self.rpath is not None:
self.compiler_obj.set_runtime_library_dirs(self.rpath) self.compiler.set_runtime_library_dirs(self.rpath)
if self.link_objects is not None: if self.link_objects is not None:
self.compiler_obj.set_link_objects(self.link_objects) self.compiler.set_link_objects(self.link_objects)
# Now actually compile and link everything. # Now actually compile and link everything.
self.build_extensions() self.build_extensions()
...@@ -548,13 +502,13 @@ class build_ext(Command): ...@@ -548,13 +502,13 @@ class build_ext(Command):
for undef in ext.undef_macros: for undef in ext.undef_macros:
macros.append((undef,)) macros.append((undef,))
objects = self.compiler_obj.compile(sources, objects = self.compiler.compile(sources,
output_dir=self.build_temp, output_dir=self.build_temp,
macros=macros, macros=macros,
include_dirs=ext.include_dirs, include_dirs=ext.include_dirs,
debug=self.debug, debug=self.debug,
extra_postargs=extra_args, extra_postargs=extra_args,
depends=ext.depends) depends=ext.depends)
# XXX -- this is a Vile HACK! # XXX -- this is a Vile HACK!
# #
...@@ -575,9 +529,9 @@ class build_ext(Command): ...@@ -575,9 +529,9 @@ class build_ext(Command):
extra_args = ext.extra_link_args or [] extra_args = ext.extra_link_args or []
# Detect target language, if not provided # Detect target language, if not provided
language = ext.language or self.compiler_obj.detect_language(sources) language = ext.language or self.compiler.detect_language(sources)
self.compiler_obj.link_shared_object( self.compiler.link_shared_object(
objects, ext_path, objects, ext_path,
libraries=self.get_libraries(ext), libraries=self.get_libraries(ext),
library_dirs=ext.library_dirs, library_dirs=ext.library_dirs,
...@@ -710,13 +664,13 @@ class build_ext(Command): ...@@ -710,13 +664,13 @@ class build_ext(Command):
of the file from which it will be loaded (eg. "foo/bar.so", or of the file from which it will be loaded (eg. "foo/bar.so", or
"foo\bar.pyd"). "foo\bar.pyd").
""" """
_sysconfig = __import__('sysconfig') from distutils.sysconfig import get_config_var
ext_path = ext_name.split('.') ext_path = ext_name.split('.')
# OS/2 has an 8 character module (extension) limit :-( # OS/2 has an 8 character module (extension) limit :-(
if os.name == "os2": if os.name == "os2":
ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8] ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
# extensions in debug_mode are named 'module_d.pyd' under windows # extensions in debug_mode are named 'module_d.pyd' under windows
so_ext = _sysconfig.get_config_var('SO') so_ext = get_config_var('SO')
if os.name == 'nt' and self.debug: if os.name == 'nt' and self.debug:
return os.path.join(*ext_path) + '_d' + so_ext return os.path.join(*ext_path) + '_d' + so_ext
return os.path.join(*ext_path) + so_ext return os.path.join(*ext_path) + so_ext
...@@ -744,7 +698,7 @@ class build_ext(Command): ...@@ -744,7 +698,7 @@ class build_ext(Command):
# Append '_d' to the python import library on debug builds. # Append '_d' to the python import library on debug builds.
if sys.platform == "win32": if sys.platform == "win32":
from distutils.msvccompiler import MSVCCompiler from distutils.msvccompiler import MSVCCompiler
if not isinstance(self.compiler_obj, MSVCCompiler): if not isinstance(self.compiler, MSVCCompiler):
template = "python%d%d" template = "python%d%d"
if self.debug: if self.debug:
template = template + '_d' template = template + '_d'
...@@ -775,12 +729,28 @@ class build_ext(Command): ...@@ -775,12 +729,28 @@ class build_ext(Command):
# don't extend ext.libraries, it may be shared with other # don't extend ext.libraries, it may be shared with other
# extensions, it is a reference to the original list # extensions, it is a reference to the original list
return ext.libraries + [pythonlib] return ext.libraries + [pythonlib]
elif sys.platform[:6] == "atheos":
from distutils import sysconfig
template = "python%d.%d"
pythonlib = (template %
(sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
# 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': elif sys.platform == 'darwin':
# Don't use the default code below # Don't use the default code below
return ext.libraries return ext.libraries
else: else:
_sysconfig = __import__('sysconfig') from distutils import sysconfig
if _sysconfig.get_config_var('Py_ENABLE_SHARED'): if sysconfig.get_config_var('Py_ENABLE_SHARED'):
template = "python%d.%d" template = "python%d.%d"
pythonlib = (template % pythonlib = (template %
(sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
......
...@@ -4,16 +4,16 @@ Implements the Distutils 'build_py' command.""" ...@@ -4,16 +4,16 @@ Implements the Distutils 'build_py' command."""
__revision__ = "$Id$" __revision__ = "$Id$"
import os import sys, os
import sys import sys
from glob import glob from glob import glob
from distutils.core import Command from distutils.core import Command
from distutils.errors import DistutilsOptionError, DistutilsFileError from distutils.errors import *
from distutils.util import convert_path, Mixin2to3 from distutils.util import convert_path, Mixin2to3
from distutils import log from distutils import log
class build_py(Command): class build_py (Command):
description = "\"build\" pure Python modules (copy to build directory)" description = "\"build\" pure Python modules (copy to build directory)"
...@@ -133,6 +133,7 @@ class build_py(Command): ...@@ -133,6 +133,7 @@ class build_py(Command):
def build_package_data(self): def build_package_data(self):
"""Copy data files into build directory""" """Copy data files into build directory"""
lastdir = None
for package, src_dir, build_dir, filenames in self.data_files: for package, src_dir, build_dir, filenames in self.data_files:
for filename in filenames: for filename in filenames:
target = os.path.join(build_dir, filename) target = os.path.join(build_dir, filename)
......
...@@ -6,6 +6,7 @@ __revision__ = "$Id$" ...@@ -6,6 +6,7 @@ __revision__ = "$Id$"
import os, re import os, re
from stat import ST_MODE from stat import ST_MODE
from distutils import sysconfig
from distutils.core import Command from distutils.core import Command
from distutils.dep_util import newer from distutils.dep_util import newer
from distutils.util import convert_path, Mixin2to3 from distutils.util import convert_path, Mixin2to3
...@@ -56,7 +57,6 @@ class build_scripts(Command): ...@@ -56,7 +57,6 @@ class build_scripts(Command):
ie. starts with "\#!" and contains "python"), then adjust the first ie. starts with "\#!" and contains "python"), then adjust the first
line to refer to the current Python interpreter as we copy. line to refer to the current Python interpreter as we copy.
""" """
_sysconfig = __import__('sysconfig')
self.mkpath(self.build_dir) self.mkpath(self.build_dir)
outfiles = [] outfiles = []
updated_files = [] updated_files = []
...@@ -96,16 +96,16 @@ class build_scripts(Command): ...@@ -96,16 +96,16 @@ class build_scripts(Command):
updated_files.append(outfile) updated_files.append(outfile)
if not self.dry_run: if not self.dry_run:
outf = open(outfile, "w") outf = open(outfile, "w")
if not _sysconfig.is_python_build(): if not sysconfig.python_build:
outf.write("#!%s%s\n" % outf.write("#!%s%s\n" %
(self.executable, (self.executable,
post_interp)) post_interp))
else: else:
outf.write("#!%s%s\n" % outf.write("#!%s%s\n" %
(os.path.join( (os.path.join(
_sysconfig.get_config_var("BINDIR"), sysconfig.get_config_var("BINDIR"),
"python%s%s" % (_sysconfig.get_config_var("VERSION"), "python%s%s" % (sysconfig.get_config_var("VERSION"),
_sysconfig.get_config_var("EXE"))), sysconfig.get_config_var("EXE"))),
post_interp)) post_interp))
outf.writelines(f.readlines()) outf.writelines(f.readlines())
outf.close() outf.close()
......
...@@ -11,12 +11,11 @@ this header file lives". ...@@ -11,12 +11,11 @@ this header file lives".
__revision__ = "$Id$" __revision__ = "$Id$"
import os import sys, os, re
import re
from distutils.core import Command from distutils.core import Command
from distutils.errors import DistutilsExecError from distutils.errors import DistutilsExecError
from distutils.ccompiler import customize_compiler from distutils.sysconfig import customize_compiler
from distutils import log from distutils import log
LANG_EXT = {"c": ".c", "c++": ".cxx"} LANG_EXT = {"c": ".c", "c++": ".cxx"}
......
...@@ -7,17 +7,26 @@ __revision__ = "$Id$" ...@@ -7,17 +7,26 @@ __revision__ = "$Id$"
import sys import sys
import os import os
from sysconfig import get_config_vars, get_paths, get_path, get_config_var
from distutils import log from distutils import log
from distutils.core import Command from distutils.core import Command
from distutils.debug import DEBUG from distutils.debug import DEBUG
from distutils.sysconfig import get_config_vars
from distutils.errors import DistutilsPlatformError from distutils.errors import DistutilsPlatformError
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.util import convert_path, change_root, get_platform from distutils.util import convert_path, subst_vars, change_root
from distutils.util import get_platform
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
# kept for backward compat, will be removed in 3.2 # this keeps compatibility from 2.3 to 2.5
if sys.version < "2.6":
USER_BASE = None
USER_SITE = None
HAS_USER_SITE = False
else:
from site import USER_BASE
from site import USER_SITE
HAS_USER_SITE = True
if sys.version < "2.2": if sys.version < "2.2":
WINDOWS_SCHEME = { WINDOWS_SCHEME = {
'purelib': '$base', 'purelib': '$base',
...@@ -50,21 +59,15 @@ INSTALL_SCHEMES = { ...@@ -50,21 +59,15 @@ INSTALL_SCHEMES = {
'scripts': '$base/bin', 'scripts': '$base/bin',
'data' : '$base', 'data' : '$base',
}, },
'unix_user': {
'purelib': '$usersite',
'platlib': '$usersite',
'headers': '$userbase/include/python$py_version_short/$dist_name',
'scripts': '$userbase/bin',
'data' : '$userbase',
},
'nt': WINDOWS_SCHEME, 'nt': WINDOWS_SCHEME,
'nt_user': { 'mac': {
'purelib': '$usersite', 'purelib': '$base/Lib/site-packages',
'platlib': '$usersite', 'platlib': '$base/Lib/site-packages',
'headers': '$userbase/Python$py_version_nodot/Include/$dist_name', 'headers': '$base/Include/$dist_name',
'scripts': '$userbase/Scripts', 'scripts': '$base/Scripts',
'data' : '$userbase', 'data' : '$base',
}, },
'os2': { 'os2': {
'purelib': '$base/Lib/site-packages', 'purelib': '$base/Lib/site-packages',
'platlib': '$base/Lib/site-packages', 'platlib': '$base/Lib/site-packages',
...@@ -72,26 +75,47 @@ INSTALL_SCHEMES = { ...@@ -72,26 +75,47 @@ INSTALL_SCHEMES = {
'scripts': '$base/Scripts', 'scripts': '$base/Scripts',
'data' : '$base', 'data' : '$base',
}, },
'os2_home': { }
# user site schemes
if HAS_USER_SITE:
INSTALL_SCHEMES['nt_user'] = {
'purelib': '$usersite',
'platlib': '$usersite',
'headers': '$userbase/Python$py_version_nodot/Include/$dist_name',
'scripts': '$userbase/Scripts',
'data' : '$userbase',
}
INSTALL_SCHEMES['unix_user'] = {
'purelib': '$usersite', 'purelib': '$usersite',
'platlib': '$usersite', 'platlib': '$usersite',
'headers': '$userbase/include/python$py_version_short/$dist_name', 'headers': '$userbase/include/python$py_version_short/$dist_name',
'scripts': '$userbase/bin', 'scripts': '$userbase/bin',
'data' : '$userbase', 'data' : '$userbase',
}, }
}
INSTALL_SCHEMES['mac_user'] = {
'purelib': '$usersite',
'platlib': '$usersite',
'headers': '$userbase/$py_version_short/include/$dist_name',
'scripts': '$userbase/bin',
'data' : '$userbase',
}
INSTALL_SCHEMES['os2_home'] = {
'purelib': '$usersite',
'platlib': '$usersite',
'headers': '$userbase/include/python$py_version_short/$dist_name',
'scripts': '$userbase/bin',
'data' : '$userbase',
}
# The keys to an installation scheme; if any new types of files are to be
# installed, be sure to add an entry to every installation scheme above,
# and to SCHEME_KEYS here.
SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data') SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
# end of backward compat
def _subst_vars(s, local_vars):
try:
return s.format(**local_vars)
except KeyError:
try:
return s.format(**os.environ)
except KeyError as var:
raise AttributeError('{%s}' % var)
class install(Command): class install(Command):
...@@ -158,10 +182,11 @@ class install(Command): ...@@ -158,10 +182,11 @@ class install(Command):
boolean_options = ['compile', 'force', 'skip-build'] boolean_options = ['compile', 'force', 'skip-build']
user_options.append(('user', None, if HAS_USER_SITE:
"install in user site-package '%s'" % \ user_options.append(('user', None,
get_path('purelib', '%s_user' % os.name))) "install in user site-package '%s'" % USER_SITE))
boolean_options.append('user') boolean_options.append('user')
negative_opt = {'no-compile' : 'compile'} negative_opt = {'no-compile' : 'compile'}
...@@ -191,8 +216,8 @@ class install(Command): ...@@ -191,8 +216,8 @@ class install(Command):
self.install_lib = None # set to either purelib or platlib self.install_lib = None # set to either purelib or platlib
self.install_scripts = None self.install_scripts = None
self.install_data = None self.install_data = None
self.install_userbase = get_config_var('userbase') self.install_userbase = USER_BASE
self.install_usersite = get_path('purelib', '%s_user' % os.name) self.install_usersite = USER_SITE
self.compile = None self.compile = None
self.optimize = None self.optimize = None
...@@ -302,9 +327,7 @@ class install(Command): ...@@ -302,9 +327,7 @@ class install(Command):
# about needing recursive variable expansion (shudder). # about needing recursive variable expansion (shudder).
py_version = sys.version.split()[0] py_version = sys.version.split()[0]
prefix, exec_prefix, srcdir, projectbase = get_config_vars('prefix', 'exec_prefix', (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
'srcdir', 'projectbase')
self.config_vars = {'dist_name': self.distribution.get_name(), self.config_vars = {'dist_name': self.distribution.get_name(),
'dist_version': self.distribution.get_version(), 'dist_version': self.distribution.get_version(),
'dist_fullname': self.distribution.get_fullname(), 'dist_fullname': self.distribution.get_fullname(),
...@@ -315,12 +338,12 @@ class install(Command): ...@@ -315,12 +338,12 @@ class install(Command):
'prefix': prefix, 'prefix': prefix,
'sys_exec_prefix': exec_prefix, 'sys_exec_prefix': exec_prefix,
'exec_prefix': exec_prefix, 'exec_prefix': exec_prefix,
'srcdir': srcdir,
'projectbase': projectbase,
} }
self.config_vars['userbase'] = self.install_userbase if HAS_USER_SITE:
self.config_vars['usersite'] = self.install_usersite self.config_vars['userbase'] = self.install_userbase
self.config_vars['usersite'] = self.install_usersite
self.expand_basedirs() self.expand_basedirs()
self.dump_dirs("post-expand_basedirs()") self.dump_dirs("post-expand_basedirs()")
...@@ -424,10 +447,10 @@ class install(Command): ...@@ -424,10 +447,10 @@ class install(Command):
raise DistutilsPlatformError( raise DistutilsPlatformError(
"User base directory is not specified") "User base directory is not specified")
self.install_base = self.install_platbase = self.install_userbase self.install_base = self.install_platbase = self.install_userbase
self.select_scheme("posix_user") self.select_scheme("unix_user")
elif self.home is not None: elif self.home is not None:
self.install_base = self.install_platbase = self.home self.install_base = self.install_platbase = self.home
self.select_scheme("posix_home") self.select_scheme("unix_home")
else: else:
if self.prefix is None: if self.prefix is None:
if self.exec_prefix is not None: if self.exec_prefix is not None:
...@@ -443,7 +466,7 @@ class install(Command): ...@@ -443,7 +466,7 @@ class install(Command):
self.install_base = self.prefix self.install_base = self.prefix
self.install_platbase = self.exec_prefix self.install_platbase = self.exec_prefix
self.select_scheme("posix_prefix") self.select_scheme("unix_prefix")
def finalize_other(self): def finalize_other(self):
"""Finalizes options for non-posix platforms""" """Finalizes options for non-posix platforms"""
...@@ -455,7 +478,7 @@ class install(Command): ...@@ -455,7 +478,7 @@ class install(Command):
self.select_scheme(os.name + "_user") self.select_scheme(os.name + "_user")
elif self.home is not None: elif self.home is not None:
self.install_base = self.install_platbase = self.home self.install_base = self.install_platbase = self.home
self.select_scheme("posix_home") self.select_scheme("unix_home")
else: else:
if self.prefix is None: if self.prefix is None:
self.prefix = os.path.normpath(sys.prefix) self.prefix = os.path.normpath(sys.prefix)
...@@ -470,15 +493,11 @@ class install(Command): ...@@ -470,15 +493,11 @@ class install(Command):
def select_scheme(self, name): def select_scheme(self, name):
"""Sets the install directories by applying the install schemes.""" """Sets the install directories by applying the install schemes."""
# it's the caller's problem if they supply a bad name! # it's the caller's problem if they supply a bad name!
scheme = get_paths(name, expand=False) scheme = INSTALL_SCHEMES[name]
for key, value in scheme.items(): for key in SCHEME_KEYS:
if key == 'platinclude':
key = 'headers'
value = os.path.join(value, self.distribution.get_name())
attrname = 'install_' + key attrname = 'install_' + key
if hasattr(self, attrname): if getattr(self, attrname) is None:
if getattr(self, attrname) is None: setattr(self, attrname, scheme[key])
setattr(self, attrname, value)
def _expand_attrs(self, attrs): def _expand_attrs(self, attrs):
for attr in attrs: for attr in attrs:
...@@ -486,7 +505,7 @@ class install(Command): ...@@ -486,7 +505,7 @@ class install(Command):
if val is not None: if val is not None:
if os.name == 'posix' or os.name == 'nt': if os.name == 'posix' or os.name == 'nt':
val = os.path.expanduser(val) val = os.path.expanduser(val)
val = _subst_vars(val, self.config_vars) val = subst_vars(val, self.config_vars)
setattr(self, attr, val) setattr(self, attr, val)
def expand_basedirs(self): def expand_basedirs(self):
......
...@@ -7,15 +7,13 @@ Implements the Distutils 'register' command (register with the repository). ...@@ -7,15 +7,13 @@ Implements the Distutils 'register' command (register with the repository).
__revision__ = "$Id$" __revision__ = "$Id$"
import os import os, string, getpass
import string
import getpass
import io import io
import urllib.parse import urllib.parse, urllib.request
import urllib.request
from warnings import warn from warnings import warn
from distutils.core import PyPIRCCommand from distutils.core import PyPIRCCommand
from distutils.errors import *
from distutils import log from distutils import log
class register(PyPIRCCommand): class register(PyPIRCCommand):
......
...@@ -7,14 +7,14 @@ __revision__ = "$Id$" ...@@ -7,14 +7,14 @@ __revision__ = "$Id$"
import os import os
import string import string
import sys import sys
from types import *
from glob import glob from glob import glob
from warnings import warn from warnings import warn
from distutils.core import Command from distutils.core import Command
from distutils import dir_util, dep_util, file_util, archive_util from distutils import dir_util, dep_util, file_util, archive_util
from distutils.text_file import TextFile from distutils.text_file import TextFile
from distutils.errors import (DistutilsPlatformError, DistutilsOptionError, from distutils.errors import *
DistutilsTemplateError)
from distutils.filelist import FileList from distutils.filelist import FileList
from distutils import log from distutils import log
from distutils.util import convert_path from distutils.util import convert_path
...@@ -76,10 +76,6 @@ class sdist(Command): ...@@ -76,10 +76,6 @@ class sdist(Command):
('medata-check', None, ('medata-check', None,
"Ensure that all required elements of meta-data " "Ensure that all required elements of meta-data "
"are supplied. Warn if any missing. [default]"), "are supplied. Warn if any missing. [default]"),
('owner=', 'u',
"Owner name used when creating a tar file [default: current user]"),
('group=', 'g',
"Group name used when creating a tar file [default: current group]"),
] ]
boolean_options = ['use-defaults', 'prune', boolean_options = ['use-defaults', 'prune',
...@@ -119,8 +115,6 @@ class sdist(Command): ...@@ -119,8 +115,6 @@ class sdist(Command):
self.archive_files = None self.archive_files = None
self.metadata_check = 1 self.metadata_check = 1
self.owner = None
self.group = None
def finalize_options(self): def finalize_options(self):
if self.manifest is None: if self.manifest is None:
...@@ -424,8 +418,7 @@ class sdist(Command): ...@@ -424,8 +418,7 @@ class sdist(Command):
self.formats.append(self.formats.pop(self.formats.index('tar'))) self.formats.append(self.formats.pop(self.formats.index('tar')))
for fmt in self.formats: for fmt in self.formats:
file = self.make_archive(base_name, fmt, base_dir=base_dir, file = self.make_archive(base_name, fmt, base_dir=base_dir)
owner=self.owner, group=self.group)
archive_files.append(file) archive_files.append(file)
self.distribution.dist_files.append(('sdist', '', file)) self.distribution.dist_files.append(('sdist', '', file))
......
"""distutils.command.upload """distutils.command.upload
Implements the Distutils 'upload' subcommand (upload package to PyPI).""" Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
import os
import io
import socket
import platform
from urllib.request import urlopen, Request, HTTPError
from base64 import standard_b64encode
from urllib.parse import urlparse
from hashlib import md5
from distutils.errors import DistutilsOptionError from distutils.errors import *
from distutils.core import PyPIRCCommand from distutils.core import PyPIRCCommand
from distutils.spawn import spawn from distutils.spawn import spawn
from distutils import log from distutils import log
import sys
import os, io
import socket
import platform
import configparser
import http.client as httpclient
from base64 import standard_b64encode
import urllib.parse
# this keeps compatibility for 2.3 and 2.4
if sys.version < "2.5":
from md5 import md5
else:
from hashlib import md5
class upload(PyPIRCCommand): class upload(PyPIRCCommand):
...@@ -60,15 +66,6 @@ class upload(PyPIRCCommand): ...@@ -60,15 +66,6 @@ class upload(PyPIRCCommand):
self.upload_file(command, pyversion, filename) self.upload_file(command, pyversion, filename)
def upload_file(self, command, pyversion, filename): def upload_file(self, command, pyversion, filename):
# Makes sure the repository URL is compliant
schema, netloc, url, params, query, fragments = \
urlparse(self.repository)
if params or query or fragments:
raise AssertionError("Incompatible url %s" % self.repository)
if schema not in ('http', 'https'):
raise AssertionError("unsupported schema " + schema)
# Sign if requested # Sign if requested
if self.sign: if self.sign:
gpg_args = ["gpg", "--detach-sign", "-a", filename] gpg_args = ["gpg", "--detach-sign", "-a", filename]
...@@ -140,10 +137,10 @@ class upload(PyPIRCCommand): ...@@ -140,10 +137,10 @@ class upload(PyPIRCCommand):
for key, value in data.items(): for key, value in data.items():
title = '\nContent-Disposition: form-data; name="%s"' % key title = '\nContent-Disposition: form-data; name="%s"' % key
# handle multiple entries for the same name # handle multiple entries for the same name
if not isinstance(value, list): if type(value) != type([]):
value = [value] value = [value]
for value in value: for value in value:
if isinstance(value, tuple): if type(value) is tuple:
title += '; filename="%s"' % value[0] title += '; filename="%s"' % value[0]
value = value[1] value = value[1]
else: else:
...@@ -161,30 +158,40 @@ class upload(PyPIRCCommand): ...@@ -161,30 +158,40 @@ class upload(PyPIRCCommand):
self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO) self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
# build the Request # build the Request
headers = {'Content-type': # We can't use urllib since we need to send the Basic
'multipart/form-data; boundary=%s' % boundary, # auth right with the first request
'Content-length': str(len(body)), # TODO(jhylton): Can we fix urllib?
'Authorization': auth} schema, netloc, url, params, query, fragments = \
urllib.parse.urlparse(self.repository)
request = Request(self.repository, data=body, assert not params and not query and not fragments
headers=headers) if schema == 'http':
# send the data http = httpclient.HTTPConnection(netloc)
elif schema == 'https':
http = httpclient.HTTPSConnection(netloc)
else:
raise AssertionError("unsupported schema "+schema)
data = ''
loglevel = log.INFO
try: try:
result = urlopen(request) http.connect()
status = result.getcode() http.putrequest("POST", url)
reason = result.msg http.putheader('Content-type',
'multipart/form-data; boundary=%s'%boundary)
http.putheader('Content-length', str(len(body)))
http.putheader('Authorization', auth)
http.endheaders()
http.send(body)
except socket.error as e: except socket.error as e:
self.announce(str(e), log.ERROR) self.announce(str(e), log.ERROR)
return return
except HTTPError as e:
status = e.code
reason = e.msg
if status == 200: r = http.getresponse()
self.announce('Server response (%s): %s' % (status, reason), if r.status == 200:
self.announce('Server response (%s): %s' % (r.status, r.reason),
log.INFO) log.INFO)
else: else:
self.announce('Upload failed (%s): %s' % (status, reason), self.announce('Upload failed (%s): %s' % (r.status, r.reason),
log.ERROR) log.ERROR)
if self.show_response: if self.show_response:
self.announce('-'*75, result.read(), '-'*75) self.announce('-'*75, r.read(), '-'*75)
...@@ -4,6 +4,7 @@ Provides the PyPIRCCommand class, the base class for the command classes ...@@ -4,6 +4,7 @@ Provides the PyPIRCCommand class, the base class for the command classes
that uses .pypirc in the distutils.command package. that uses .pypirc in the distutils.command package.
""" """
import os import os
import sys
from configparser import ConfigParser from configparser import ConfigParser
from distutils.cmd import Command from distutils.cmd import Command
...@@ -59,6 +60,8 @@ class PyPIRCCommand(Command): ...@@ -59,6 +60,8 @@ class PyPIRCCommand(Command):
if os.path.exists(rc): if os.path.exists(rc):
self.announce('Using PyPI login from %s' % rc) self.announce('Using PyPI login from %s' % rc)
repository = self.repository or self.DEFAULT_REPOSITORY repository = self.repository or self.DEFAULT_REPOSITORY
realm = self.realm or self.DEFAULT_REALM
config = ConfigParser() config = ConfigParser()
config.read(rc) config.read(rc)
sections = config.sections() sections = config.sections()
......
...@@ -8,12 +8,10 @@ really defined in distutils.dist and distutils.cmd. ...@@ -8,12 +8,10 @@ really defined in distutils.dist and distutils.cmd.
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, os
import os
from distutils.debug import DEBUG from distutils.debug import DEBUG
from distutils.errors import (DistutilsSetupError, DistutilsArgError, from distutils.errors import *
DistutilsError, CCompilerError)
from distutils.util import grok_environment_error from distutils.util import grok_environment_error
# Mainly import these so setup scripts can "from distutils.core import" them. # Mainly import these so setup scripts can "from distutils.core import" them.
...@@ -33,9 +31,9 @@ usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] ...@@ -33,9 +31,9 @@ usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: %(script)s cmd --help or: %(script)s cmd --help
""" """
def gen_usage(script_name): def gen_usage (script_name):
script = os.path.basename(script_name) script = os.path.basename(script_name)
return USAGE % {'script': script} return USAGE % vars()
# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'. # Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
...@@ -58,7 +56,7 @@ extension_keywords = ('name', 'sources', 'include_dirs', ...@@ -58,7 +56,7 @@ extension_keywords = ('name', 'sources', 'include_dirs',
'extra_objects', 'extra_compile_args', 'extra_link_args', 'extra_objects', 'extra_compile_args', 'extra_link_args',
'swig_opts', 'export_symbols', 'depends', 'language') 'swig_opts', 'export_symbols', 'depends', 'language')
def setup(**attrs): def setup (**attrs):
"""The gateway to the Distutils: do everything your setup script needs """The gateway to the Distutils: do everything your setup script needs
to do, in a highly flexible and user-driven way. Briefly: create a to do, in a highly flexible and user-driven way. Briefly: create a
Distribution instance; find and parse config files; parse the command Distribution instance; find and parse config files; parse the command
...@@ -131,9 +129,8 @@ def setup(**attrs): ...@@ -131,9 +129,8 @@ def setup(**attrs):
if _setup_stop_after == "config": if _setup_stop_after == "config":
return dist return dist
# Parse the command line and override config files; any # Parse the command line; any command-line errors are the end user's
# command-line errors are the end user's fault, so turn them into # fault, so turn them into SystemExit to suppress tracebacks.
# SystemExit to suppress tracebacks.
try: try:
ok = dist.parse_command_line() ok = dist.parse_command_line()
except DistutilsArgError as msg: except DistutilsArgError as msg:
...@@ -170,8 +167,10 @@ def setup(**attrs): ...@@ -170,8 +167,10 @@ def setup(**attrs):
return dist return dist
# setup ()
def run_setup(script_name, script_args=None, stop_after="run"):
def run_setup (script_name, script_args=None, stop_after="run"):
"""Run a setup script in a somewhat controlled environment, and """Run a setup script in a somewhat controlled environment, and
return the Distribution instance that drives things. This is useful return the Distribution instance that drives things. This is useful
if you need to find out the distribution meta-data (passed as if you need to find out the distribution meta-data (passed as
...@@ -234,4 +233,7 @@ def run_setup(script_name, script_args=None, stop_after="run"): ...@@ -234,4 +233,7 @@ def run_setup(script_name, script_args=None, stop_after="run"):
# I wonder if the setup script's namespace -- g and l -- would be of # I wonder if the setup script's namespace -- g and l -- would be of
# any interest to callers? # any interest to callers?
#print "_setup_distribution:", _setup_distribution
return _setup_distribution return _setup_distribution
# run_setup ()
...@@ -50,13 +50,16 @@ __revision__ = "$Id$" ...@@ -50,13 +50,16 @@ __revision__ = "$Id$"
import os import os
import sys import sys
import copy import copy
from subprocess import Popen, PIPE
import re import re
from warnings import warn
from distutils.ccompiler import gen_preprocess_options, gen_lib_options
from distutils.unixccompiler import UnixCCompiler from distutils.unixccompiler import UnixCCompiler
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.errors import DistutilsExecError, CompileError, UnknownFileError from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
from distutils.util import get_compiler_versions from distutils import log
from distutils.version import LooseVersion
from distutils.spawn import find_executable
def get_msvcr(): def get_msvcr():
"""Include the appropriate MSVC runtime library if Python was built """Include the appropriate MSVC runtime library if Python was built
...@@ -107,7 +110,7 @@ class CygwinCCompiler(UnixCCompiler): ...@@ -107,7 +110,7 @@ class CygwinCCompiler(UnixCCompiler):
% details) % details)
self.gcc_version, self.ld_version, self.dllwrap_version = \ self.gcc_version, self.ld_version, self.dllwrap_version = \
get_compiler_versions() get_versions()
self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
(self.gcc_version, (self.gcc_version,
self.ld_version, self.ld_version,
...@@ -337,7 +340,7 @@ def check_config_h(): ...@@ -337,7 +340,7 @@ def check_config_h():
# XXX since this function also checks sys.version, it's not strictly a # XXX since this function also checks sys.version, it's not strictly a
# "pyconfig.h" check -- should probably be renamed... # "pyconfig.h" check -- should probably be renamed...
_sysconfig = __import__('sysconfig') from distutils import sysconfig
# if sys.version contains GCC then python was compiled with GCC, and the # if sys.version contains GCC then python was compiled with GCC, and the
# pyconfig.h file should be OK # pyconfig.h file should be OK
...@@ -345,7 +348,7 @@ def check_config_h(): ...@@ -345,7 +348,7 @@ def check_config_h():
return CONFIG_H_OK, "sys.version mentions 'GCC'" return CONFIG_H_OK, "sys.version mentions 'GCC'"
# let's see if __GNUC__ is mentioned in python.h # let's see if __GNUC__ is mentioned in python.h
fn = _sysconfig.get_config_h_filename() fn = sysconfig.get_config_h_filename()
try: try:
with open(fn) as config_h: with open(fn) as config_h:
if "__GNUC__" in config_h.read(): if "__GNUC__" in config_h.read():
...@@ -356,27 +359,33 @@ def check_config_h(): ...@@ -356,27 +359,33 @@ def check_config_h():
return (CONFIG_H_UNCERTAIN, return (CONFIG_H_UNCERTAIN,
"couldn't read '%s': %s" % (fn, exc.strerror)) "couldn't read '%s': %s" % (fn, exc.strerror))
class _Deprecated_SRE_Pattern(object): RE_VERSION = re.compile(b'(\d+\.\d+(\.\d+)*)')
def __init__(self, pattern):
self.pattern = pattern
def __getattr__(self, name): def _find_exe_version(cmd):
if name in ('findall', 'finditer', 'match', 'scanner', 'search', """Find the version of an executable by running `cmd` in the shell.
'split', 'sub', 'subn'):
warn("'distutils.cygwinccompiler.RE_VERSION' is deprecated "
"and will be removed in the next version", DeprecationWarning)
return getattr(self.pattern, name)
If the command is not found, or the output does not match
RE_VERSION = _Deprecated_SRE_Pattern(re.compile('(\d+\.\d+(\.\d+)*)')) `RE_VERSION`, returns None.
"""
executable = cmd.split()[0]
if find_executable(executable) is None:
return None
out = Popen(cmd, shell=True, stdout=PIPE).stdout
try:
out_string = out.read()
finally:
out.close()
result = RE_VERSION.search(out_string)
if result is None:
return None
# LooseVersion works with strings
# so we need to decode our bytes
return LooseVersion(result.group(1).decode())
def get_versions(): def get_versions():
""" Try to find out the versions of gcc, ld and dllwrap. """ Try to find out the versions of gcc, ld and dllwrap.
If not possible it returns None for it. If not possible it returns None for it.
""" """
warn("'distutils.cygwinccompiler.get_versions' is deprecated " commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
"use 'distutils.util.get_compiler_versions' instead", return tuple([_find_exe_version(cmd) for cmd in commands])
DeprecationWarning)
return get_compiler_versions()
...@@ -9,27 +9,29 @@ __revision__ = "$Id$" ...@@ -9,27 +9,29 @@ __revision__ = "$Id$"
import os import os
from distutils.errors import DistutilsFileError from distutils.errors import DistutilsFileError
def newer(source, target):
"""Tells if the target is newer than the source.
Return true if 'source' exists and is more recently modified than def newer (source, target):
'target', or if 'source' exists and 'target' doesn't. """Return true if 'source' exists and is more recently modified than
'target', or if 'source' exists and 'target' doesn't. Return false if
Return false if both exist and 'target' is the same age or younger both exist and 'target' is the same age or younger than 'source'.
than 'source'. Raise DistutilsFileError if 'source' does not exist. Raise DistutilsFileError if 'source' does not exist.
Note that this test is not very accurate: files created in the same second
will have the same "age".
""" """
if not os.path.exists(source): if not os.path.exists(source):
raise DistutilsFileError("file '%s' does not exist" % raise DistutilsFileError("file '%s' does not exist" %
os.path.abspath(source)) os.path.abspath(source))
if not os.path.exists(target): if not os.path.exists(target):
return True return 1
from stat import ST_MTIME
mtime1 = os.stat(source)[ST_MTIME]
mtime2 = os.stat(target)[ST_MTIME]
return mtime1 > mtime2
# newer ()
return os.stat(source).st_mtime > os.stat(target).st_mtime
def newer_pairwise(sources, targets): def newer_pairwise (sources, targets):
"""Walk two filename lists in parallel, testing if each source is newer """Walk two filename lists in parallel, testing if each source is newer
than its corresponding target. Return a pair of lists (sources, than its corresponding target. Return a pair of lists (sources,
targets) where source is newer than target, according to the semantics targets) where source is newer than target, according to the semantics
...@@ -41,18 +43,19 @@ def newer_pairwise(sources, targets): ...@@ -41,18 +43,19 @@ def newer_pairwise(sources, targets):
# build a pair of lists (sources, targets) where source is newer # build a pair of lists (sources, targets) where source is newer
n_sources = [] n_sources = []
n_targets = [] n_targets = []
for source, target in zip(sources, targets): for i in range(len(sources)):
if newer(source, target): if newer(sources[i], targets[i]):
n_sources.append(source) n_sources.append(sources[i])
n_targets.append(target) n_targets.append(targets[i])
return n_sources, n_targets return (n_sources, n_targets)
# newer_pairwise ()
def newer_group(sources, target, missing='error'):
"""Return true if 'target' is out-of-date with respect to any file
listed in 'sources'.
In other words, if 'target' exists and is newer def newer_group (sources, target, missing='error'):
"""Return true if 'target' is out-of-date with respect to any file
listed in 'sources'. In other words, if 'target' exists and is newer
than every file in 'sources', return false; otherwise return true. than every file in 'sources', return false; otherwise return true.
'missing' controls what we do when a source file is missing; the 'missing' controls what we do when a source file is missing; the
default ("error") is to blow up with an OSError from inside 'stat()'; default ("error") is to blow up with an OSError from inside 'stat()';
...@@ -65,14 +68,14 @@ def newer_group(sources, target, missing='error'): ...@@ -65,14 +68,14 @@ def newer_group(sources, target, missing='error'):
""" """
# If the target doesn't even exist, then it's definitely out-of-date. # If the target doesn't even exist, then it's definitely out-of-date.
if not os.path.exists(target): if not os.path.exists(target):
return True return 1
# Otherwise we have to find out the hard way: if *any* source file # Otherwise we have to find out the hard way: if *any* source file
# is more recent than 'target', then 'target' is out-of-date and # is more recent than 'target', then 'target' is out-of-date and
# we can immediately return true. If we fall through to the end # we can immediately return true. If we fall through to the end
# of the loop, then 'target' is up-to-date and we return false. # of the loop, then 'target' is up-to-date and we return false.
target_mtime = os.stat(target).st_mtime from stat import ST_MTIME
target_mtime = os.stat(target)[ST_MTIME]
for source in sources: for source in sources:
if not os.path.exists(source): if not os.path.exists(source):
if missing == 'error': # blow up when we stat() the file if missing == 'error': # blow up when we stat() the file
...@@ -80,9 +83,12 @@ def newer_group(sources, target, missing='error'): ...@@ -80,9 +83,12 @@ def newer_group(sources, target, missing='error'):
elif missing == 'ignore': # missing source dropped from elif missing == 'ignore': # missing source dropped from
continue # target's dependency list continue # target's dependency list
elif missing == 'newer': # missing source means target is elif missing == 'newer': # missing source means target is
return True # out-of-date return 1 # out-of-date
if os.stat(source).st_mtime > target_mtime: source_mtime = os.stat(source)[ST_MTIME]
return True if source_mtime > target_mtime:
return 1
else:
return 0
return False # newer_group ()
...@@ -4,7 +4,7 @@ Utility functions for manipulating directories and directory trees.""" ...@@ -4,7 +4,7 @@ Utility functions for manipulating directories and directory trees."""
__revision__ = "$Id$" __revision__ = "$Id$"
import os import os, sys
from distutils.errors import DistutilsFileError, DistutilsInternalError from distutils.errors import DistutilsFileError, DistutilsInternalError
from distutils import log from distutils import log
......
...@@ -7,15 +7,13 @@ being built/installed/distributed. ...@@ -7,15 +7,13 @@ being built/installed/distributed.
__revision__ = "$Id$" __revision__ = "$Id$"
import sys, os, re import sys, os, re
from email import message_from_file
try: try:
import warnings import warnings
except ImportError: except ImportError:
warnings = None warnings = None
from distutils.errors import (DistutilsOptionError, DistutilsArgError, from distutils.errors import *
DistutilsModuleError, DistutilsClassError)
from distutils.fancy_getopt import FancyGetopt, translate_longopt from distutils.fancy_getopt import FancyGetopt, translate_longopt
from distutils.util import check_environ, strtobool, rfc822_escape from distutils.util import check_environ, strtobool, rfc822_escape
from distutils import log from distutils import log
...@@ -55,9 +53,7 @@ class Distribution: ...@@ -55,9 +53,7 @@ class Distribution:
('quiet', 'q', "run quietly (turns verbosity off)"), ('quiet', 'q', "run quietly (turns verbosity off)"),
('dry-run', 'n', "don't actually do anything"), ('dry-run', 'n', "don't actually do anything"),
('help', 'h', "show detailed help message"), ('help', 'h', "show detailed help message"),
('no-user-cfg', None, ]
'ignore pydistutils.cfg in your home directory'),
]
# 'common_usage' is a short (2-3 line) string describing the common # 'common_usage' is a short (2-3 line) string describing the common
# usage of the setup script. # usage of the setup script.
...@@ -264,22 +260,6 @@ Common commands: (see '--help-commands' for more) ...@@ -264,22 +260,6 @@ Common commands: (see '--help-commands' for more)
else: else:
sys.stderr.write(msg + "\n") sys.stderr.write(msg + "\n")
# no-user-cfg is handled before other command line args
# because other args override the config files, and this
# one is needed before we can load the config files.
# If attrs['script_args'] wasn't passed, assume false.
#
# This also make sure we just look at the global options
self.want_user_cfg = True
if self.script_args is not None:
for arg in self.script_args:
if not arg.startswith('-'):
break
if arg == '--no-user-cfg':
self.want_user_cfg = False
break
self.finalize_options() self.finalize_options()
def get_option_dict(self, command): def get_option_dict(self, command):
...@@ -331,10 +311,7 @@ Common commands: (see '--help-commands' for more) ...@@ -331,10 +311,7 @@ Common commands: (see '--help-commands' for more)
Distutils installation directory (ie. where the top-level Distutils installation directory (ie. where the top-level
Distutils __inst__.py file lives), a file in the user's home Distutils __inst__.py file lives), a file in the user's home
directory named .pydistutils.cfg on Unix and pydistutils.cfg directory named .pydistutils.cfg on Unix and pydistutils.cfg
on Windows/Mac; and setup.cfg in the current directory. on Windows/Mac, and setup.cfg in the current directory.
The file in the user's home directory can be disabled with the
--no-user-cfg option.
""" """
files = [] files = []
check_environ() check_environ()
...@@ -354,19 +331,15 @@ Common commands: (see '--help-commands' for more) ...@@ -354,19 +331,15 @@ Common commands: (see '--help-commands' for more)
user_filename = "pydistutils.cfg" user_filename = "pydistutils.cfg"
# And look for the user config file # And look for the user config file
if self.want_user_cfg: user_file = os.path.join(os.path.expanduser('~'), user_filename)
user_file = os.path.join(os.path.expanduser('~'), user_filename) if os.path.isfile(user_file):
if os.path.isfile(user_file): files.append(user_file)
files.append(user_file)
# All platforms support local setup.cfg # All platforms support local setup.cfg
local_file = "setup.cfg" local_file = "setup.cfg"
if os.path.isfile(local_file): if os.path.isfile(local_file):
files.append(local_file) files.append(local_file)
if DEBUG:
self.announce("using config files: %s" % ', '.join(files))
return files return files
def parse_config_files(self, filenames=None): def parse_config_files(self, filenames=None):
...@@ -1016,80 +989,25 @@ class DistributionMetadata: ...@@ -1016,80 +989,25 @@ class DistributionMetadata:
"provides", "requires", "obsoletes", "provides", "requires", "obsoletes",
) )
def __init__(self, path=None): def __init__ (self):
if path is not None: self.name = None
self.read_pkg_file(open(path)) self.version = None
else: self.author = None
self.name = None self.author_email = None
self.version = None
self.author = None
self.author_email = None
self.maintainer = None
self.maintainer_email = None
self.url = None
self.license = None
self.description = None
self.long_description = None
self.keywords = None
self.platforms = None
self.classifiers = None
self.download_url = None
# PEP 314
self.provides = None
self.requires = None
self.obsoletes = None
def read_pkg_file(self, file):
"""Reads the metadata values from a file object."""
msg = message_from_file(file)
def _read_field(name):
value = msg[name]
if value == 'UNKNOWN':
return None
return value
def _read_list(name):
values = msg.get_all(name, None)
if values == []:
return None
return values
metadata_version = msg['metadata-version']
self.name = _read_field('name')
self.version = _read_field('version')
self.description = _read_field('summary')
# we are filling author only.
self.author = _read_field('author')
self.maintainer = None self.maintainer = None
self.author_email = _read_field('author-email')
self.maintainer_email = None self.maintainer_email = None
self.url = _read_field('home-page') self.url = None
self.license = _read_field('license') self.license = None
self.description = None
if 'download-url' in msg: self.long_description = None
self.download_url = _read_field('download-url') self.keywords = None
else: self.platforms = None
self.download_url = None self.classifiers = None
self.download_url = None
self.long_description = _read_field('description') # PEP 314
self.description = _read_field('summary') self.provides = None
self.requires = None
if 'keywords' in msg: self.obsoletes = None
self.keywords = _read_field('keywords').split(',')
self.platforms = _read_list('platform')
self.classifiers = _read_list('classifier')
# PEP 314 - these fields only exist in 1.1
if metadata_version == '1.1':
self.requires = _read_list('requires')
self.provides = _read_list('provides')
self.obsoletes = _read_list('obsoletes')
else:
self.requires = None
self.provides = None
self.obsoletes = None
def write_pkg_info(self, base_dir): def write_pkg_info(self, base_dir):
"""Write the PKG-INFO file into the release tree. """Write the PKG-INFO file into the release tree.
......
...@@ -21,13 +21,12 @@ handles the EMX port of the GNU C compiler to OS/2. ...@@ -21,13 +21,12 @@ handles the EMX port of the GNU C compiler to OS/2.
__revision__ = "$Id$" __revision__ = "$Id$"
import os, sys, copy import os,sys,copy
from warnings import warn from distutils.ccompiler import gen_preprocess_options, gen_lib_options
from distutils.unixccompiler import UnixCCompiler from distutils.unixccompiler import UnixCCompiler
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.errors import DistutilsExecError, CompileError, UnknownFileError from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
from distutils.util import get_compiler_versions from distutils import log
class EMXCCompiler (UnixCCompiler): class EMXCCompiler (UnixCCompiler):
...@@ -56,8 +55,8 @@ class EMXCCompiler (UnixCCompiler): ...@@ -56,8 +55,8 @@ class EMXCCompiler (UnixCCompiler):
("Reason: %s." % details) + ("Reason: %s." % details) +
"Compiling may fail because of undefined preprocessor macros.") "Compiling may fail because of undefined preprocessor macros.")
gcc_version, ld_version, dllwrap_version = get_compiler_versions() (self.gcc_version, self.ld_version) = \
self.gcc_version, self.ld_version = gcc_version, ld_version get_versions()
self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" % self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" %
(self.gcc_version, (self.gcc_version,
self.ld_version) ) self.ld_version) )
...@@ -292,11 +291,23 @@ def get_versions(): ...@@ -292,11 +291,23 @@ def get_versions():
""" Try to find out the versions of gcc and ld. """ Try to find out the versions of gcc and ld.
If not possible it returns None for it. If not possible it returns None for it.
""" """
warn("'distutils.emxccompiler.get_versions' is deprecated " from distutils.version import StrictVersion
"use 'distutils.util.get_compiler_versions' instead", from distutils.spawn import find_executable
DeprecationWarning) import re
gcc_exe = find_executable('gcc')
if gcc_exe:
out = os.popen(gcc_exe + ' -dumpversion','r')
out_string = out.read()
out.close()
result = re.search('(\d+\.\d+\.\d+)', out_string, re.ASCII)
if result:
gcc_version = StrictVersion(result.group(1))
else:
gcc_version = None
else:
gcc_version = None
# EMX ld has no way of reporting version number, and we use GCC # EMX ld has no way of reporting version number, and we use GCC
# anyway - so we can link OMF DLLs # anyway - so we can link OMF DLLs
gcc_version, ld_version, dllwrap_version = get_compiler_versions() ld_version = None
return gcc_version, None return (gcc_version, ld_version)
...@@ -10,79 +10,90 @@ symbols whose names start with "Distutils" and end with "Error".""" ...@@ -10,79 +10,90 @@ symbols whose names start with "Distutils" and end with "Error"."""
__revision__ = "$Id$" __revision__ = "$Id$"
class DistutilsError(Exception): class DistutilsError (Exception):
"""The root of all Distutils evil.""" """The root of all Distutils evil."""
pass
class DistutilsModuleError(DistutilsError): class DistutilsModuleError (DistutilsError):
"""Unable to load an expected module, or to find an expected class """Unable to load an expected module, or to find an expected class
within some module (in particular, command modules and classes).""" within some module (in particular, command modules and classes)."""
pass
class DistutilsClassError(DistutilsError): class DistutilsClassError (DistutilsError):
"""Some command class (or possibly distribution class, if anyone """Some command class (or possibly distribution class, if anyone
feels a need to subclass Distribution) is found not to be holding feels a need to subclass Distribution) is found not to be holding
up its end of the bargain, ie. implementing some part of the up its end of the bargain, ie. implementing some part of the
"command "interface.""" "command "interface."""
pass
class DistutilsGetoptError(DistutilsError): class DistutilsGetoptError (DistutilsError):
"""The option table provided to 'fancy_getopt()' is bogus.""" """The option table provided to 'fancy_getopt()' is bogus."""
pass
class DistutilsArgError(DistutilsError): class DistutilsArgError (DistutilsError):
"""Raised by fancy_getopt in response to getopt.error -- ie. an """Raised by fancy_getopt in response to getopt.error -- ie. an
error in the command line usage.""" error in the command line usage."""
pass
class DistutilsFileError(DistutilsError): class DistutilsFileError (DistutilsError):
"""Any problems in the filesystem: expected file not found, etc. """Any problems in the filesystem: expected file not found, etc.
Typically this is for problems that we detect before IOError or Typically this is for problems that we detect before IOError or
OSError could be raised.""" OSError could be raised."""
pass
class DistutilsOptionError(DistutilsError): class DistutilsOptionError (DistutilsError):
"""Syntactic/semantic errors in command options, such as use of """Syntactic/semantic errors in command options, such as use of
mutually conflicting options, or inconsistent options, mutually conflicting options, or inconsistent options,
badly-spelled values, etc. No distinction is made between option badly-spelled values, etc. No distinction is made between option
values originating in the setup script, the command line, config values originating in the setup script, the command line, config
files, or what-have-you -- but if we *know* something originated in files, or what-have-you -- but if we *know* something originated in
the setup script, we'll raise DistutilsSetupError instead.""" the setup script, we'll raise DistutilsSetupError instead."""
pass
class DistutilsSetupError(DistutilsError): class DistutilsSetupError (DistutilsError):
"""For errors that can be definitely blamed on the setup script, """For errors that can be definitely blamed on the setup script,
such as invalid keyword arguments to 'setup()'.""" such as invalid keyword arguments to 'setup()'."""
pass
class DistutilsPlatformError(DistutilsError): class DistutilsPlatformError (DistutilsError):
"""We don't know how to do something on the current platform (but """We don't know how to do something on the current platform (but
we do know how to do it on some platform) -- eg. trying to compile we do know how to do it on some platform) -- eg. trying to compile
C files on a platform not supported by a CCompiler subclass.""" C files on a platform not supported by a CCompiler subclass."""
pass
class DistutilsExecError(DistutilsError): class DistutilsExecError (DistutilsError):
"""Any problems executing an external program (such as the C """Any problems executing an external program (such as the C
compiler, when compiling C files).""" compiler, when compiling C files)."""
pass
class DistutilsInternalError(DistutilsError): class DistutilsInternalError (DistutilsError):
"""Internal inconsistencies or impossibilities (obviously, this """Internal inconsistencies or impossibilities (obviously, this
should never be seen if the code is working!).""" should never be seen if the code is working!)."""
pass
class DistutilsTemplateError(DistutilsError): class DistutilsTemplateError (DistutilsError):
"""Syntax error in a file list template.""" """Syntax error in a file list template."""
class DistutilsByteCompileError(DistutilsError): class DistutilsByteCompileError(DistutilsError):
"""Byte compile error.""" """Byte compile error."""
# Exception classes used by the CCompiler implementation classes # Exception classes used by the CCompiler implementation classes
class CCompilerError(Exception): class CCompilerError (Exception):
"""Some compile/link operation failed.""" """Some compile/link operation failed."""
class PreprocessError(CCompilerError): class PreprocessError (CCompilerError):
"""Failure to preprocess one or more C/C++ files.""" """Failure to preprocess one or more C/C++ files."""
class CompileError(CCompilerError): class CompileError (CCompilerError):
"""Failure to compile one or more C/C++ source files.""" """Failure to compile one or more C/C++ source files."""
class LibError(CCompilerError): class LibError (CCompilerError):
"""Failure to create a static library from one or more C/C++ object """Failure to create a static library from one or more C/C++ object
files.""" files."""
class LinkError(CCompilerError): class LinkError (CCompilerError):
"""Failure to link one or more C/C++ object files into an executable """Failure to link one or more C/C++ object files into an executable
or shared library file.""" or shared library file."""
class UnknownFileError(CCompilerError): class UnknownFileError (CCompilerError):
"""Attempt to process an unknown file type.""" """Attempt to process an unknown file type."""
...@@ -6,6 +6,7 @@ modules in setup scripts.""" ...@@ -6,6 +6,7 @@ modules in setup scripts."""
__revision__ = "$Id$" __revision__ = "$Id$"
import os import os
import sys
import warnings import warnings
# This class is really only used by the "build_ext" command, so it might # This class is really only used by the "build_ext" command, so it might
...@@ -134,17 +135,14 @@ class Extension: ...@@ -134,17 +135,14 @@ class Extension:
def read_setup_file(filename): def read_setup_file(filename):
"""Reads a Setup file and returns Extension instances.""" """Reads a Setup file and returns Extension instances."""
warnings.warn('distutils.extensions.read_setup_file is deprecated. ' from distutils.sysconfig import (parse_makefile, expand_makefile_vars,
'It will be removed in the next Python release.')
_sysconfig = __import__('sysconfig')
from distutils.sysconfig import (expand_makefile_vars,
_variable_rx) _variable_rx)
from distutils.text_file import TextFile from distutils.text_file import TextFile
from distutils.util import split_quoted from distutils.util import split_quoted
# First pass over the file to gather "VAR = VALUE" assignments. # First pass over the file to gather "VAR = VALUE" assignments.
vars = _sysconfig._parse_makefile(filename) vars = parse_makefile(filename)
# Second pass to gobble up the real content: lines of the form # Second pass to gobble up the real content: lines of the form
# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...] # <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
...@@ -164,10 +162,7 @@ def read_setup_file(filename): ...@@ -164,10 +162,7 @@ def read_setup_file(filename):
file.warn("'%s' lines not handled yet" % line) file.warn("'%s' lines not handled yet" % line)
continue continue
with warnings.catch_warnings(): line = expand_makefile_vars(line, vars)
warnings.simplefilter("ignore")
line = expand_makefile_vars(line, vars)
words = split_quoted(line) words = split_quoted(line)
# NB. this parses a slightly different syntax than the old # NB. this parses a slightly different syntax than the old
......
...@@ -10,11 +10,9 @@ additional features: ...@@ -10,11 +10,9 @@ additional features:
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, string, re
import string
import re
import getopt import getopt
from distutils.errors import DistutilsGetoptError, DistutilsArgError from distutils.errors import *
# Much like command_re in distutils.core, this is close to but not quite # Much like command_re in distutils.core, this is close to but not quite
# the same as a Python NAME -- except, in the spirit of most GNU # the same as a Python NAME -- except, in the spirit of most GNU
...@@ -446,3 +444,16 @@ class OptionDummy: ...@@ -446,3 +444,16 @@ class OptionDummy:
'options' will be initialized to None.""" 'options' will be initialized to None."""
for opt in options: for opt in options:
setattr(self, opt, None) setattr(self, opt, None)
if __name__ == "__main__":
text = """\
Tra-la-la, supercalifragilisticexpialidocious.
How *do* you spell that odd word, anyways?
(Someone ask Mary -- she'll know [or she'll
say, "How should I know?"].)"""
for w in (10, 20, 30, 40):
print("width: %d" % w)
print("\n".join(wrap_text(text, w)))
print()
...@@ -10,18 +10,17 @@ from distutils.errors import DistutilsFileError ...@@ -10,18 +10,17 @@ from distutils.errors import DistutilsFileError
from distutils import log from distutils import log
# for generating verbose output in 'copy_file()' # for generating verbose output in 'copy_file()'
_copy_action = {None: 'copying', _copy_action = { None: 'copying',
'hard': 'hard linking', 'hard': 'hard linking',
'sym': 'symbolically linking'} 'sym': 'symbolically linking' }
def _copy_file_contents(src, dst, buffer_size=16*1024): def _copy_file_contents(src, dst, buffer_size=16*1024):
"""Copy the file 'src' to 'dst'. """Copy the file 'src' to 'dst'; both must be filenames. Any error
opening either file, reading from 'src', or writing to 'dst', raises
Both must be filenames. Any error opening either file, reading from DistutilsFileError. Data is read/written in chunks of 'buffer_size'
'src', or writing to 'dst', raises DistutilsFileError. Data is bytes (default 16k). No attempt is made to handle anything apart from
read/written in chunks of 'buffer_size' bytes (default 16k). No attempt regular files.
is made to handle anything apart from regular files.
""" """
# Stolen from shutil module in the standard library, but with # Stolen from shutil module in the standard library, but with
# custom error-handling added. # custom error-handling added.
...@@ -69,16 +68,15 @@ def _copy_file_contents(src, dst, buffer_size=16*1024): ...@@ -69,16 +68,15 @@ def _copy_file_contents(src, dst, buffer_size=16*1024):
def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0, def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
link=None, verbose=1, dry_run=0): link=None, verbose=1, dry_run=0):
"""Copy a file 'src' to 'dst'. """Copy a file 'src' to 'dst'. If 'dst' is a directory, then 'src' is
copied there with the same name; otherwise, it must be a filename. (If
If 'dst' is a directory, then 'src' is copied there with the same name; the file exists, it will be ruthlessly clobbered.) If 'preserve_mode'
otherwise, it must be a filename. (If the file exists, it will be is true (the default), the file's mode (type and permission bits, or
ruthlessly clobbered.) If 'preserve_mode' is true (the default), whatever is analogous on the current platform) is copied. If
the file's mode (type and permission bits, or whatever is analogous on 'preserve_times' is true (the default), the last-modified and
the current platform) is copied. If 'preserve_times' is true (the last-access times are copied as well. If 'update' is true, 'src' will
default), the last-modified and last-access times are copied as well. only be copied if 'dst' does not exist, or if 'dst' does exist but is
If 'update' is true, 'src' will only be copied if 'dst' does not exist, older than 'src'.
or if 'dst' does exist but is older than 'src'.
'link' allows you to make hard links (os.link) or symbolic links 'link' allows you to make hard links (os.link) or symbolic links
(os.symlink) instead of copying: set it to "hard" or "sym"; if it is (os.symlink) instead of copying: set it to "hard" or "sym"; if it is
...@@ -132,6 +130,15 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0, ...@@ -132,6 +130,15 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
if dry_run: if dry_run:
return (dst, 1) return (dst, 1)
# On Mac OS, use the native file copy routine
if os.name == 'mac':
import macostools
try:
macostools.copy(src, dst, 0, preserve_times)
except os.error as exc:
raise DistutilsFileError(
"could not copy '%s' to '%s': %s" % (src, dst, exc.args[-1]))
# If linking (hard or symbolic), use the appropriate system call # If linking (hard or symbolic), use the appropriate system call
# (Unix only, of course, but that's the caller's responsibility) # (Unix only, of course, but that's the caller's responsibility)
elif link == 'hard': elif link == 'hard':
...@@ -159,12 +166,13 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0, ...@@ -159,12 +166,13 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
# XXX I suspect this is Unix-specific -- need porting help! # XXX I suspect this is Unix-specific -- need porting help!
def move_file(src, dst, verbose=1, dry_run=0): def move_file (src, dst,
"""Move a file 'src' to 'dst'. verbose=1,
dry_run=0):
If 'dst' is a directory, the file will be moved into it with the same """Move a file 'src' to 'dst'. If 'dst' is a directory, the file will
name; otherwise, 'src' is just renamed to 'dst'. Return the new be moved into it with the same name; otherwise, 'src' is just renamed
full name of the file. to 'dst'. Return the new full name of the file.
Handles cross-device moves on Unix using 'copy_file()'. What about Handles cross-device moves on Unix using 'copy_file()'. What about
other systems??? other systems???
...@@ -221,7 +229,7 @@ def move_file(src, dst, verbose=1, dry_run=0): ...@@ -221,7 +229,7 @@ def move_file(src, dst, verbose=1, dry_run=0):
return dst return dst
def write_file(filename, contents): def write_file (filename, contents):
"""Create a file with the specified name and write 'contents' (a """Create a file with the specified name and write 'contents' (a
sequence of strings without line terminators) to it. sequence of strings without line terminators) to it.
""" """
......
...@@ -108,7 +108,7 @@ class FileList: ...@@ -108,7 +108,7 @@ class FileList:
# defined: it's the first word of the line. Which of the other # defined: it's the first word of the line. Which of the other
# three are defined depends on the action; it'll be either # three are defined depends on the action; it'll be either
# patterns, (dir and patterns), or (dir_pattern). # patterns, (dir and patterns), or (dir_pattern).
action, patterns, dir, dir_pattern = self._parse_template_line(line) (action, patterns, dir, dir_pattern) = self._parse_template_line(line)
# OK, now we know that the action is valid and we have the # OK, now we know that the action is valid and we have the
# right number of words on the line for that action -- so we # right number of words on the line for that action -- so we
...@@ -175,15 +175,15 @@ class FileList: ...@@ -175,15 +175,15 @@ class FileList:
raise DistutilsInternalError( raise DistutilsInternalError(
"this cannot happen: invalid action '%s'" % action) "this cannot happen: invalid action '%s'" % action)
# -- Filtering/selection methods ----------------------------------- # -- Filtering/selection methods -----------------------------------
def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
"""Select strings (presumably filenames) from 'self.files' that """Select strings (presumably filenames) from 'self.files' that
match 'pattern', a Unix-style wildcard (glob) pattern. match 'pattern', a Unix-style wildcard (glob) pattern. Patterns
are not quite the same as implemented by the 'fnmatch' module: '*'
Patterns are not quite the same as implemented by the 'fnmatch' and '?' match non-special characters, where "special" is platform-
module: '*' and '?' match non-special characters, where "special" dependent: slash on Unix; colon, slash, and backslash on
is platform-dependent: slash on Unix; colon, slash, and backslash on
DOS/Windows; and colon on Mac OS. DOS/Windows; and colon on Mac OS.
If 'anchor' is true (the default), then the pattern match is more If 'anchor' is true (the default), then the pattern match is more
...@@ -220,13 +220,13 @@ class FileList: ...@@ -220,13 +220,13 @@ class FileList:
return files_found return files_found
def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): def exclude_pattern (self, pattern,
anchor=1, prefix=None, is_regex=0):
"""Remove strings (presumably filenames) from 'files' that match """Remove strings (presumably filenames) from 'files' that match
'pattern'. 'pattern'. Other parameters are the same as for
'include_pattern()', above.
Other parameters are the same as for 'include_pattern()', above. The list 'self.files' is modified in place.
The list 'self.files' is modified in place. Return 1 if files are Return True if files are found, False otherwise.
found.
""" """
files_found = False files_found = False
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
...@@ -275,11 +275,10 @@ def findall(dir=os.curdir): ...@@ -275,11 +275,10 @@ def findall(dir=os.curdir):
def glob_to_re(pattern): def glob_to_re(pattern):
"""Translate a shell-like glob pattern to a regular expression. """Translate a shell-like glob pattern to a regular expression; return
a string containing the regex. Differs from 'fnmatch.translate()' in
Return a string containing the regex. Differs from that '*' does not match "special characters" (which are
'fnmatch.translate()' in that '*' does not match "special characters" platform-specific).
(which are platform-specific).
""" """
pattern_re = fnmatch.translate(pattern) pattern_re = fnmatch.translate(pattern)
...@@ -297,9 +296,7 @@ def glob_to_re(pattern): ...@@ -297,9 +296,7 @@ def glob_to_re(pattern):
def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0): def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
"""Translate a shell-like wildcard pattern to a compiled regular """Translate a shell-like wildcard pattern to a compiled regular
expression. expression. Return the compiled regex. If 'is_regex' true,
Return the compiled regex. If 'is_regex' true,
then 'pattern' is directly compiled to a regex (if it's a string) then 'pattern' is directly compiled to a regex (if it's a string)
or just returned as-is (assumes it's a regex object). or just returned as-is (assumes it's a regex object).
""" """
...@@ -317,7 +314,7 @@ def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0): ...@@ -317,7 +314,7 @@ def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
if prefix is not None: if prefix is not None:
# ditch end of pattern character # ditch end of pattern character
empty_pattern = glob_to_re('') empty_pattern = glob_to_re('')
prefix_re = glob_to_re(prefix)[:-len(empty_pattern)] prefix_re = (glob_to_re(prefix))[:-len(empty_pattern)]
pattern_re = "^" + os.path.join(prefix_re, ".*" + pattern_re) pattern_re = "^" + os.path.join(prefix_re, ".*" + pattern_re)
else: # no prefix -- respect anchor flag else: # no prefix -- respect anchor flag
if anchor: if anchor:
......
...@@ -19,9 +19,10 @@ import subprocess ...@@ -19,9 +19,10 @@ import subprocess
import sys import sys
import re import re
from distutils.errors import (DistutilsExecError, DistutilsPlatformError, from distutils.errors import DistutilsExecError, DistutilsPlatformError, \
CompileError, LibError, LinkError) CompileError, LibError, LinkError
from distutils.ccompiler import CCompiler, gen_lib_options from distutils.ccompiler import CCompiler, gen_preprocess_options, \
gen_lib_options
from distutils import log from distutils import log
from distutils.util import get_platform from distutils.util import get_platform
......
...@@ -10,12 +10,12 @@ for the Microsoft Visual Studio. ...@@ -10,12 +10,12 @@ for the Microsoft Visual Studio.
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, os
import os from distutils.errors import \
DistutilsExecError, DistutilsPlatformError, \
from distutils.errors import (DistutilsExecError, DistutilsPlatformError, CompileError, LibError, LinkError
CompileError, LibError, LinkError) from distutils.ccompiler import \
from distutils.ccompiler import CCompiler, gen_lib_options CCompiler, gen_preprocess_options, gen_lib_options
from distutils import log from distutils import log
_can_read_reg = False _can_read_reg = False
...@@ -124,7 +124,7 @@ class MacroExpander: ...@@ -124,7 +124,7 @@ class MacroExpander:
self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1") self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
else: else:
self.set_macro("FrameworkSDKDir", net, "sdkinstallroot") self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
except KeyError: except KeyError as exc: #
raise DistutilsPlatformError( raise DistutilsPlatformError(
"""Python was built with Visual Studio 2003; """Python was built with Visual Studio 2003;
extensions must be built with a compiler than can generate compatible binaries. extensions must be built with a compiler than can generate compatible binaries.
......
...@@ -7,9 +7,6 @@ available. ...@@ -7,9 +7,6 @@ available.
Written by: Fred L. Drake, Jr. Written by: Fred L. Drake, Jr.
Email: <fdrake@acm.org> Email: <fdrake@acm.org>
**This module has been moved out of Distutils and will be removed from
Python in the next version (3.3)**
""" """
__revision__ = "$Id$" __revision__ = "$Id$"
...@@ -17,45 +14,51 @@ __revision__ = "$Id$" ...@@ -17,45 +14,51 @@ __revision__ = "$Id$"
import io import io
import os import os
import re import re
from warnings import warn import sys
from distutils.errors import DistutilsPlatformError from .errors import DistutilsPlatformError
# importing sysconfig from Lib # These are needed in a couple of spots, so just compute them once.
# to avoid this module to shadow it PREFIX = os.path.normpath(sys.prefix)
_sysconfig = __import__('sysconfig') EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
# names defined here to keep backward compatibility # Path to the base directory of the project. On Windows the binary may
# for APIs that were relocated # live in project/PCBuild9. If we're dealing with an x64 Windows build,
get_python_version = _sysconfig.get_python_version # it'll live in project/PCbuild/amd64.
get_config_h_filename = _sysconfig.get_config_h_filename project_base = os.path.dirname(os.path.abspath(sys.executable))
parse_config_h = _sysconfig.parse_config_h if os.name == "nt" and "pcbuild" in project_base[-8:].lower():
get_config_vars = _sysconfig.get_config_vars project_base = os.path.abspath(os.path.join(project_base, os.path.pardir))
get_config_var = _sysconfig.get_config_var # PC/VS7.1
from distutils.ccompiler import customize_compiler if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower():
project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
_DEPRECATION_MSG = ("distutils.sysconfig.%s is deprecated. " os.path.pardir))
"Use the APIs provided by the sysconfig module instead") # PC/AMD64
if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower():
def _get_project_base(): project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
return _sysconfig._PROJECT_BASE os.path.pardir))
project_base = _get_project_base() # python_build: (Boolean) if true, we're either building Python or
# building an extension with an un-installed Python, so we use
class _DeprecatedBool(int): # different (hard-wired) directories.
def __nonzero__(self): # Setup.local is available for Makefile builds including VPATH builds,
warn(_DEPRECATION_MSG % 'get_python_version', DeprecationWarning) # Setup.dist is available on Windows
return super(_DeprecatedBool, self).__nonzero__()
def _python_build(): def _python_build():
return _DeprecatedBool(_sysconfig.is_python_build()) for fn in ("Setup.dist", "Setup.local"):
if os.path.isfile(os.path.join(project_base, "Modules", fn)):
return True
return False
python_build = _python_build() python_build = _python_build()
def get_python_inc(plat_specific=0, prefix=None): def get_python_version():
"""This function is deprecated. """Return a string containing the major and minor Python version,
leaving off the patchlevel. Sample return values could be '1.5'
or '2.2'.
"""
return sys.version[:3]
Return the directory containing installed Python header files. def get_python_inc(plat_specific=0, prefix=None):
"""Return the directory containing installed Python header files.
If 'plat_specific' is false (the default), this is the path to the If 'plat_specific' is false (the default), this is the path to the
non-platform-specific header files, i.e. Python.h and so on; non-platform-specific header files, i.e. Python.h and so on;
...@@ -65,22 +68,39 @@ def get_python_inc(plat_specific=0, prefix=None): ...@@ -65,22 +68,39 @@ def get_python_inc(plat_specific=0, prefix=None):
If 'prefix' is supplied, use it instead of sys.prefix or If 'prefix' is supplied, use it instead of sys.prefix or
sys.exec_prefix -- i.e., ignore 'plat_specific'. sys.exec_prefix -- i.e., ignore 'plat_specific'.
""" """
warn(_DEPRECATION_MSG % 'get_python_inc', DeprecationWarning) if prefix is None:
get_path = _sysconfig.get_path prefix = plat_specific and EXEC_PREFIX or PREFIX
if os.name == "posix":
if prefix is not None: if python_build:
vars = {'base': prefix} # Assume the executable is in the build directory. The
return get_path('include', vars=vars) # pyconfig.h file should be in the same directory. Since
# the build directory may not be the source directory, we
if not plat_specific: # must use "srcdir" from the makefile to find the "Include"
return get_path('include') # directory.
base = os.path.dirname(os.path.abspath(sys.executable))
if plat_specific:
return base
else:
incdir = os.path.join(get_config_var('srcdir'), 'Include')
return os.path.normpath(incdir)
return os.path.join(prefix, "include", "python" + get_python_version())
elif os.name == "nt":
return os.path.join(prefix, "include")
elif os.name == "mac":
if plat_specific:
return os.path.join(prefix, "Mac", "Include")
else:
return os.path.join(prefix, "Include")
elif os.name == "os2":
return os.path.join(prefix, "Include")
else: else:
return get_path('platinclude') raise DistutilsPlatformError(
"I don't know where Python installs its C header files "
"on platform '%s'" % os.name)
def get_python_lib(plat_specific=False, standard_lib=False, prefix=None):
"""This function is deprecated.
Return the directory containing the Python library (standard or def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
"""Return the directory containing the Python library (standard or
site additions). site additions).
If 'plat_specific' is true, return the directory containing If 'plat_specific' is true, return the directory containing
...@@ -93,33 +113,149 @@ def get_python_lib(plat_specific=False, standard_lib=False, prefix=None): ...@@ -93,33 +113,149 @@ def get_python_lib(plat_specific=False, standard_lib=False, prefix=None):
If 'prefix' is supplied, use it instead of sys.prefix or If 'prefix' is supplied, use it instead of sys.prefix or
sys.exec_prefix -- i.e., ignore 'plat_specific'. sys.exec_prefix -- i.e., ignore 'plat_specific'.
""" """
warn(_DEPRECATION_MSG % 'get_python_lib', DeprecationWarning) if prefix is None:
vars = {} prefix = plat_specific and EXEC_PREFIX or PREFIX
get_path = _sysconfig.get_path
if prefix is not None: if os.name == "posix":
if plat_specific: libpython = os.path.join(prefix,
vars['platbase'] = prefix "lib", "python" + get_python_version())
if standard_lib:
return libpython
else: else:
vars['base'] = prefix return os.path.join(libpython, "site-packages")
if standard_lib: elif os.name == "nt":
if standard_lib:
return os.path.join(prefix, "Lib")
else:
if get_python_version() < "2.2":
return prefix
else:
return os.path.join(prefix, "Lib", "site-packages")
elif os.name == "mac":
if plat_specific: if plat_specific:
return get_path('platstdlib', vars=vars) if standard_lib:
return os.path.join(prefix, "Lib", "lib-dynload")
else:
return os.path.join(prefix, "Lib", "site-packages")
else:
if standard_lib:
return os.path.join(prefix, "Lib")
else:
return os.path.join(prefix, "Lib", "site-packages")
elif os.name == "os2":
if standard_lib:
return os.path.join(prefix, "Lib")
else: else:
return get_path('stdlib', vars=vars) return os.path.join(prefix, "Lib", "site-packages")
else: else:
if plat_specific: raise DistutilsPlatformError(
return get_path('platlib', vars=vars) "I don't know where Python installs its library "
"on platform '%s'" % os.name)
def customize_compiler(compiler):
"""Do any platform-specific customization of a CCompiler instance.
Mainly needed on Unix, so we can plug in the information that
varies across Unices and is stored in Python's Makefile.
"""
if compiler.compiler_type == "unix":
(cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS')
if 'CC' in os.environ:
cc = os.environ['CC']
if 'CXX' in os.environ:
cxx = os.environ['CXX']
if 'LDSHARED' in os.environ:
ldshared = os.environ['LDSHARED']
if 'CPP' in os.environ:
cpp = os.environ['CPP']
else:
cpp = cc + " -E" # not always
if 'LDFLAGS' in os.environ:
ldshared = ldshared + ' ' + os.environ['LDFLAGS']
if 'CFLAGS' in os.environ:
cflags = opt + ' ' + os.environ['CFLAGS']
ldshared = ldshared + ' ' + os.environ['CFLAGS']
if 'CPPFLAGS' in os.environ:
cpp = cpp + ' ' + os.environ['CPPFLAGS']
cflags = cflags + ' ' + os.environ['CPPFLAGS']
ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
if 'AR' in os.environ:
ar = os.environ['AR']
if 'ARFLAGS' in os.environ:
archiver = ar + ' ' + os.environ['ARFLAGS']
else: else:
return get_path('purelib', vars=vars) archiver = ar + ' ' + ar_flags
cc_cmd = cc + ' ' + cflags
compiler.set_executables(
preprocessor=cpp,
compiler=cc_cmd,
compiler_so=cc_cmd + ' ' + ccshared,
compiler_cxx=cxx,
linker_so=ldshared,
linker_exe=cc,
archiver=archiver)
compiler.shared_lib_extension = so_ext
def get_config_h_filename():
"""Return full pathname of installed pyconfig.h file."""
if python_build:
if os.name == "nt":
inc_dir = os.path.join(project_base, "PC")
else:
inc_dir = project_base
else:
inc_dir = get_python_inc(plat_specific=1)
if get_python_version() < '2.2':
config_h = 'config.h'
else:
# The name of the config.h file changed in 2.2
config_h = 'pyconfig.h'
return os.path.join(inc_dir, config_h)
def get_makefile_filename(): def get_makefile_filename():
"""This function is deprecated. """Return full pathname of installed Makefile from the Python build."""
if python_build:
return os.path.join(os.path.dirname(sys.executable), "Makefile")
lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
return os.path.join(lib_dir, "config", "Makefile")
def parse_config_h(fp, g=None):
"""Parse a config.h-style file.
Return full pathname of installed Makefile from the Python build. A dictionary containing name/value pairs is returned. If an
optional dictionary is passed in as the second argument, it is
used instead of a new dictionary.
""" """
if g is None:
g = {}
define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
#
while True:
line = fp.readline()
if not line:
break
m = define_rx.match(line)
if m:
n, v = m.group(1, 2)
try: v = int(v)
except ValueError: pass
g[n] = v
else:
m = undef_rx.match(line)
if m:
g[m.group(1)] = 0
return g
warn(_DEPRECATION_MSG % 'get_makefile_filename', DeprecationWarning)
return _sysconfig._get_makefile_filename()
# Regexes needed for parsing Makefile (and similar syntaxes, # Regexes needed for parsing Makefile (and similar syntaxes,
# like old-style Setup files). # like old-style Setup files).
...@@ -128,29 +264,91 @@ _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") ...@@ -128,29 +264,91 @@ _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
def parse_makefile(fn, g=None): def parse_makefile(fn, g=None):
"""This function is deprecated. """Parse a Makefile-style file.
Parse a Makefile-style file.
A dictionary containing name/value pairs is returned. If an A dictionary containing name/value pairs is returned. If an
optional dictionary is passed in as the second argument, it is optional dictionary is passed in as the second argument, it is
used instead of a new dictionary. used instead of a new dictionary.
""" """
warn(_DEPRECATION_MSG % 'parse_makefile', DeprecationWarning) from distutils.text_file import TextFile
return _sysconfig._parse_makefile(fn, g) fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
def expand_makefile_vars(s, vars): if g is None:
"""This function is deprecated. g = {}
done = {}
notdone = {}
Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in while True:
line = fp.readline()
if line is None: # eof
break
m = _variable_rx.match(line)
if m:
n, v = m.group(1, 2)
v = v.strip()
# `$$' is a literal `$' in make
tmpv = v.replace('$$', '')
if "$" in tmpv:
notdone[n] = v
else:
try:
v = int(v)
except ValueError:
# insert literal `$'
done[n] = v.replace('$$', '$')
else:
done[n] = v
# do variable interpolation here
while notdone:
for name in list(notdone):
value = notdone[name]
m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
if m:
n = m.group(1)
found = True
if n in done:
item = str(done[n])
elif n in notdone:
# get it on a subsequent round
found = False
elif n in os.environ:
# do it like make: fall back to environment
item = os.environ[n]
else:
done[n] = item = ""
if found:
after = value[m.end():]
value = value[:m.start()] + item + after
if "$" in after:
notdone[name] = value
else:
try: value = int(value)
except ValueError:
done[name] = value.strip()
else:
done[name] = value
del notdone[name]
else:
# bogus variable reference; just drop it since we can't deal
del notdone[name]
fp.close()
# save the results in the global dictionary
g.update(done)
return g
def expand_makefile_vars(s, vars):
"""Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
'string' according to 'vars' (a dictionary mapping variable names to 'string' according to 'vars' (a dictionary mapping variable names to
values). Variables not present in 'vars' are silently expanded to the values). Variables not present in 'vars' are silently expanded to the
empty string. The variable values in 'vars' should not contain further empty string. The variable values in 'vars' should not contain further
variable expansions; if 'vars' is the output of 'parse_makefile()', variable expansions; if 'vars' is the output of 'parse_makefile()',
you're fine. Returns a variable-expanded version of 's'. you're fine. Returns a variable-expanded version of 's'.
""" """
warn('this function will be removed in then next version of Python',
DeprecationWarning)
# This algorithm does multiple expansion, so if vars['foo'] contains # This algorithm does multiple expansion, so if vars['foo'] contains
# "${bar}", it will expand ${foo} to ${bar}, and then expand # "${bar}", it will expand ${foo} to ${bar}, and then expand
...@@ -166,3 +364,220 @@ def expand_makefile_vars(s, vars): ...@@ -166,3 +364,220 @@ def expand_makefile_vars(s, vars):
else: else:
break break
return s return s
_config_vars = None
def _init_posix():
"""Initialize the module as appropriate for POSIX systems."""
g = {}
# load the installed Makefile:
try:
filename = get_makefile_filename()
parse_makefile(filename, g)
except IOError as msg:
my_msg = "invalid Python installation: unable to open %s" % filename
if hasattr(msg, "strerror"):
my_msg = my_msg + " (%s)" % msg.strerror
raise DistutilsPlatformError(my_msg)
# load the installed pyconfig.h:
try:
filename = get_config_h_filename()
parse_config_h(io.open(filename), g)
except IOError as msg:
my_msg = "invalid Python installation: unable to open %s" % filename
if hasattr(msg, "strerror"):
my_msg = my_msg + " (%s)" % msg.strerror
raise DistutilsPlatformError(my_msg)
# On MacOSX we need to check the setting of the environment variable
# MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so
# it needs to be compatible.
# If it isn't set we set it to the configure-time value
if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g:
cfg_target = g['MACOSX_DEPLOYMENT_TARGET']
cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '')
if cur_target == '':
cur_target = cfg_target
os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target)
elif [int(x) for x in cfg_target.split('.')] > [int(x) for x in cur_target.split('.')]:
my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure'
% (cur_target, cfg_target))
raise DistutilsPlatformError(my_msg)
# On AIX, there are wrong paths to the linker scripts in the Makefile
# -- these paths are relative to the Python source, but when installed
# the scripts are in another directory.
if python_build:
g['LDSHARED'] = g['BLDSHARED']
elif get_python_version() < '2.1':
# The following two branches are for 1.5.2 compatibility.
if sys.platform == 'aix4': # what about AIX 3.x ?
# Linker script is in the config directory, not in Modules as the
# Makefile says.
python_lib = get_python_lib(standard_lib=1)
ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
python_exp = os.path.join(python_lib, 'config', 'python.exp')
g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp)
global _config_vars
_config_vars = g
def _init_nt():
"""Initialize the module as appropriate for NT"""
g = {}
# set basic install directories
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
# XXX hmmm.. a normal install puts include files here
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
g['SO'] = '.pyd'
g['EXE'] = ".exe"
g['VERSION'] = get_python_version().replace(".", "")
g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
global _config_vars
_config_vars = g
def _init_mac():
"""Initialize the module as appropriate for Macintosh systems"""
g = {}
# set basic install directories
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
# XXX hmmm.. a normal install puts include files here
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
import MacOS
if not hasattr(MacOS, 'runtimemodel'):
g['SO'] = '.ppc.slb'
else:
g['SO'] = '.%s.slb' % MacOS.runtimemodel
# XXX are these used anywhere?
g['install_lib'] = os.path.join(EXEC_PREFIX, "Lib")
g['install_platlib'] = os.path.join(EXEC_PREFIX, "Mac", "Lib")
# These are used by the extension module build
g['srcdir'] = ':'
global _config_vars
_config_vars = g
def _init_os2():
"""Initialize the module as appropriate for OS/2"""
g = {}
# set basic install directories
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
# XXX hmmm.. a normal install puts include files here
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
g['SO'] = '.pyd'
g['EXE'] = ".exe"
global _config_vars
_config_vars = g
def get_config_vars(*args):
"""With no arguments, return a dictionary of all configuration
variables relevant for the current platform. Generally this includes
everything needed to build extensions and install both pure modules and
extensions. On Unix, this means every variable defined in Python's
installed Makefile; on Windows and Mac OS it's a much smaller set.
With arguments, return a list of values that result from looking up
each argument in the configuration variable dictionary.
"""
global _config_vars
if _config_vars is None:
func = globals().get("_init_" + os.name)
if func:
func()
else:
_config_vars = {}
# Normalized versions of prefix and exec_prefix are handy to have;
# in fact, these are the standard versions used most places in the
# Distutils.
_config_vars['prefix'] = PREFIX
_config_vars['exec_prefix'] = EXEC_PREFIX
# Convert srcdir into an absolute path if it appears necessary.
# Normally it is relative to the build directory. However, during
# testing, for example, we might be running a non-installed python
# from a different directory.
if python_build and os.name == "posix":
base = os.path.dirname(os.path.abspath(sys.executable))
if (not os.path.isabs(_config_vars['srcdir']) and
base != os.getcwd()):
# srcdir is relative and we are not in the same directory
# as the executable. Assume executable is in the build
# directory and make srcdir absolute.
srcdir = os.path.join(base, _config_vars['srcdir'])
_config_vars['srcdir'] = os.path.normpath(srcdir)
if sys.platform == 'darwin':
kernel_version = os.uname()[2] # Kernel version (8.4.3)
major_version = int(kernel_version.split('.')[0])
if major_version < 8:
# On Mac OS X before 10.4, check if -arch and -isysroot
# are in CFLAGS or LDFLAGS and remove them if they are.
# This is needed when building extensions on a 10.3 system
# using a universal build of python.
for key in ('LDFLAGS', 'BASECFLAGS',
# a number of derived variables. These need to be
# patched up as well.
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
flags = _config_vars[key]
flags = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII)
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
_config_vars[key] = flags
else:
# Allow the user to override the architecture flags using
# an environment variable.
# NOTE: This name was introduced by Apple in OSX 10.5 and
# is used by several scripting languages distributed with
# that OS release.
if 'ARCHFLAGS' in os.environ:
arch = os.environ['ARCHFLAGS']
for key in ('LDFLAGS', 'BASECFLAGS',
# a number of derived variables. These need to be
# patched up as well.
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
flags = _config_vars[key]
flags = re.sub('-arch\s+\w+\s', ' ', flags)
flags = flags + ' ' + arch
_config_vars[key] = flags
if args:
vals = []
for name in args:
vals.append(_config_vars.get(name))
return vals
else:
return _config_vars
def get_config_var(name):
"""Return the value of a single variable using the dictionary
returned by 'get_config_vars()'. Equivalent to
get_config_vars().get(name)
"""
return get_config_vars().get(name)
...@@ -3,19 +3,11 @@ import os ...@@ -3,19 +3,11 @@ import os
import shutil import shutil
import tempfile import tempfile
from copy import deepcopy from copy import deepcopy
import warnings
from distutils import log from distutils import log
from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
from distutils.core import Distribution from distutils.core import Distribution
def capture_warnings(func):
def _capture_warnings(*args, **kw):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return func(*args, **kw)
return _capture_warnings
class LoggingSilencer(object): class LoggingSilencer(object):
def setUp(self): def setUp(self):
...@@ -63,8 +55,6 @@ class TempdirManager(object): ...@@ -63,8 +55,6 @@ class TempdirManager(object):
super().tearDown() super().tearDown()
while self.tempdirs: while self.tempdirs:
d = self.tempdirs.pop() d = self.tempdirs.pop()
if not os.path.exists(d):
continue
shutil.rmtree(d, os.name in ('nt', 'cygwin')) shutil.rmtree(d, os.name in ('nt', 'cygwin'))
def mkdtemp(self): def mkdtemp(self):
......
...@@ -14,31 +14,16 @@ from distutils.spawn import find_executable, spawn ...@@ -14,31 +14,16 @@ from distutils.spawn import find_executable, spawn
from distutils.tests import support from distutils.tests import support
from test.support import check_warnings from test.support import check_warnings
try:
import grp
import pwd
UID_GID_SUPPORT = True
except ImportError:
UID_GID_SUPPORT = False
try: try:
import zipfile import zipfile
ZIP_SUPPORT = True ZIP_SUPPORT = True
except ImportError: except ImportError:
ZIP_SUPPORT = find_executable('zip') ZIP_SUPPORT = find_executable('zip')
# some tests will fail if zlib is not available
try:
import zlib
except ImportError:
zlib = None
class ArchiveUtilTestCase(support.TempdirManager, class ArchiveUtilTestCase(support.TempdirManager,
support.LoggingSilencer, support.LoggingSilencer,
unittest.TestCase): unittest.TestCase):
@unittest.skipUnless(zlib, "requires zlib")
def test_make_tarball(self): def test_make_tarball(self):
# creating something to tar # creating something to tar
tmpdir = self.mkdtemp() tmpdir = self.mkdtemp()
...@@ -49,7 +34,7 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -49,7 +34,7 @@ class ArchiveUtilTestCase(support.TempdirManager,
tmpdir2 = self.mkdtemp() tmpdir2 = self.mkdtemp()
unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0], unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
"source and target should be on same drive") "Source and target should be on same drive")
base_name = os.path.join(tmpdir2, 'archive') base_name = os.path.join(tmpdir2, 'archive')
...@@ -99,7 +84,6 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -99,7 +84,6 @@ class ArchiveUtilTestCase(support.TempdirManager,
base_name = os.path.join(tmpdir2, 'archive') base_name = os.path.join(tmpdir2, 'archive')
return tmpdir, tmpdir2, base_name return tmpdir, tmpdir2, base_name
@unittest.skipUnless(zlib, "Requires zlib")
@unittest.skipUnless(find_executable('tar') and find_executable('gzip'), @unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
'Need the tar command to run') 'Need the tar command to run')
def test_tarfile_vs_tar(self): def test_tarfile_vs_tar(self):
...@@ -185,7 +169,6 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -185,7 +169,6 @@ class ArchiveUtilTestCase(support.TempdirManager,
self.assertTrue(not os.path.exists(tarball)) self.assertTrue(not os.path.exists(tarball))
self.assertEquals(len(w.warnings), 1) self.assertEquals(len(w.warnings), 1)
@unittest.skipUnless(zlib, "Requires zlib")
@unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run') @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
def test_make_zipfile(self): def test_make_zipfile(self):
# creating something to tar # creating something to tar
...@@ -210,59 +193,6 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -210,59 +193,6 @@ class ArchiveUtilTestCase(support.TempdirManager,
base_name = os.path.join(tmpdir, 'archive') base_name = os.path.join(tmpdir, 'archive')
self.assertRaises(ValueError, make_archive, base_name, 'xxx') self.assertRaises(ValueError, make_archive, base_name, 'xxx')
@unittest.skipUnless(zlib, "Requires zlib")
def test_make_archive_owner_group(self):
# testing make_archive with owner and group, with various combinations
# this works even if there's not gid/uid support
if UID_GID_SUPPORT:
group = grp.getgrgid(0)[0]
owner = pwd.getpwuid(0)[0]
else:
group = owner = 'root'
base_dir, root_dir, base_name = self._create_files()
base_name = os.path.join(self.mkdtemp() , 'archive')
res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner,
group=group)
self.assertTrue(os.path.exists(res))
res = make_archive(base_name, 'zip', root_dir, base_dir)
self.assertTrue(os.path.exists(res))
res = make_archive(base_name, 'tar', root_dir, base_dir,
owner=owner, group=group)
self.assertTrue(os.path.exists(res))
res = make_archive(base_name, 'tar', root_dir, base_dir,
owner='kjhkjhkjg', group='oihohoh')
self.assertTrue(os.path.exists(res))
@unittest.skipUnless(zlib, "Requires zlib")
@unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
def test_tarfile_root_owner(self):
tmpdir, tmpdir2, base_name = self._create_files()
old_dir = os.getcwd()
os.chdir(tmpdir)
group = grp.getgrgid(0)[0]
owner = pwd.getpwuid(0)[0]
try:
archive_name = make_tarball(base_name, 'dist', compress=None,
owner=owner, group=group)
finally:
os.chdir(old_dir)
# check if the compressed tarball was created
self.assertTrue(os.path.exists(archive_name))
# now checks the rights
archive = tarfile.open(archive_name)
try:
for member in archive.getmembers():
self.assertEquals(member.uid, 0)
self.assertEquals(member.gid, 0)
finally:
archive.close()
def test_make_archive_cwd(self): def test_make_archive_cwd(self):
current_dir = os.getcwd() current_dir = os.getcwd()
def _breaks(*args, **kw): def _breaks(*args, **kw):
......
...@@ -5,8 +5,6 @@ import os ...@@ -5,8 +5,6 @@ import os
import tempfile import tempfile
import shutil import shutil
from test.support import run_unittest
from distutils.core import Distribution from distutils.core import Distribution
from distutils.command.bdist import bdist from distutils.command.bdist import bdist
from distutils.tests import support from distutils.tests import support
...@@ -42,4 +40,4 @@ def test_suite(): ...@@ -42,4 +40,4 @@ def test_suite():
return unittest.makeSuite(BuildTestCase) return unittest.makeSuite(BuildTestCase)
if __name__ == '__main__': if __name__ == '__main__':
run_unittest(test_suite()) test_support.run_unittest(test_suite())
...@@ -4,15 +4,6 @@ import unittest ...@@ -4,15 +4,6 @@ import unittest
import sys import sys
import os import os
# zlib is not used here, but if it's not available
# test_simple_built will fail
try:
import zlib
except ImportError:
zlib = None
from test.support import run_unittest
from distutils.core import Distribution from distutils.core import Distribution
from distutils.command.bdist_dumb import bdist_dumb from distutils.command.bdist_dumb import bdist_dumb
from distutils.tests import support from distutils.tests import support
...@@ -42,7 +33,6 @@ class BuildDumbTestCase(support.TempdirManager, ...@@ -42,7 +33,6 @@ class BuildDumbTestCase(support.TempdirManager,
sys.argv[:] = self.old_sys_argv[1] sys.argv[:] = self.old_sys_argv[1]
super(BuildDumbTestCase, self).tearDown() super(BuildDumbTestCase, self).tearDown()
@unittest.skipUnless(zlib, "requires zlib")
def test_simple_built(self): def test_simple_built(self):
# let's create a simple package # let's create a simple package
...@@ -83,23 +73,8 @@ class BuildDumbTestCase(support.TempdirManager, ...@@ -83,23 +73,8 @@ class BuildDumbTestCase(support.TempdirManager,
# now let's check what we have in the zip file # now let's check what we have in the zip file
# XXX to be done # XXX to be done
def test_finalize_options(self):
pkg_dir, dist = self.create_dist()
os.chdir(pkg_dir)
cmd = bdist_dumb(dist)
self.assertEquals(cmd.bdist_dir, None)
cmd.finalize_options()
# bdist_dir is initialized to bdist_base/dumb if not set
base = cmd.get_finalized_command('bdist').bdist_base
self.assertEquals(cmd.bdist_dir, os.path.join(base, 'dumb'))
# the format is set to a default value depending on the os.name
default = cmd.default_format[os.name]
self.assertEquals(cmd.format, default)
def test_suite(): def test_suite():
return unittest.makeSuite(BuildDumbTestCase) return unittest.makeSuite(BuildDumbTestCase)
if __name__ == '__main__': if __name__ == '__main__':
run_unittest(test_suite()) test_support.run_unittest(test_suite())
...@@ -6,8 +6,6 @@ import os ...@@ -6,8 +6,6 @@ import os
import tempfile import tempfile
import shutil import shutil
from test.support import run_unittest
from distutils.core import Distribution from distutils.core import Distribution
from distutils.command.bdist_rpm import bdist_rpm from distutils.command.bdist_rpm import bdist_rpm
from distutils.tests import support from distutils.tests import support
...@@ -124,4 +122,4 @@ def test_suite(): ...@@ -124,4 +122,4 @@ def test_suite():
return unittest.makeSuite(BuildRpmTestCase) return unittest.makeSuite(BuildRpmTestCase)
if __name__ == '__main__': if __name__ == '__main__':
run_unittest(test_suite()) test_support.run_unittest(test_suite())
"""Tests for distutils.command.bdist_wininst.""" """Tests for distutils.command.bdist_wininst."""
import unittest import unittest
from test.support import run_unittest
from distutils.command.bdist_wininst import bdist_wininst from distutils.command.bdist_wininst import bdist_wininst
from distutils.tests import support from distutils.tests import support
...@@ -29,4 +27,4 @@ def test_suite(): ...@@ -29,4 +27,4 @@ def test_suite():
return unittest.makeSuite(BuildWinInstTestCase) return unittest.makeSuite(BuildWinInstTestCase)
if __name__ == '__main__': if __name__ == '__main__':
run_unittest(test_suite()) test_support.run_unittest(test_suite())
...@@ -120,7 +120,8 @@ class BuildCLibTestCase(support.TempdirManager, ...@@ -120,7 +120,8 @@ class BuildCLibTestCase(support.TempdirManager,
# before we run the command, we want to make sure # before we run the command, we want to make sure
# all commands are present on the system # all commands are present on the system
# by creating a compiler and checking its executables # by creating a compiler and checking its executables
from distutils.ccompiler import new_compiler, customize_compiler from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler
compiler = new_compiler() compiler = new_compiler()
customize_compiler(compiler) customize_compiler(compiler)
......
...@@ -3,13 +3,10 @@ import os ...@@ -3,13 +3,10 @@ import os
import tempfile import tempfile
import shutil import shutil
from io import StringIO from io import StringIO
import warnings
from test.support import check_warnings
from test.support import captured_stdout
from distutils.core import Extension, Distribution from distutils.core import Extension, Distribution
from distutils.command.build_ext import build_ext from distutils.command.build_ext import build_ext
import sysconfig from distutils import sysconfig
from distutils.tests.support import TempdirManager from distutils.tests.support import TempdirManager
from distutils.tests.support import LoggingSilencer from distutils.tests.support import LoggingSilencer
from distutils.extension import Extension from distutils.extension import Extension
...@@ -25,23 +22,19 @@ ALREADY_TESTED = False ...@@ -25,23 +22,19 @@ ALREADY_TESTED = False
def _get_source_filename(): def _get_source_filename():
srcdir = sysconfig.get_config_var('srcdir') srcdir = sysconfig.get_config_var('srcdir')
if srcdir is None:
return os.path.join(sysconfig.project_base, 'Modules', 'xxmodule.c')
return os.path.join(srcdir, 'Modules', 'xxmodule.c') return os.path.join(srcdir, 'Modules', 'xxmodule.c')
_XX_MODULE_PATH = _get_source_filename() class BuildExtTestCase(TempdirManager,
LoggingSilencer,
class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase): unittest.TestCase):
def setUp(self): def setUp(self):
# Create a simple test environment # Create a simple test environment
# Note that we're making changes to sys.path # Note that we're making changes to sys.path
super(BuildExtTestCase, self).setUp() super(BuildExtTestCase, self).setUp()
self.tmp_dir = self.mkdtemp() self.tmp_dir = self.mkdtemp()
if os.path.exists(_XX_MODULE_PATH): self.sys_path = sys.path, sys.path[:]
self.sys_path = sys.path[:] sys.path.append(self.tmp_dir)
sys.path.append(self.tmp_dir) shutil.copy(_get_source_filename(), self.tmp_dir)
shutil.copy(_XX_MODULE_PATH, self.tmp_dir)
if sys.version > "2.6": if sys.version > "2.6":
import site import site
self.old_user_base = site.USER_BASE self.old_user_base = site.USER_BASE
...@@ -49,19 +42,6 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase): ...@@ -49,19 +42,6 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase):
from distutils.command import build_ext from distutils.command import build_ext
build_ext.USER_BASE = site.USER_BASE build_ext.USER_BASE = site.USER_BASE
def tearDown(self):
# Get everything back to normal
if os.path.exists(_XX_MODULE_PATH):
support.unload('xx')
sys.path[:] = self.sys_path
# XXX on Windows the test leaves a directory
# with xx module in TEMP
shutil.rmtree(self.tmp_dir, os.name == 'nt' or
sys.platform == 'cygwin')
super(BuildExtTestCase, self).tearDown()
@unittest.skipIf(not os.path.exists(_XX_MODULE_PATH),
'xxmodule.c not found')
def test_build_ext(self): def test_build_ext(self):
global ALREADY_TESTED global ALREADY_TESTED
xx_c = os.path.join(self.tmp_dir, 'xxmodule.c') xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
...@@ -104,23 +84,35 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase): ...@@ -104,23 +84,35 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase):
self.assertTrue(isinstance(xx.Null(), xx.Null)) self.assertTrue(isinstance(xx.Null(), xx.Null))
self.assertTrue(isinstance(xx.Str(), xx.Str)) self.assertTrue(isinstance(xx.Str(), xx.Str))
def tearDown(self):
# Get everything back to normal
support.unload('xx')
sys.path = self.sys_path[0]
sys.path[:] = self.sys_path[1]
if sys.version > "2.6":
import site
site.USER_BASE = self.old_user_base
from distutils.command import build_ext
build_ext.USER_BASE = self.old_user_base
super(BuildExtTestCase, self).tearDown()
def test_solaris_enable_shared(self): def test_solaris_enable_shared(self):
dist = Distribution({'name': 'xx'}) dist = Distribution({'name': 'xx'})
cmd = build_ext(dist) cmd = build_ext(dist)
old = sys.platform old = sys.platform
sys.platform = 'sunos' # fooling finalize_options sys.platform = 'sunos' # fooling finalize_options
from sysconfig import _CONFIG_VARS from distutils.sysconfig import _config_vars
old_var = _CONFIG_VARS.get('Py_ENABLE_SHARED') old_var = _config_vars.get('Py_ENABLE_SHARED')
_CONFIG_VARS['Py_ENABLE_SHARED'] = 1 _config_vars['Py_ENABLE_SHARED'] = 1
try: try:
cmd.ensure_finalized() cmd.ensure_finalized()
finally: finally:
sys.platform = old sys.platform = old
if old_var is None: if old_var is None:
del _CONFIG_VARS['Py_ENABLE_SHARED'] del _config_vars['Py_ENABLE_SHARED']
else: else:
_CONFIG_VARS['Py_ENABLE_SHARED'] = old_var _config_vars['Py_ENABLE_SHARED'] = old_var
# make sure we get some library dirs under solaris # make sure we get some library dirs under solaris
self.assertTrue(len(cmd.library_dirs) > 0) self.assertTrue(len(cmd.library_dirs) > 0)
...@@ -182,10 +174,11 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase): ...@@ -182,10 +174,11 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase):
cmd = build_ext(dist) cmd = build_ext(dist)
cmd.finalize_options() cmd.finalize_options()
py_include = sysconfig.get_path('include') from distutils import sysconfig
py_include = sysconfig.get_python_inc()
self.assertTrue(py_include in cmd.include_dirs) self.assertTrue(py_include in cmd.include_dirs)
plat_py_include = sysconfig.get_path('platinclude') plat_py_include = sysconfig.get_python_inc(plat_specific=1)
self.assertTrue(plat_py_include in cmd.include_dirs) self.assertTrue(plat_py_include in cmd.include_dirs)
# make sure cmd.libraries is turned into a list # make sure cmd.libraries is turned into a list
...@@ -336,6 +329,7 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase): ...@@ -336,6 +329,7 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase):
self.assertEquals(so_dir, other_tmp_dir) self.assertEquals(so_dir, other_tmp_dir)
cmd.inplace = 0 cmd.inplace = 0
cmd.compiler = None
cmd.run() cmd.run()
so_file = cmd.get_outputs()[0] so_file = cmd.get_outputs()[0]
self.assertTrue(os.path.exists(so_file)) self.assertTrue(os.path.exists(so_file))
...@@ -404,26 +398,6 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase): ...@@ -404,26 +398,6 @@ class BuildExtTestCase(TempdirManager, LoggingSilencer, unittest.TestCase):
wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext) wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
self.assertEquals(wanted, path) self.assertEquals(wanted, path)
def test_compiler_deprecation_warning(self):
dist = Distribution()
cmd = build_ext(dist)
class MyCompiler(object):
def do_something(self):
pass
with check_warnings() as w:
warnings.simplefilter("always")
cmd.compiler = MyCompiler()
self.assertEquals(len(w.warnings), 1)
cmd.compile = 'unix'
self.assertEquals(len(w.warnings), 1)
cmd.compiler = MyCompiler()
cmd.compiler.do_something()
# two more warnings genereated by the get
# and the set
self.assertEquals(len(w.warnings), 3)
def test_suite(): def test_suite():
src = _get_source_filename() src = _get_source_filename()
if not os.path.exists(src): if not os.path.exists(src):
......
...@@ -16,7 +16,7 @@ class BuildPyTestCase(support.TempdirManager, ...@@ -16,7 +16,7 @@ class BuildPyTestCase(support.TempdirManager,
support.LoggingSilencer, support.LoggingSilencer,
unittest.TestCase): unittest.TestCase):
def _setup_package_data(self): def test_package_data(self):
sources = self.mkdtemp() sources = self.mkdtemp()
f = open(os.path.join(sources, "__init__.py"), "w") f = open(os.path.join(sources, "__init__.py"), "w")
f.write("# Pretend this is a package.") f.write("# Pretend this is a package.")
...@@ -52,18 +52,9 @@ class BuildPyTestCase(support.TempdirManager, ...@@ -52,18 +52,9 @@ class BuildPyTestCase(support.TempdirManager,
self.assertEqual(len(cmd.get_outputs()), 3) self.assertEqual(len(cmd.get_outputs()), 3)
pkgdest = os.path.join(destination, "pkg") pkgdest = os.path.join(destination, "pkg")
files = os.listdir(pkgdest) files = os.listdir(pkgdest)
return files
def test_package_data(self):
files = self._setup_package_data()
self.assertTrue("__init__.py" in files) self.assertTrue("__init__.py" in files)
self.assertTrue("README.txt" in files)
@unittest.skipIf(sys.flags.optimize >= 2,
"pyc files are not written with -O2 and above")
def test_package_data_pyc(self):
files = self._setup_package_data()
self.assertTrue("__init__.pyc" in files) self.assertTrue("__init__.pyc" in files)
self.assertTrue("README.txt" in files)
def test_empty_package_dir (self): def test_empty_package_dir (self):
# See SF 1668596/1720897. # See SF 1668596/1720897.
......
...@@ -5,7 +5,7 @@ import unittest ...@@ -5,7 +5,7 @@ import unittest
from distutils.command.build_scripts import build_scripts from distutils.command.build_scripts import build_scripts
from distutils.core import Distribution from distutils.core import Distribution
import sysconfig from distutils import sysconfig
from distutils.tests import support from distutils.tests import support
...@@ -91,12 +91,12 @@ class BuildScriptsTestCase(support.TempdirManager, ...@@ -91,12 +91,12 @@ class BuildScriptsTestCase(support.TempdirManager,
# --with-suffix=3`, python is compiled okay but the build scripts # --with-suffix=3`, python is compiled okay but the build scripts
# failed when writing the name of the executable # failed when writing the name of the executable
old = sysconfig.get_config_vars().get('VERSION') old = sysconfig.get_config_vars().get('VERSION')
sysconfig._CONFIG_VARS['VERSION'] = 4 sysconfig._config_vars['VERSION'] = 4
try: try:
cmd.run() cmd.run()
finally: finally:
if old is not None: if old is not None:
sysconfig._CONFIG_VARS['VERSION'] = old sysconfig._config_vars['VERSION'] = old
built = os.listdir(target) built = os.listdir(target)
for name in expected: for name in expected:
......
"""Tests for distutils.ccompiler."""
import os
import unittest
from test.support import captured_stdout
from distutils.ccompiler import (gen_lib_options, CCompiler,
get_default_compiler, customize_compiler)
from distutils import debug
from distutils.tests import support
class FakeCompiler(object):
def library_dir_option(self, dir):
return "-L" + dir
def runtime_library_dir_option(self, dir):
return ["-cool", "-R" + dir]
def find_library_file(self, dirs, lib, debug=0):
return 'found'
def library_option(self, lib):
return "-l" + lib
class CCompilerTestCase(support.EnvironGuard, unittest.TestCase):
def test_gen_lib_options(self):
compiler = FakeCompiler()
libdirs = ['lib1', 'lib2']
runlibdirs = ['runlib1']
libs = [os.path.join('dir', 'name'), 'name2']
opts = gen_lib_options(compiler, libdirs, runlibdirs, libs)
wanted = ['-Llib1', '-Llib2', '-cool', '-Rrunlib1', 'found',
'-lname2']
self.assertEquals(opts, wanted)
def test_debug_print(self):
class MyCCompiler(CCompiler):
executables = {}
compiler = MyCCompiler()
with captured_stdout() as stdout:
compiler.debug_print('xxx')
stdout.seek(0)
self.assertEquals(stdout.read(), '')
debug.DEBUG = True
try:
with captured_stdout() as stdout:
compiler.debug_print('xxx')
stdout.seek(0)
self.assertEquals(stdout.read(), 'xxx\n')
finally:
debug.DEBUG = False
def test_customize_compiler(self):
# not testing if default compiler is not unix
if get_default_compiler() != 'unix':
return
os.environ['AR'] = 'my_ar'
os.environ['ARFLAGS'] = '-arflags'
# make sure AR gets caught
class compiler:
compiler_type = 'unix'
def set_executables(self, **kw):
self.exes = kw
comp = compiler()
customize_compiler(comp)
self.assertEquals(comp.exes['archiver'], 'my_ar -arflags')
def test_suite():
return unittest.makeSuite(CCompilerTestCase)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
"""Tests for distutils.cmd.""" """Tests for distutils.cmd."""
import unittest import unittest
import os import os
from test.support import captured_stdout, run_unittest from test.support import captured_stdout
from distutils.cmd import Command from distutils.cmd import Command
from distutils.dist import Distribution from distutils.dist import Distribution
...@@ -124,4 +124,4 @@ def test_suite(): ...@@ -124,4 +124,4 @@ def test_suite():
return unittest.makeSuite(CommandTestCase) return unittest.makeSuite(CommandTestCase)
if __name__ == '__main__': if __name__ == '__main__':
run_unittest(test_suite()) test_support.run_unittest(test_suite())
...@@ -2,21 +2,29 @@ ...@@ -2,21 +2,29 @@
import unittest import unittest
import sys import sys
import os import os
from io import BytesIO
import subprocess import subprocess
import warnings
import sysconfig
from test.support import check_warnings, run_unittest
from test.support import captured_stdout
from distutils import cygwinccompiler from distutils import cygwinccompiler
from distutils.cygwinccompiler import (CygwinCCompiler, check_config_h, from distutils.cygwinccompiler import (CygwinCCompiler, check_config_h,
CONFIG_H_OK, CONFIG_H_NOTOK, CONFIG_H_OK, CONFIG_H_NOTOK,
CONFIG_H_UNCERTAIN, get_versions, CONFIG_H_UNCERTAIN, get_versions,
get_msvcr, RE_VERSION) get_msvcr)
from distutils.util import get_compiler_versions
from distutils.tests import support from distutils.tests import support
class FakePopen(object):
test_class = None
def __init__(self, cmd, shell, stdout):
self.cmd = cmd.split()[0]
exes = self.test_class._exes
if self.cmd in exes:
# issue #6438 in Python 3.x, Popen returns bytes
self.stdout = BytesIO(exes[self.cmd])
else:
self.stdout = os.popen(cmd, 'r')
class CygwinCCompilerTestCase(support.TempdirManager, class CygwinCCompilerTestCase(support.TempdirManager,
unittest.TestCase): unittest.TestCase):
...@@ -24,17 +32,32 @@ class CygwinCCompilerTestCase(support.TempdirManager, ...@@ -24,17 +32,32 @@ class CygwinCCompilerTestCase(support.TempdirManager,
super(CygwinCCompilerTestCase, self).setUp() super(CygwinCCompilerTestCase, self).setUp()
self.version = sys.version self.version = sys.version
self.python_h = os.path.join(self.mkdtemp(), 'python.h') self.python_h = os.path.join(self.mkdtemp(), 'python.h')
from distutils import sysconfig
self.old_get_config_h_filename = sysconfig.get_config_h_filename self.old_get_config_h_filename = sysconfig.get_config_h_filename
sysconfig.get_config_h_filename = self._get_config_h_filename sysconfig.get_config_h_filename = self._get_config_h_filename
self.old_find_executable = cygwinccompiler.find_executable
cygwinccompiler.find_executable = self._find_executable
self._exes = {}
self.old_popen = cygwinccompiler.Popen
FakePopen.test_class = self
cygwinccompiler.Popen = FakePopen
def tearDown(self): def tearDown(self):
sys.version = self.version sys.version = self.version
from distutils import sysconfig
sysconfig.get_config_h_filename = self.old_get_config_h_filename sysconfig.get_config_h_filename = self.old_get_config_h_filename
cygwinccompiler.find_executable = self.old_find_executable
cygwinccompiler.Popen = self.old_popen
super(CygwinCCompilerTestCase, self).tearDown() super(CygwinCCompilerTestCase, self).tearDown()
def _get_config_h_filename(self): def _get_config_h_filename(self):
return self.python_h return self.python_h
def _find_executable(self, name):
if name in self._exes:
return name
return None
def test_check_config_h(self): def test_check_config_h(self):
# check_config_h looks for "GCC" in sys.version first # check_config_h looks for "GCC" in sys.version first
...@@ -58,6 +81,40 @@ class CygwinCCompilerTestCase(support.TempdirManager, ...@@ -58,6 +81,40 @@ class CygwinCCompilerTestCase(support.TempdirManager,
self.write_file(self.python_h, 'xxx __GNUC__ xxx') self.write_file(self.python_h, 'xxx __GNUC__ xxx')
self.assertEquals(check_config_h()[0], CONFIG_H_OK) self.assertEquals(check_config_h()[0], CONFIG_H_OK)
def test_get_versions(self):
# get_versions calls distutils.spawn.find_executable on
# 'gcc', 'ld' and 'dllwrap'
self.assertEquals(get_versions(), (None, None, None))
# Let's fake we have 'gcc' and it returns '3.4.5'
self._exes['gcc'] = b'gcc (GCC) 3.4.5 (mingw special)\nFSF'
res = get_versions()
self.assertEquals(str(res[0]), '3.4.5')
# and let's see what happens when the version
# doesn't match the regular expression
# (\d+\.\d+(\.\d+)*)
self._exes['gcc'] = b'very strange output'
res = get_versions()
self.assertEquals(res[0], None)
# same thing for ld
self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
res = get_versions()
self.assertEquals(str(res[1]), '2.17.50')
self._exes['ld'] = b'@(#)PROGRAM:ld PROJECT:ld64-77'
res = get_versions()
self.assertEquals(res[1], None)
# and dllwrap
self._exes['dllwrap'] = b'GNU dllwrap 2.17.50 20060824\nFSF'
res = get_versions()
self.assertEquals(str(res[2]), '2.17.50')
self._exes['dllwrap'] = b'Cheese Wrap'
res = get_versions()
self.assertEquals(res[2], None)
def test_get_msvcr(self): def test_get_msvcr(self):
# none # none
...@@ -90,23 +147,8 @@ class CygwinCCompilerTestCase(support.TempdirManager, ...@@ -90,23 +147,8 @@ class CygwinCCompilerTestCase(support.TempdirManager,
'[MSC v.1999 32 bits (Intel)]') '[MSC v.1999 32 bits (Intel)]')
self.assertRaises(ValueError, get_msvcr) self.assertRaises(ValueError, get_msvcr)
def test_get_version_deprecated(self):
with check_warnings() as w:
warnings.simplefilter("always")
# make sure get_compiler_versions and get_versions
# returns the same thing
self.assertEquals(get_compiler_versions(), get_versions())
# make sure using get_version() generated a warning
self.assertEquals(len(w.warnings), 1)
# make sure any usage of RE_VERSION will also
# generate a warning, but till works
version = RE_VERSION.search('1.2').group(1)
self.assertEquals(version, '1.2')
self.assertEquals(len(w.warnings), 2)
def test_suite(): def test_suite():
return unittest.makeSuite(CygwinCCompilerTestCase) return unittest.makeSuite(CygwinCCompilerTestCase)
if __name__ == '__main__': if __name__ == '__main__':
run_unittest(test_suite()) test_support.run_unittest(test_suite())
...@@ -7,9 +7,8 @@ import unittest ...@@ -7,9 +7,8 @@ import unittest
import warnings import warnings
import textwrap import textwrap
from distutils.dist import Distribution, fix_help_options, DistributionMetadata from distutils.dist import Distribution, fix_help_options
from distutils.cmd import Command from distutils.cmd import Command
import distutils.dist
from test.support import TESTFN, captured_stdout from test.support import TESTFN, captured_stdout
from distutils.tests import support from distutils.tests import support
...@@ -38,8 +37,7 @@ class TestDistribution(Distribution): ...@@ -38,8 +37,7 @@ class TestDistribution(Distribution):
return self._config_files return self._config_files
class DistributionTestCase(support.TempdirManager, class DistributionTestCase(support.LoggingSilencer,
support.LoggingSilencer,
support.EnvironGuard, support.EnvironGuard,
unittest.TestCase): unittest.TestCase):
...@@ -60,27 +58,6 @@ class DistributionTestCase(support.TempdirManager, ...@@ -60,27 +58,6 @@ class DistributionTestCase(support.TempdirManager,
d.parse_command_line() d.parse_command_line()
return d return d
def test_debug_mode(self):
with open(TESTFN, "w") as f:
f.write("[global]")
f.write("command_packages = foo.bar, splat")
files = [TESTFN]
sys.argv.append("build")
with captured_stdout() as stdout:
self.create_distribution(files)
stdout.seek(0)
self.assertEquals(stdout.read(), '')
distutils.dist.DEBUG = True
try:
with captured_stdout() as stdout:
self.create_distribution(files)
stdout.seek(0)
self.assertEquals(stdout.read(), '')
finally:
distutils.dist.DEBUG = False
def test_command_packages_unspecified(self): def test_command_packages_unspecified(self):
sys.argv.append("build") sys.argv.append("build")
d = self.create_distribution() d = self.create_distribution()
...@@ -182,35 +159,6 @@ class DistributionTestCase(support.TempdirManager, ...@@ -182,35 +159,6 @@ class DistributionTestCase(support.TempdirManager,
kwargs = {'level': 'ok2'} kwargs = {'level': 'ok2'}
self.assertRaises(ValueError, dist.announce, args, kwargs) self.assertRaises(ValueError, dist.announce, args, kwargs)
def test_find_config_files_disable(self):
# Ticket #1180: Allow user to disable their home config file.
temp_home = self.mkdtemp()
if os.name == 'posix':
user_filename = os.path.join(temp_home, ".pydistutils.cfg")
else:
user_filename = os.path.join(temp_home, "pydistutils.cfg")
with open(user_filename, 'w') as f:
f.write('[distutils]\n')
def _expander(path):
return temp_home
old_expander = os.path.expanduser
os.path.expanduser = _expander
try:
d = distutils.dist.Distribution()
all_files = d.find_config_files()
d = distutils.dist.Distribution(attrs={'script_args':
['--no-user-cfg']})
files = d.find_config_files()
finally:
os.path.expanduser = old_expander
# make sure --no-user-cfg disables the user cfg file
self.assertEquals(len(all_files)-1, len(files))
class MetadataTestCase(support.TempdirManager, support.EnvironGuard, class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
unittest.TestCase): unittest.TestCase):
...@@ -364,38 +312,11 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, ...@@ -364,38 +312,11 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
"version": "1.0", "version": "1.0",
"long_description": long_desc} "long_description": long_desc}
dist = distutils.dist.Distribution(attrs) dist = Distribution(attrs)
meta = self.format_metadata(dist) meta = self.format_metadata(dist)
meta = meta.replace('\n' + 8 * ' ', '\n') meta = meta.replace('\n' + 8 * ' ', '\n')
self.assertTrue(long_desc in meta) self.assertTrue(long_desc in meta)
def test_read_metadata(self):
attrs = {"name": "package",
"version": "1.0",
"long_description": "desc",
"description": "xxx",
"download_url": "http://example.com",
"keywords": ['one', 'two'],
"requires": ['foo']}
dist = Distribution(attrs)
metadata = dist.metadata
# write it then reloads it
PKG_INFO = io.StringIO()
metadata.write_pkg_file(PKG_INFO)
PKG_INFO.seek(0)
metadata.read_pkg_file(PKG_INFO)
self.assertEquals(metadata.name, "package")
self.assertEquals(metadata.version, "1.0")
self.assertEquals(metadata.description, "xxx")
self.assertEquals(metadata.download_url, 'http://example.com')
self.assertEquals(metadata.keywords, ['one', 'two'])
self.assertEquals(metadata.platforms, ['UNKNOWN'])
self.assertEquals(metadata.obsoletes, None)
self.assertEquals(metadata.requires, ['foo'])
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DistributionTestCase)) suite.addTest(unittest.makeSuite(DistributionTestCase))
......
"""Tests for distutils.emxccompiler."""
import unittest
import sys
import os
import warnings
from test.support import check_warnings, run_unittest
from test.support import captured_stdout
from distutils.emxccompiler import get_versions
from distutils.util import get_compiler_versions
from distutils.tests import support
class EmxCCompilerTestCase(support.TempdirManager,
unittest.TestCase):
def test_get_version_deprecated(self):
with check_warnings() as w:
warnings.simplefilter("always")
# make sure get_compiler_versions and get_versions
# returns the same gcc
gcc, ld, dllwrap = get_compiler_versions()
emx_gcc, emx_ld = get_versions()
self.assertEquals(gcc, emx_gcc)
# make sure using get_version() generated a warning
self.assertEquals(len(w.warnings), 1)
def test_suite():
return unittest.makeSuite(EmxCCompilerTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
"""Tests for distutils.extension.""" """Tests for distutils.extension."""
import os
import sys
import unittest import unittest
import os
import warnings import warnings
from test.support import check_warnings from test.support import check_warnings
from distutils.extension import read_setup_file, Extension from distutils.extension import read_setup_file, Extension
from distutils.tests.support import capture_warnings
class ExtensionTestCase(unittest.TestCase): class ExtensionTestCase(unittest.TestCase):
@capture_warnings
def test_read_setup_file(self): def test_read_setup_file(self):
# trying to read a Setup file # trying to read a Setup file
# (sample extracted from the PyGame project) # (sample extracted from the PyGame project)
...@@ -33,22 +30,16 @@ class ExtensionTestCase(unittest.TestCase): ...@@ -33,22 +30,16 @@ class ExtensionTestCase(unittest.TestCase):
self.assertEquals(names, wanted) self.assertEquals(names, wanted)
@unittest.skipIf(sys.flags.optimize >= 2, def test_extension_init(self):
"Assertions are omitted with -O2 and above") # the first argument, which is the name, must be a string
def test_extension_init_assertions(self):
# The first argument, which is the name, must be a string.
self.assertRaises(AssertionError, Extension, 1, []) self.assertRaises(AssertionError, Extension, 1, [])
ext = Extension('name', [])
self.assertEquals(ext.name, 'name')
# the second argument, which is the list of files, must # the second argument, which is the list of files, must
# be a list of strings # be a list of strings
self.assertRaises(AssertionError, Extension, 'name', 'file') self.assertRaises(AssertionError, Extension, 'name', 'file')
self.assertRaises(AssertionError, Extension, 'name', ['file', 1]) self.assertRaises(AssertionError, Extension, 'name', ['file', 1])
def test_extension_init(self):
ext = Extension('name', [])
self.assertEquals(ext.name, 'name')
ext = Extension('name', ['file1', 'file2']) ext = Extension('name', ['file1', 'file2'])
self.assertEquals(ext.sources, ['file1', 'file2']) self.assertEquals(ext.sources, ['file1', 'file2'])
......
...@@ -3,7 +3,7 @@ import unittest ...@@ -3,7 +3,7 @@ import unittest
import os import os
import shutil import shutil
from distutils.file_util import move_file, write_file, copy_file from distutils.file_util import move_file
from distutils import log from distutils import log
from distutils.tests import support from distutils.tests import support
...@@ -55,21 +55,6 @@ class FileUtilTestCase(support.TempdirManager, unittest.TestCase): ...@@ -55,21 +55,6 @@ class FileUtilTestCase(support.TempdirManager, unittest.TestCase):
wanted = ['moving %s -> %s' % (self.source, self.target_dir)] wanted = ['moving %s -> %s' % (self.source, self.target_dir)]
self.assertEquals(self._logs, wanted) self.assertEquals(self._logs, wanted)
def test_write_file(self):
lines = ['a', 'b', 'c']
dir = self.mkdtemp()
foo = os.path.join(dir, 'foo')
write_file(foo, lines)
content = [line.strip() for line in open(foo).readlines()]
self.assertEquals(content, lines)
def test_copy_file(self):
src_dir = self.mkdtemp()
foo = os.path.join(src_dir, 'foo')
write_file(foo, 'content')
dst_dir = self.mkdtemp()
copy_file(foo, dst_dir)
self.assertTrue(os.path.exists(os.path.join(dst_dir, 'foo')))
def test_suite(): def test_suite():
return unittest.makeSuite(FileUtilTestCase) return unittest.makeSuite(FileUtilTestCase)
......
"""Tests for distutils.filelist.""" """Tests for distutils.filelist."""
from os.path import join
import unittest import unittest
from test.support import captured_stdout
from distutils.filelist import glob_to_re, FileList from distutils.filelist import glob_to_re, FileList
from test.support import captured_stdout
from distutils import debug from distutils import debug
MANIFEST_IN = """\
include ok
include xo
exclude xo
include foo.tmp
global-include *.x
global-include *.txt
global-exclude *.tmp
recursive-include f *.oo
recursive-exclude global *.x
graft dir
prune dir3
"""
class FileListTestCase(unittest.TestCase): class FileListTestCase(unittest.TestCase):
def test_glob_to_re(self): def test_glob_to_re(self):
...@@ -34,34 +19,6 @@ class FileListTestCase(unittest.TestCase): ...@@ -34,34 +19,6 @@ class FileListTestCase(unittest.TestCase):
self.assertEquals(glob_to_re('foo????'), r'foo[^/][^/][^/][^/]\Z(?ms)') self.assertEquals(glob_to_re('foo????'), r'foo[^/][^/][^/][^/]\Z(?ms)')
self.assertEquals(glob_to_re(r'foo\\??'), r'foo\\\\[^/][^/]\Z(?ms)') self.assertEquals(glob_to_re(r'foo\\??'), r'foo\\\\[^/][^/]\Z(?ms)')
def test_process_template_line(self):
# testing all MANIFEST.in template patterns
file_list = FileList()
# simulated file list
file_list.allfiles = ['foo.tmp', 'ok', 'xo', 'four.txt',
join('global', 'one.txt'),
join('global', 'two.txt'),
join('global', 'files.x'),
join('global', 'here.tmp'),
join('f', 'o', 'f.oo'),
join('dir', 'graft-one'),
join('dir', 'dir2', 'graft2'),
join('dir3', 'ok'),
join('dir3', 'sub', 'ok.txt')
]
for line in MANIFEST_IN.split('\n'):
if line.strip() == '':
continue
file_list.process_template_line(line)
wanted = ['ok', 'four.txt', join('global', 'one.txt'),
join('global', 'two.txt'), join('f', 'o', 'f.oo'),
join('dir', 'graft-one'), join('dir', 'dir2', 'graft2')]
self.assertEquals(file_list.files, wanted)
def test_debug_print(self): def test_debug_print(self):
file_list = FileList() file_list = FileList()
with captured_stdout() as stdout: with captured_stdout() as stdout:
......
...@@ -5,14 +5,12 @@ import os.path ...@@ -5,14 +5,12 @@ import os.path
import sys import sys
import unittest import unittest
import site import site
import sysconfig
from sysconfig import (get_scheme_names, _CONFIG_VARS, _INSTALL_SCHEMES,
get_config_var, get_path)
from test.support import captured_stdout from test.support import captured_stdout
from distutils.command.install import install from distutils.command.install import install
from distutils.command import install as install_module from distutils.command import install as install_module
from distutils.command.install import INSTALL_SCHEMES
from distutils.core import Distribution from distutils.core import Distribution
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
...@@ -38,23 +36,9 @@ class InstallTestCase(support.TempdirManager, ...@@ -38,23 +36,9 @@ class InstallTestCase(support.TempdirManager,
build_lib=os.path.join(builddir, "lib"), build_lib=os.path.join(builddir, "lib"),
) )
cmd = install(dist)
cmd.home = destination
posix_prefix = _INSTALL_SCHEMES['posix_prefix'] cmd.ensure_finalized()
old_posix_prefix = posix_prefix['platinclude']
posix_prefix['platinclude'] = \
'{platbase}/include/python{py_version_short}'
posix_home = _INSTALL_SCHEMES['posix_home']
old_posix_home = posix_home['platinclude']
posix_home['platinclude'] = '{base}/include/python'
try:
cmd = install(dist)
cmd.home = destination
cmd.ensure_finalized()
finally:
posix_home['platinclude'] = old_posix_home
posix_prefix['platinclude'] = old_posix_prefix
self.assertEqual(cmd.install_base, destination) self.assertEqual(cmd.install_base, destination)
self.assertEqual(cmd.install_platbase, destination) self.assertEqual(cmd.install_platbase, destination)
...@@ -79,19 +63,18 @@ class InstallTestCase(support.TempdirManager, ...@@ -79,19 +63,18 @@ class InstallTestCase(support.TempdirManager,
return return
# preparing the environement for the test # preparing the environement for the test
self.old_user_base = get_config_var('userbase') self.old_user_base = site.USER_BASE
self.old_user_site = get_path('purelib', '%s_user' % os.name) self.old_user_site = site.USER_SITE
self.tmpdir = self.mkdtemp() self.tmpdir = self.mkdtemp()
self.user_base = os.path.join(self.tmpdir, 'B') self.user_base = os.path.join(self.tmpdir, 'B')
self.user_site = os.path.join(self.tmpdir, 'S') self.user_site = os.path.join(self.tmpdir, 'S')
_CONFIG_VARS['userbase'] = self.user_base site.USER_BASE = self.user_base
scheme = _INSTALL_SCHEMES['%s_user' % os.name] site.USER_SITE = self.user_site
scheme['purelib'] = self.user_site install_module.USER_BASE = self.user_base
install_module.USER_SITE = self.user_site
def _expanduser(path): def _expanduser(path):
if path[0] == '~': return self.tmpdir
path = os.path.normpath(self.tmpdir) + path[1:]
return path
self.old_expand = os.path.expanduser self.old_expand = os.path.expanduser
os.path.expanduser = _expanduser os.path.expanduser = _expanduser
...@@ -99,17 +82,19 @@ class InstallTestCase(support.TempdirManager, ...@@ -99,17 +82,19 @@ class InstallTestCase(support.TempdirManager,
# this is the actual test # this is the actual test
self._test_user_site() self._test_user_site()
finally: finally:
_CONFIG_VARS['userbase'] = self.old_user_base site.USER_BASE = self.old_user_base
scheme['purelib'] = self.old_user_site site.USER_SITE = self.old_user_site
install_module.USER_BASE = self.old_user_base
install_module.USER_SITE = self.old_user_site
os.path.expanduser = self.old_expand os.path.expanduser = self.old_expand
def _test_user_site(self): def _test_user_site(self):
schemes = get_scheme_names() for key in ('nt_user', 'unix_user', 'os2_home'):
for key in ('nt_user', 'posix_user', 'os2_home'): self.assertTrue(key in INSTALL_SCHEMES)
self.assertTrue(key in schemes)
dist = Distribution({'name': 'xx'}) dist = Distribution({'name': 'xx'})
cmd = install(dist) cmd = install(dist)
# making sure the user option is there # making sure the user option is there
options = [name for name, short, lable in options = [name for name, short, lable in
cmd.user_options] cmd.user_options]
...@@ -200,7 +185,7 @@ class InstallTestCase(support.TempdirManager, ...@@ -200,7 +185,7 @@ class InstallTestCase(support.TempdirManager,
with open(cmd.record) as f: with open(cmd.record) as f:
self.assertEquals(len(f.readlines()), 1) self.assertEquals(len(f.readlines()), 1)
def _test_debug_mode(self): def test_debug_mode(self):
# this covers the code called when DEBUG is set # this covers the code called when DEBUG is set
old_logs_len = len(self.logs) old_logs_len = len(self.logs)
install_module.DEBUG = True install_module.DEBUG = True
......
"""Tests for distutils.command.install_data.""" """Tests for distutils.command.install_data."""
import os
import sys import sys
import os
import unittest import unittest
from distutils.command.install_lib import install_lib from distutils.command.install_lib import install_lib
...@@ -31,7 +31,9 @@ class InstallLibTestCase(support.TempdirManager, ...@@ -31,7 +31,9 @@ class InstallLibTestCase(support.TempdirManager,
cmd.finalize_options() cmd.finalize_options()
self.assertEquals(cmd.optimize, 2) self.assertEquals(cmd.optimize, 2)
def _setup_byte_compile(self): @unittest.skipUnless(not sys.dont_write_bytecode,
'byte-compile not supported')
def test_byte_compile(self):
pkg_dir, dist = self.create_dist() pkg_dir, dist = self.create_dist()
cmd = install_lib(dist) cmd = install_lib(dist)
cmd.compile = cmd.optimize = 1 cmd.compile = cmd.optimize = 1
...@@ -39,15 +41,8 @@ class InstallLibTestCase(support.TempdirManager, ...@@ -39,15 +41,8 @@ class InstallLibTestCase(support.TempdirManager,
f = os.path.join(pkg_dir, 'foo.py') f = os.path.join(pkg_dir, 'foo.py')
self.write_file(f, '# python file') self.write_file(f, '# python file')
cmd.byte_compile([f]) cmd.byte_compile([f])
return pkg_dir self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyc')))
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyo')))
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile not enabled')
def test_byte_compile(self):
pkg_dir = self._setup_byte_compile()
if sys.flags.optimize < 1:
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyc')))
else:
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyo')))
def test_get_outputs(self): def test_get_outputs(self):
pkg_dir, dist = self.create_dist() pkg_dir, dist = self.create_dist()
......
...@@ -202,10 +202,10 @@ class RegisterTestCase(PyPIRCCommandTestCase): ...@@ -202,10 +202,10 @@ class RegisterTestCase(PyPIRCCommandTestCase):
self.assertRaises(DistutilsSetupError, cmd.run) self.assertRaises(DistutilsSetupError, cmd.run)
# we don't test the reSt feature if docutils # we don't test the reSt feature if docutils
# is not installed or we our on py3k # is not installed
try: try:
import docutils import docutils
except Exception: except ImportError:
return return
# metadata are OK but long_description is broken # metadata are OK but long_description is broken
......
...@@ -3,22 +3,6 @@ import os ...@@ -3,22 +3,6 @@ import os
import unittest import unittest
import shutil import shutil
import zipfile import zipfile
import tarfile
# zlib is not used here, but if it's not available
# the tests that use zipfile may fail
try:
import zlib
except ImportError:
zlib = None
try:
import grp
import pwd
UID_GID_SUPPORT = True
except ImportError:
UID_GID_SUPPORT = False
from os.path import join from os.path import join
import sys import sys
import tempfile import tempfile
...@@ -95,7 +79,6 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -95,7 +79,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.warn = _warn cmd.warn = _warn
return dist, cmd return dist, cmd
@unittest.skipUnless(zlib, "requires zlib")
def test_prune_file_list(self): def test_prune_file_list(self):
# this test creates a package with some vcs dirs in it # this test creates a package with some vcs dirs in it
# and launch sdist to make sure they get pruned # and launch sdist to make sure they get pruned
...@@ -137,7 +120,6 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -137,7 +120,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
# making sure everything has been pruned correctly # making sure everything has been pruned correctly
self.assertEquals(len(content), 4) self.assertEquals(len(content), 4)
@unittest.skipUnless(zlib, "requires zlib")
def test_make_distribution(self): def test_make_distribution(self):
# check if tar and gzip are installed # check if tar and gzip are installed
...@@ -174,7 +156,6 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -174,7 +156,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
self.assertEquals(result, self.assertEquals(result,
['fake-1.0.tar', 'fake-1.0.tar.gz']) ['fake-1.0.tar', 'fake-1.0.tar.gz'])
@unittest.skipUnless(zlib, "requires zlib")
def test_add_defaults(self): def test_add_defaults(self):
# http://bugs.python.org/issue2279 # http://bugs.python.org/issue2279
...@@ -236,7 +217,6 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -236,7 +217,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
manifest = open(join(self.tmp_dir, 'MANIFEST')).read() manifest = open(join(self.tmp_dir, 'MANIFEST')).read()
self.assertEquals(manifest, MANIFEST % {'sep': os.sep}) self.assertEquals(manifest, MANIFEST % {'sep': os.sep})
@unittest.skipUnless(zlib, "requires zlib")
def test_metadata_check_option(self): def test_metadata_check_option(self):
# testing the `medata-check` option # testing the `medata-check` option
dist, cmd = self.get_cmd(metadata={}) dist, cmd = self.get_cmd(metadata={})
...@@ -296,57 +276,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -296,57 +276,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.formats = 'supazipa' cmd.formats = 'supazipa'
self.assertRaises(DistutilsOptionError, cmd.finalize_options) self.assertRaises(DistutilsOptionError, cmd.finalize_options)
@unittest.skipUnless(zlib, "requires zlib")
@unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
def test_make_distribution_owner_group(self):
# check if tar and gzip are installed
if (find_executable('tar') is None or
find_executable('gzip') is None):
return
# now building a sdist
dist, cmd = self.get_cmd()
# creating a gztar and specifying the owner+group
cmd.formats = ['gztar']
cmd.owner = pwd.getpwuid(0)[0]
cmd.group = grp.getgrgid(0)[0]
cmd.ensure_finalized()
cmd.run()
# making sure we have the good rights
archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
archive = tarfile.open(archive_name)
try:
for member in archive.getmembers():
self.assertEquals(member.uid, 0)
self.assertEquals(member.gid, 0)
finally:
archive.close()
# building a sdist again
dist, cmd = self.get_cmd()
# creating a gztar
cmd.formats = ['gztar']
cmd.ensure_finalized()
cmd.run()
# making sure we have the good rights
archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
archive = tarfile.open(archive_name)
# note that we are not testing the group ownership here
# because, depending on the platforms and the container
# rights (see #7408)
try:
for member in archive.getmembers():
self.assertEquals(member.uid, os.getuid())
finally:
archive.close()
@unittest.skipUnless(zlib, "requires zlib")
def test_get_file_list(self): def test_get_file_list(self):
# make sure MANIFEST is recalculated # make sure MANIFEST is recalculated
dist, cmd = self.get_cmd() dist, cmd = self.get_cmd()
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
import os import os
import test import test
import unittest import unittest
import shutil
from distutils import sysconfig from distutils import sysconfig
from distutils.ccompiler import get_default_compiler
from distutils.tests import support from distutils.tests import support
from test.support import TESTFN, run_unittest from test.support import TESTFN, run_unittest
...@@ -26,7 +26,10 @@ class SysconfigTestCase(support.EnvironGuard, ...@@ -26,7 +26,10 @@ class SysconfigTestCase(support.EnvironGuard,
elif os.path.isdir(TESTFN): elif os.path.isdir(TESTFN):
shutil.rmtree(TESTFN) shutil.rmtree(TESTFN)
@support.capture_warnings def test_get_config_h_filename(self):
config_h = sysconfig.get_config_h_filename()
self.assertTrue(os.path.isfile(config_h), config_h)
def test_get_python_lib(self): def test_get_python_lib(self):
lib_dir = sysconfig.get_python_lib() lib_dir = sysconfig.get_python_lib()
# XXX doesn't work on Linux when Python was never installed before # XXX doesn't work on Linux when Python was never installed before
...@@ -34,11 +37,7 @@ class SysconfigTestCase(support.EnvironGuard, ...@@ -34,11 +37,7 @@ class SysconfigTestCase(support.EnvironGuard,
# test for pythonxx.lib? # test for pythonxx.lib?
self.assertNotEqual(sysconfig.get_python_lib(), self.assertNotEqual(sysconfig.get_python_lib(),
sysconfig.get_python_lib(prefix=TESTFN)) sysconfig.get_python_lib(prefix=TESTFN))
_sysconfig = __import__('sysconfig')
res = sysconfig.get_python_lib(True, True)
self.assertEquals(_sysconfig.get_path('platstdlib'), res)
@support.capture_warnings
def test_get_python_inc(self): def test_get_python_inc(self):
inc_dir = sysconfig.get_python_inc() inc_dir = sysconfig.get_python_inc()
# This is not much of a test. We make sure Python.h exists # This is not much of a test. We make sure Python.h exists
...@@ -48,7 +47,31 @@ class SysconfigTestCase(support.EnvironGuard, ...@@ -48,7 +47,31 @@ class SysconfigTestCase(support.EnvironGuard,
python_h = os.path.join(inc_dir, "Python.h") python_h = os.path.join(inc_dir, "Python.h")
self.assertTrue(os.path.isfile(python_h), python_h) self.assertTrue(os.path.isfile(python_h), python_h)
@support.capture_warnings def test_get_config_vars(self):
cvars = sysconfig.get_config_vars()
self.assertTrue(isinstance(cvars, dict))
self.assertTrue(cvars)
def test_customize_compiler(self):
# not testing if default compiler is not unix
if get_default_compiler() != 'unix':
return
os.environ['AR'] = 'my_ar'
os.environ['ARFLAGS'] = '-arflags'
# make sure AR gets caught
class compiler:
compiler_type = 'unix'
def set_executables(self, **kw):
self.exes = kw
comp = compiler()
sysconfig.customize_compiler(comp)
self.assertEquals(comp.exes['archiver'], 'my_ar -arflags')
def test_parse_makefile_base(self): def test_parse_makefile_base(self):
self.makefile = TESTFN self.makefile = TESTFN
fd = open(self.makefile, 'w') fd = open(self.makefile, 'w')
......
"""Tests for distutils.unixccompiler.""" """Tests for distutils.unixccompiler."""
import sys import sys
import unittest import unittest
import sysconfig
from distutils import sysconfig
from distutils.unixccompiler import UnixCCompiler from distutils.unixccompiler import UnixCCompiler
class UnixCCompilerTestCase(unittest.TestCase): class UnixCCompilerTestCase(unittest.TestCase):
...@@ -114,14 +114,6 @@ class UnixCCompilerTestCase(unittest.TestCase): ...@@ -114,14 +114,6 @@ class UnixCCompilerTestCase(unittest.TestCase):
sysconfig.get_config_var = gcv sysconfig.get_config_var = gcv
self.assertEqual(self.cc.rpath_foo(), '-R/foo') self.assertEqual(self.cc.rpath_foo(), '-R/foo')
# AIX C/C++ linker
sys.platform = 'aix'
def gcv(v):
return 'xxx'
sysconfig.get_config_var = gcv
self.assertEqual(self.cc.rpath_foo(), '-blibpath:/foo')
def test_suite(): def test_suite():
return unittest.makeSuite(UnixCCompilerTestCase) return unittest.makeSuite(UnixCCompilerTestCase)
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
import sys import sys
import os import os
import unittest import unittest
import http.client as httpclient
from distutils.command import upload as upload_mod
from distutils.command.upload import upload from distutils.command.upload import upload
from distutils.core import Distribution from distutils.core import Distribution
...@@ -38,37 +38,48 @@ index-servers = ...@@ -38,37 +38,48 @@ index-servers =
[server1] [server1]
username:me username:me
""" """
class Response(object):
def __init__(self, status=200, reason='OK'):
self.status = status
self.reason = reason
class FakeOpen(object): class FakeConnection(object):
def __init__(self, url): def __init__(self):
self.url = url self.requests = []
if not isinstance(url, str): self.headers = []
self.req = url self.body = ''
else:
self.req = None
self.msg = 'OK'
def getcode(self): def __call__(self, netloc):
return 200 return self
def connect(self):
pass
endheaders = connect
def putrequest(self, method, url):
self.requests.append((method, url))
def putheader(self, name, value):
self.headers.append((name, value))
def send(self, body):
self.body = body
def getresponse(self):
return Response()
class uploadTestCase(PyPIRCCommandTestCase): class uploadTestCase(PyPIRCCommandTestCase):
def setUp(self): def setUp(self):
super(uploadTestCase, self).setUp() super(uploadTestCase, self).setUp()
self.old_open = upload_mod.urlopen self.old_class = httpclient.HTTPConnection
upload_mod.urlopen = self._urlopen self.conn = httpclient.HTTPConnection = FakeConnection()
self.last_open = None
def tearDown(self): def tearDown(self):
upload_mod.urlopen = self.old_open httpclient.HTTPConnection = self.old_class
super(uploadTestCase, self).tearDown() super(uploadTestCase, self).tearDown()
def _urlopen(self, url):
self.last_open = FakeOpen(url)
return self.last_open
def test_finalize_options(self): def test_finalize_options(self):
# new format # new format
...@@ -113,15 +124,13 @@ class uploadTestCase(PyPIRCCommandTestCase): ...@@ -113,15 +124,13 @@ class uploadTestCase(PyPIRCCommandTestCase):
cmd.run() cmd.run()
# what did we send ? # what did we send ?
headers = dict(self.last_open.req.headers) headers = dict(self.conn.headers)
self.assertEquals(headers['Content-length'], '2087') self.assertEquals(headers['Content-length'], '2087')
self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) self.assertTrue(headers['Content-type'].startswith('multipart/form-data'))
self.assertEquals(self.last_open.req.get_method(), 'POST') self.assertFalse('\n' in headers['Authorization'])
self.assertEquals(self.last_open.req.get_full_url(),
'http://pypi.python.org/pypi') self.assertEquals(self.conn.requests, [('POST', '/pypi')])
self.assertTrue(b'xxx' in self.last_open.req.data) self.assert_((b'xxx') in self.conn.body)
auth = self.last_open.req.headers['Authorization']
self.assertFalse('\n' in auth)
def test_suite(): def test_suite():
return unittest.makeSuite(uploadTestCase) return unittest.makeSuite(uploadTestCase)
......
...@@ -3,33 +3,15 @@ import os ...@@ -3,33 +3,15 @@ import os
import sys import sys
import unittest import unittest
from copy import copy from copy import copy
from io import BytesIO
import subprocess
from sysconfig import get_config_vars, get_platform
from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
from distutils.util import (convert_path, change_root, from distutils.util import (get_platform, convert_path, change_root,
check_environ, split_quoted, strtobool, check_environ, split_quoted, strtobool,
rfc822_escape, get_compiler_versions, rfc822_escape, byte_compile)
_find_exe_version, _MAC_OS_X_LD_VERSION, from distutils import util # used to patch _environ_checked
byte_compile) from distutils.sysconfig import get_config_vars
from distutils import util from distutils import sysconfig
from distutils.tests import support from distutils.tests import support
from distutils.version import LooseVersion
class FakePopen(object):
test_class = None
def __init__(self, cmd, shell, stdout, stderr):
self.cmd = cmd.split()[0]
exes = self.test_class._exes
if self.cmd not in exes:
# we don't want to call the system, returning an empty
# output so it doesn't match
self.stdout = BytesIO()
self.stderr = BytesIO()
else:
self.stdout = BytesIO(exes[self.cmd])
self.stderr = BytesIO()
class UtilTestCase(support.EnvironGuard, unittest.TestCase): class UtilTestCase(support.EnvironGuard, unittest.TestCase):
...@@ -43,7 +25,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase): ...@@ -43,7 +25,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
self.join = os.path.join self.join = os.path.join
self.isabs = os.path.isabs self.isabs = os.path.isabs
self.splitdrive = os.path.splitdrive self.splitdrive = os.path.splitdrive
#self._config_vars = copy(sysconfig._config_vars) self._config_vars = copy(sysconfig._config_vars)
# patching os.uname # patching os.uname
if hasattr(os, 'uname'): if hasattr(os, 'uname'):
...@@ -52,17 +34,8 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase): ...@@ -52,17 +34,8 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
else: else:
self.uname = None self.uname = None
self._uname = None self._uname = None
os.uname = self._get_uname
# patching POpen os.uname = self._get_uname
self.old_find_executable = util.find_executable
util.find_executable = self._find_executable
self._exes = {}
self.old_popen = subprocess.Popen
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
FakePopen.test_class = self
subprocess.Popen = FakePopen
def tearDown(self): def tearDown(self):
# getting back the environment # getting back the environment
...@@ -77,11 +50,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase): ...@@ -77,11 +50,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
os.uname = self.uname os.uname = self.uname
else: else:
del os.uname del os.uname
#sysconfig._config_vars = copy(self._config_vars) sysconfig._config_vars = copy(self._config_vars)
util.find_executable = self.old_find_executable
subprocess.Popen = self.old_popen
sys.old_stdout = self.old_stdout
sys.old_stderr = self.old_stderr
super(UtilTestCase, self).tearDown() super(UtilTestCase, self).tearDown()
def _set_uname(self, uname): def _set_uname(self, uname):
...@@ -91,11 +60,103 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase): ...@@ -91,11 +60,103 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
return self._uname return self._uname
def test_get_platform(self): def test_get_platform(self):
platform = util.get_platform()
self.assertEquals(platform, get_platform()) # windows XP, 32bits
util.set_platform('MyOwnPlatform') os.name = 'nt'
self.assertEquals('MyOwnPlatform', util.get_platform()) sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
util.set_platform(platform) '[MSC v.1310 32 bit (Intel)]')
sys.platform = 'win32'
self.assertEquals(get_platform(), 'win32')
# windows XP, amd64
os.name = 'nt'
sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
'[MSC v.1310 32 bit (Amd64)]')
sys.platform = 'win32'
self.assertEquals(get_platform(), 'win-amd64')
# windows XP, itanium
os.name = 'nt'
sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
'[MSC v.1310 32 bit (Itanium)]')
sys.platform = 'win32'
self.assertEquals(get_platform(), 'win-ia64')
# macbook
os.name = 'posix'
sys.version = ('2.5 (r25:51918, Sep 19 2006, 08:49:13) '
'\n[GCC 4.0.1 (Apple Computer, Inc. build 5341)]')
sys.platform = 'darwin'
self._set_uname(('Darwin', 'macziade', '8.11.1',
('Darwin Kernel Version 8.11.1: '
'Wed Oct 10 18:23:28 PDT 2007; '
'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
'-fwrapv -O3 -Wall -Wstrict-prototypes')
cursize = sys.maxsize
sys.maxsize = (2 ** 31)-1
try:
self.assertEquals(get_platform(), 'macosx-10.3-i386')
finally:
sys.maxsize = cursize
# macbook with fat binaries (fat, universal or fat64)
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3')
self.assertEquals(get_platform(), 'macosx-10.4-fat')
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3')
self.assertEquals(get_platform(), 'macosx-10.4-intel')
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3')
self.assertEquals(get_platform(), 'macosx-10.4-fat3')
get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3')
self.assertEquals(get_platform(), 'macosx-10.4-universal')
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3')
self.assertEquals(get_platform(), 'macosx-10.4-fat64')
for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3'%(arch,))
self.assertEquals(get_platform(), 'macosx-10.4-%s'%(arch,))
# linux debian sarge
os.name = 'posix'
sys.version = ('2.3.5 (#1, Jul 4 2007, 17:28:59) '
'\n[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]')
sys.platform = 'linux2'
self._set_uname(('Linux', 'aglae', '2.6.21.1dedibox-r7',
'#1 Mon Apr 30 17:25:38 CEST 2007', 'i686'))
self.assertEquals(get_platform(), 'linux-i686')
# XXX more platforms to tests here
def test_convert_path(self): def test_convert_path(self):
# linux/mac # linux/mac
...@@ -199,70 +260,6 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase): ...@@ -199,70 +260,6 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
'header%(8s)s') % {'8s': '\n'+8*' '} 'header%(8s)s') % {'8s': '\n'+8*' '}
self.assertEquals(res, wanted) self.assertEquals(res, wanted)
def test_find_exe_version(self):
# the ld version scheme under MAC OS is:
# ^@(#)PROGRAM:ld PROJECT:ld64-VERSION
#
# where VERSION is a 2-digit number for major
# revisions. For instance under Leopard, it's
# currently 77
#
# Dots are used when branching is done.
#
# The SnowLeopard ld64 is currently 95.2.12
for output, version in ((b'@(#)PROGRAM:ld PROJECT:ld64-77', '77'),
(b'@(#)PROGRAM:ld PROJECT:ld64-95.2.12',
'95.2.12')):
result = _MAC_OS_X_LD_VERSION.search(output)
self.assertEquals(result.group(1).decode(), version)
def _find_executable(self, name):
if name in self._exes:
return name
return None
def test_get_compiler_versions(self):
# get_versions calls distutils.spawn.find_executable on
# 'gcc', 'ld' and 'dllwrap'
self.assertEquals(get_compiler_versions(), (None, None, None))
# Let's fake we have 'gcc' and it returns '3.4.5'
self._exes['gcc'] = b'gcc (GCC) 3.4.5 (mingw special)\nFSF'
res = get_compiler_versions()
self.assertEquals(str(res[0]), '3.4.5')
# and let's see what happens when the version
# doesn't match the regular expression
# (\d+\.\d+(\.\d+)*)
self._exes['gcc'] = b'very strange output'
res = get_compiler_versions()
self.assertEquals(res[0], None)
# same thing for ld
if sys.platform != 'darwin':
self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
res = get_compiler_versions()
self.assertEquals(str(res[1]), '2.17.50')
self._exes['ld'] = b'@(#)PROGRAM:ld PROJECT:ld64-77'
res = get_compiler_versions()
self.assertEquals(res[1], None)
else:
self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
res = get_compiler_versions()
self.assertEquals(res[1], None)
self._exes['ld'] = b'@(#)PROGRAM:ld PROJECT:ld64-77'
res = get_compiler_versions()
self.assertEquals(str(res[1]), '77')
# and dllwrap
self._exes['dllwrap'] = b'GNU dllwrap 2.17.50 20060824\nFSF'
res = get_compiler_versions()
self.assertEquals(str(res[2]), '2.17.50')
self._exes['dllwrap'] = b'Cheese Wrap'
res = get_compiler_versions()
self.assertEquals(res[2], None)
def test_dont_write_bytecode(self): def test_dont_write_bytecode(self):
# makes sure byte_compile raise a DistutilsError # makes sure byte_compile raise a DistutilsError
# if sys.dont_write_bytecode is True # if sys.dont_write_bytecode is True
......
...@@ -6,8 +6,8 @@ lines, and joining lines with backslashes.""" ...@@ -6,8 +6,8 @@ lines, and joining lines with backslashes."""
__revision__ = "$Id$" __revision__ = "$Id$"
import sys import sys, os, io
import io
class TextFile: class TextFile:
"""Provides a file-like object that takes care of all the things you """Provides a file-like object that takes care of all the things you
......
...@@ -17,6 +17,7 @@ __revision__ = "$Id$" ...@@ -17,6 +17,7 @@ __revision__ = "$Id$"
import os, sys, re import os, sys, re
from distutils import sysconfig
from distutils.dep_util import newer from distutils.dep_util import newer
from distutils.ccompiler import \ from distutils.ccompiler import \
CCompiler, gen_preprocess_options, gen_lib_options CCompiler, gen_preprocess_options, gen_lib_options
...@@ -24,7 +25,6 @@ from distutils.errors import \ ...@@ -24,7 +25,6 @@ from distutils.errors import \
DistutilsExecError, CompileError, LibError, LinkError DistutilsExecError, CompileError, LibError, LinkError
from distutils import log from distutils import log
# XXX Things not currently handled: # XXX Things not currently handled:
# * optimization/debug/warning flags; we just use whatever's in Python's # * optimization/debug/warning flags; we just use whatever's in Python's
# Makefile and live with it. Is this adequate? If not, we might # Makefile and live with it. Is this adequate? If not, we might
...@@ -74,7 +74,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args): ...@@ -74,7 +74,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args):
if 'ARCHFLAGS' in os.environ and not stripArch: if 'ARCHFLAGS' in os.environ and not stripArch:
# User specified different -arch flags in the environ, # User specified different -arch flags in the environ,
# see also the sysconfig # see also distutils.sysconfig
compiler_so = compiler_so + os.environ['ARCHFLAGS'].split() compiler_so = compiler_so + os.environ['ARCHFLAGS'].split()
if stripSysroot: if stripSysroot:
...@@ -281,9 +281,7 @@ class UnixCCompiler(CCompiler): ...@@ -281,9 +281,7 @@ class UnixCCompiler(CCompiler):
# this time, there's no way to determine this information from # this time, there's no way to determine this information from
# the configuration data stored in the Python installation, so # the configuration data stored in the Python installation, so
# we use this hack. # we use this hack.
_sysconfig = __import__('sysconfig') compiler = os.path.basename(sysconfig.get_config_var("CC"))
compiler = os.path.basename(_sysconfig.get_config_var("CC"))
if sys.platform[:6] == "darwin": if sys.platform[:6] == "darwin":
# MacOSX's linker doesn't understand the -R flag at all # MacOSX's linker doesn't understand the -R flag at all
return "-L" + dir return "-L" + dir
...@@ -293,24 +291,23 @@ class UnixCCompiler(CCompiler): ...@@ -293,24 +291,23 @@ class UnixCCompiler(CCompiler):
return ["+s", "-L" + dir] return ["+s", "-L" + dir]
elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5": elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
return ["-rpath", dir] 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: else:
# No idea how --enable-new-dtags would be passed on to if self._is_gcc(compiler):
# ld if this system was using GNU ld. Don't know if a # gcc on non-GNU systems does not need -Wl, but can
# system like this even exists. # use it anyway. Since distutils has always passed in
return "-R" + dir # -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
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 library_option(self, lib): def library_option(self, lib):
return "-l" + lib return "-l" + lib
...@@ -324,8 +321,7 @@ class UnixCCompiler(CCompiler): ...@@ -324,8 +321,7 @@ class UnixCCompiler(CCompiler):
# On OSX users can specify an alternate SDK using # On OSX users can specify an alternate SDK using
# '-isysroot', calculate the SDK root if it is specified # '-isysroot', calculate the SDK root if it is specified
# (and use it further on) # (and use it further on)
_sysconfig = __import__('sysconfig') cflags = sysconfig.get_config_var('CFLAGS')
cflags = _sysconfig.get_config_var('CFLAGS')
m = re.search(r'-isysroot\s+(\S+)', cflags) m = re.search(r'-isysroot\s+(\S+)', cflags)
if m is None: if m is None:
sysroot = '/' sysroot = '/'
......
...@@ -7,40 +7,182 @@ one of the other *util.py modules. ...@@ -7,40 +7,182 @@ one of the other *util.py modules.
__revision__ = "$Id$" __revision__ = "$Id$"
import sys, os, string, re import sys, os, string, re
from distutils.errors import DistutilsPlatformError from distutils.errors import DistutilsPlatformError
from distutils.dep_util import newer from distutils.dep_util import newer
from distutils.spawn import spawn, find_executable from distutils.spawn import spawn
from distutils import log from distutils import log
from distutils.version import LooseVersion
from distutils.errors import DistutilsByteCompileError from distutils.errors import DistutilsByteCompileError
_sysconfig = __import__('sysconfig') def get_platform ():
_PLATFORM = None """Return a string that identifies the current platform. This is used
mainly to distinguish platform-specific build directories and
platform-specific built distributions. Typically includes the OS name
and version and the architecture (as supplied by 'os.uname()'),
although the exact information included depends on the OS; eg. for IRIX
the architecture isn't particularly important (IRIX only runs on SGI
hardware), but for Linux the kernel version isn't particularly
important.
Examples of returned values:
linux-i586
linux-alpha (?)
solaris-2.6-sun4u
irix-5.3
irix64-6.2
Windows will return one of:
win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
win-ia64 (64bit Windows on Itanium)
win32 (all others - specifically, sys.platform is returned)
For other non-POSIX platforms, currently just returns 'sys.platform'.
"""
if os.name == 'nt':
# sniff sys.version for architecture.
prefix = " bit ("
i = sys.version.find(prefix)
if i == -1:
return sys.platform
j = sys.version.find(")", i)
look = sys.version[i+len(prefix):j].lower()
if look == 'amd64':
return 'win-amd64'
if look == 'itanium':
return 'win-ia64'
return sys.platform
if os.name != "posix" or not hasattr(os, 'uname'):
# XXX what about the architecture? NT is Intel or Alpha,
# Mac OS is M68k or PPC, etc.
return sys.platform
# Try to distinguish various flavours of Unix
(osname, host, release, version, machine) = os.uname()
# Convert the OS name to lowercase, remove '/' characters
# (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
osname = osname.lower().replace('/', '')
machine = machine.replace(' ', '_')
machine = machine.replace('/', '-')
if osname[:5] == "linux":
# At least on Linux/Intel, 'machine' is the processor --
# i386, etc.
# XXX what about Alpha, SPARC, etc?
return "%s-%s" % (osname, machine)
elif osname[:5] == "sunos":
if release[0] >= "5": # SunOS 5 == Solaris 2
osname = "solaris"
release = "%d.%s" % (int(release[0]) - 3, release[2:])
# fall through to standard osname-release-machine representation
elif osname[:4] == "irix": # could be "irix64"!
return "%s-%s" % (osname, release)
elif osname[:3] == "aix":
return "%s-%s.%s" % (osname, version, release)
elif osname[:6] == "cygwin":
osname = "cygwin"
rel_re = re.compile (r'[\d.]+', re.ASCII)
m = rel_re.match(release)
if m:
release = m.group()
elif osname[:6] == "darwin":
#
# For our purposes, we'll assume that the system version from
# distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
# to. This makes the compatibility story a bit more sane because the
# machine is going to compile and link as if it were
# MACOSX_DEPLOYMENT_TARGET.
from distutils.sysconfig import get_config_vars
cfgvars = get_config_vars()
macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET')
if not macver:
macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
if 1:
# Always calculate the release of the running machine,
# needed to determine if we can build fat binaries or not.
macrelease = macver
# Get the system version. Reading this plist is a documented
# way to get the system version (see the documentation for
# the Gestalt Manager)
try:
f = open('/System/Library/CoreServices/SystemVersion.plist')
except IOError:
# We're on a plain darwin box, fall back to the default
# behaviour.
pass
else:
m = re.search(
r'<key>ProductUserVisibleVersion</key>\s*' +
r'<string>(.*?)</string>', f.read())
f.close()
if m is not None:
macrelease = '.'.join(m.group(1).split('.')[:2])
# else: fall back to the default behaviour
if not macver:
macver = macrelease
if macver:
from distutils.sysconfig import get_config_vars
release = macver
osname = "macosx"
if (macrelease + '.') >= '10.4.' and \
'-arch' in get_config_vars().get('CFLAGS', '').strip():
# The universal build will build fat binaries, but not on
# systems before 10.4
#
# Try to detect 4-way universal builds, those have machine-type
# 'universal' instead of 'fat'.
machine = 'fat'
cflags = get_config_vars().get('CFLAGS')
archs = re.findall('-arch\s+(\S+)', cflags)
archs = tuple(sorted(set(archs)))
if len(archs) == 1:
machine = archs[0]
elif archs == ('i386', 'ppc'):
machine = 'fat'
elif archs == ('i386', 'x86_64'):
machine = 'intel'
elif archs == ('i386', 'ppc', 'x86_64'):
machine = 'fat3'
elif archs == ('ppc64', 'x86_64'):
machine = 'fat64'
elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
machine = 'universal'
else:
raise ValueError(
"Don't know machine value for archs=%r"%(archs,))
def get_platform(): elif machine == 'i386':
"""Return a string that identifies the current platform. # On OSX the machine type returned by uname is always the
# 32-bit variant, even if the executable architecture is
# the 64-bit variant
if sys.maxsize >= 2**32:
machine = 'x86_64'
By default, will return the value returned by sysconfig.get_platform(), elif machine in ('PowerPC', 'Power_Macintosh'):
but it can be changed by calling set_platform(). # Pick a sane name for the PPC architecture.
""" machine = 'ppc'
global _PLATFORM
if _PLATFORM is None:
_PLATFORM = _sysconfig.get_platform()
return _PLATFORM
def set_platform(identifier): # See 'i386' case
"""Sets the platform string identifier returned by get_platform(). if sys.maxsize >= 2**32:
machine = 'ppc64'
Note that this change doesn't impact the value returned by return "%s-%s-%s" % (osname, release, machine)
sysconfig.get_platform() and is local to Distutils
""" # get_platform ()
global _PLATFORM
_PLATFORM = identifier
def convert_path(pathname):
"""Return 'pathname' as a name that will work on the native filesystem.
def convert_path (pathname):
"""Return 'pathname' as a name that will work on the native filesystem,
i.e. split it on '/' and put it back together again using the current i.e. split it on '/' and put it back together again using the current
directory separator. Needed because filenames in the setup script are directory separator. Needed because filenames in the setup script are
always supplied in Unix style, and have to be converted to the local always supplied in Unix style, and have to be converted to the local
...@@ -64,12 +206,12 @@ def convert_path(pathname): ...@@ -64,12 +206,12 @@ def convert_path(pathname):
return os.curdir return os.curdir
return os.path.join(*paths) return os.path.join(*paths)
# convert_path ()
def change_root(new_root, pathname):
"""Return 'pathname' with 'new_root' prepended.
If 'pathname' is relative, this is equivalent to def change_root (new_root, pathname):
"os.path.join(new_root,pathname)". """Return 'pathname' with 'new_root' prepended. If 'pathname' is
relative, this is equivalent to "os.path.join(new_root,pathname)".
Otherwise, it requires making 'pathname' relative and then joining the Otherwise, it requires making 'pathname' relative and then joining the
two, which is tricky on DOS/Windows and Mac OS. two, which is tricky on DOS/Windows and Mac OS.
""" """
...@@ -91,16 +233,23 @@ def change_root(new_root, pathname): ...@@ -91,16 +233,23 @@ def change_root(new_root, pathname):
path = path[1:] path = path[1:]
return os.path.join(new_root, path) return os.path.join(new_root, path)
else: elif os.name == 'mac':
raise DistutilsPlatformError("nothing known about " if not os.path.isabs(pathname):
"platform '%s'" % os.name) return os.path.join(new_root, pathname)
else:
# Chop off volume name from start of path
elements = pathname.split(":", 1)
pathname = ":" + elements[1]
return os.path.join(new_root, pathname)
_environ_checked = 0 else:
raise DistutilsPlatformError("nothing known about platform '%s'" % os.name)
def check_environ():
"""Ensure that 'os.environ' has all the environment variables needed.
We guarantee that users can use in config files, command-line options, _environ_checked = 0
def check_environ ():
"""Ensure that 'os.environ' has all the environment variables we
guarantee that users can use in config files, command-line options,
etc. Currently this includes: etc. Currently this includes:
HOME - user's home directory (Unix only) HOME - user's home directory (Unix only)
PLAT - description of the current platform, including hardware PLAT - description of the current platform, including hardware
...@@ -115,14 +264,14 @@ def check_environ(): ...@@ -115,14 +264,14 @@ def check_environ():
os.environ['HOME'] = pwd.getpwuid(os.getuid())[5] os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
if 'PLAT' not in os.environ: if 'PLAT' not in os.environ:
os.environ['PLAT'] = _sysconfig.get_platform() os.environ['PLAT'] = get_platform()
_environ_checked = 1 _environ_checked = 1
def subst_vars(s, local_vars):
"""Perform shell/Perl-style variable substitution on 'string'.
Every occurrence of '$' followed by a name is considered a variable, and def subst_vars (s, local_vars):
"""Perform shell/Perl-style variable substitution on 'string'. Every
occurrence of '$' followed by a name is considered a variable, and
variable is substituted by the value found in the 'local_vars' variable is substituted by the value found in the 'local_vars'
dictionary, or in 'os.environ' if it's not in 'local_vars'. dictionary, or in 'os.environ' if it's not in 'local_vars'.
'os.environ' is first checked/augmented to guarantee that it contains 'os.environ' is first checked/augmented to guarantee that it contains
...@@ -142,11 +291,12 @@ def subst_vars(s, local_vars): ...@@ -142,11 +291,12 @@ def subst_vars(s, local_vars):
except KeyError as var: except KeyError as var:
raise ValueError("invalid variable '$%s'" % var) raise ValueError("invalid variable '$%s'" % var)
def grok_environment_error(exc, prefix="error: "): # subst_vars ()
"""Generate a useful error message from an EnvironmentError.
This will generate an IOError or an OSError exception object.
Handles Python 1.5.1 and 1.5.2 styles, and def grok_environment_error (exc, prefix="error: "):
"""Generate a useful error message from an EnvironmentError (IOError or
OSError) exception object. Handles Python 1.5.1 and 1.5.2 styles, and
does what it can to deal with exception objects that don't have a does what it can to deal with exception objects that don't have a
filename (which happens when the error is due to a two-file operation, filename (which happens when the error is due to a two-file operation,
such as 'rename()' or 'link()'. Returns the error message as a string such as 'rename()' or 'link()'. Returns the error message as a string
...@@ -165,20 +315,18 @@ def grok_environment_error(exc, prefix="error: "): ...@@ -165,20 +315,18 @@ def grok_environment_error(exc, prefix="error: "):
return error return error
# Needed by 'split_quoted()' # Needed by 'split_quoted()'
_wordchars_re = _squote_re = _dquote_re = None _wordchars_re = _squote_re = _dquote_re = None
def _init_regex(): def _init_regex():
global _wordchars_re, _squote_re, _dquote_re global _wordchars_re, _squote_re, _dquote_re
_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
def split_quoted(s): def split_quoted (s):
"""Split a string up according to Unix shell-like rules for quotes and """Split a string up according to Unix shell-like rules for quotes and
backslashes. backslashes. In short: words are delimited by spaces, as long as those
In short: words are delimited by spaces, as long as those
spaces are not escaped by a backslash, or inside a quoted string. spaces are not escaped by a backslash, or inside a quoted string.
Single and double quotes are equivalent, and the quote characters can Single and double quotes are equivalent, and the quote characters can
be backslash-escaped. The backslash is stripped from any two-character be backslash-escaped. The backslash is stripped from any two-character
...@@ -186,6 +334,7 @@ def split_quoted(s): ...@@ -186,6 +334,7 @@ def split_quoted(s):
characters are stripped from any quoted string. Returns a list of characters are stripped from any quoted string. Returns a list of
words. words.
""" """
# This is a nice algorithm for splitting up a single string, since it # This is a nice algorithm for splitting up a single string, since it
# doesn't require character-by-character examination. It was a little # doesn't require character-by-character examination. It was a little
# bit of a brain-bender to get it working right, though... # bit of a brain-bender to get it working right, though...
...@@ -233,12 +382,13 @@ def split_quoted(s): ...@@ -233,12 +382,13 @@ def split_quoted(s):
return words return words
# split_quoted ()
def execute(func, args, msg=None, verbose=0, dry_run=0):
"""Perform some action that affects the outside world.
eg. by writing to the filesystem). Such actions are special because def execute (func, args, msg=None, verbose=0, dry_run=0):
they are disabled by the 'dry_run' flag. This method takes care of all """Perform some action that affects the outside world (eg. by
writing to the filesystem). Such actions are special because they
are disabled by the 'dry_run' flag. This method takes care of all
that bureaucracy for you; all you have to do is supply the that bureaucracy for you; all you have to do is supply the
function to call and an argument tuple for it (to embody the function to call and an argument tuple for it (to embody the
"external action" being performed), and an optional message to "external action" being performed), and an optional message to
...@@ -254,7 +404,7 @@ def execute(func, args, msg=None, verbose=0, dry_run=0): ...@@ -254,7 +404,7 @@ def execute(func, args, msg=None, verbose=0, dry_run=0):
func(*args) func(*args)
def strtobool(val): def strtobool (val):
"""Convert a string representation of truth to true (1) or false (0). """Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
...@@ -270,13 +420,15 @@ def strtobool(val): ...@@ -270,13 +420,15 @@ def strtobool(val):
raise ValueError("invalid truth value %r" % (val,)) raise ValueError("invalid truth value %r" % (val,))
def byte_compile(py_files, optimize=0, force=0, prefix=None, base_dir=None, def byte_compile (py_files,
verbose=1, dry_run=0, direct=None): optimize=0, force=0,
prefix=None, base_dir=None,
verbose=1, dry_run=0,
direct=None):
"""Byte-compile a collection of Python source files to either .pyc """Byte-compile a collection of Python source files to either .pyc
or .pyo files in the same directory. or .pyo files in the same directory. 'py_files' is a list of files
to compile; any files that don't end in ".py" are silently skipped.
'py_files' is a list of files to compile; any files that don't end in 'optimize' must be one of the following:
".py" are silently skipped. 'optimize' must be one of the following:
0 - don't optimize (generate .pyc) 0 - don't optimize (generate .pyc)
1 - normal optimization (like "python -O") 1 - normal optimization (like "python -O")
2 - extra optimization (like "python -OO") 2 - extra optimization (like "python -OO")
...@@ -392,8 +544,8 @@ byte_compile(files, optimize=%r, force=%r, ...@@ -392,8 +544,8 @@ byte_compile(files, optimize=%r, force=%r,
dfile = file dfile = file
if prefix: if prefix:
if file[:len(prefix)] != prefix: if file[:len(prefix)] != prefix:
raise ValueError("invalid prefix: filename %r doesn't " raise ValueError("invalid prefix: filename %r doesn't start with %r"
"start with %r" % (file, prefix)) % (file, prefix))
dfile = dfile[len(prefix):] dfile = dfile[len(prefix):]
if base_dir: if base_dir:
dfile = os.path.join(base_dir, dfile) dfile = os.path.join(base_dir, dfile)
...@@ -408,8 +560,9 @@ byte_compile(files, optimize=%r, force=%r, ...@@ -408,8 +560,9 @@ byte_compile(files, optimize=%r, force=%r,
log.debug("skipping byte-compilation of %s to %s", log.debug("skipping byte-compilation of %s to %s",
file, cfile_base) file, cfile_base)
# byte_compile ()
def rfc822_escape(header): def rfc822_escape (header):
"""Return a version of the string escaped for inclusion in an """Return a version of the string escaped for inclusion in an
RFC-822 header, by ensuring there are 8 spaces space after each newline. RFC-822 header, by ensuring there are 8 spaces space after each newline.
""" """
...@@ -417,56 +570,6 @@ def rfc822_escape(header): ...@@ -417,56 +570,6 @@ def rfc822_escape(header):
sep = '\n' + 8 * ' ' sep = '\n' + 8 * ' '
return sep.join(lines) return sep.join(lines)
_RE_VERSION = re.compile(b'(\d+\.\d+(\.\d+)*)')
_MAC_OS_X_LD_VERSION = re.compile(b'^@\(#\)PROGRAM:ld PROJECT:ld64-((\d+)(\.\d+)*)')
def _find_ld_version():
"""Finds the ld version. The version scheme differs under Mac OSX."""
if sys.platform == 'darwin':
return _find_exe_version('ld -v', _MAC_OS_X_LD_VERSION)
else:
return _find_exe_version('ld -v')
def _find_exe_version(cmd, pattern=_RE_VERSION):
"""Find the version of an executable by running `cmd` in the shell.
`pattern` is a compiled regular expression. If not provided, default
to _RE_VERSION. If the command is not found, or the output does not
match the mattern, returns None.
"""
from subprocess import Popen, PIPE
executable = cmd.split()[0]
if find_executable(executable) is None:
return None
pipe = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
try:
stdout, stderr = pipe.stdout.read(), pipe.stderr.read()
finally:
pipe.stdout.close()
pipe.stderr.close()
# some commands like ld under MacOS X, will give the
# output in the stderr, rather than stdout.
if stdout != b'':
out_string = stdout
else:
out_string = stderr
result = pattern.search(out_string)
if result is None:
return None
return LooseVersion(result.group(1).decode())
def get_compiler_versions():
"""Returns a tuple providing the versions of gcc, ld and dllwrap
For each command, if a command is not found, None is returned.
Otherwise a LooseVersion instance is returned.
"""
gcc = _find_exe_version('gcc -dumpversion')
ld = _find_ld_version()
dllwrap = _find_exe_version('dllwrap --version')
return gcc, ld, dllwrap
# 2to3 support # 2to3 support
def run_2to3(files, fixer_names=None, options=None, explicit=None): def run_2to3(files, fixer_names=None, options=None, explicit=None):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment