aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/distutils
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/distutils')
-rw-r--r--Lib/distutils/__init__.py4
-rw-r--r--Lib/distutils/archive_util.py105
-rw-r--r--Lib/distutils/bcppcompiler.py37
-rw-r--r--Lib/distutils/ccompiler.py281
-rw-r--r--Lib/distutils/cmd.py112
-rw-r--r--Lib/distutils/command/__init__.py4
-rw-r--r--Lib/distutils/command/bdist.py28
-rw-r--r--Lib/distutils/command/bdist_dumb.py38
-rw-r--r--Lib/distutils/command/bdist_msi.py37
-rw-r--r--Lib/distutils/command/bdist_rpm.py103
-rw-r--r--Lib/distutils/command/bdist_wininst.py83
-rw-r--r--Lib/distutils/command/build.py17
-rw-r--r--Lib/distutils/command/build_clib.py48
-rw-r--r--Lib/distutils/command/build_ext.py129
-rw-r--r--Lib/distutils/command/build_py.py44
-rw-r--r--Lib/distutils/command/build_scripts.py88
-rw-r--r--Lib/distutils/command/check.py12
-rw-r--r--Lib/distutils/command/clean.py4
-rw-r--r--Lib/distutils/command/command_template20
-rw-r--r--Lib/distutils/command/config.py40
-rw-r--r--Lib/distutils/command/install.py272
-rw-r--r--Lib/distutils/command/install_data.py2
-rw-r--r--Lib/distutils/command/install_egg_info.py5
-rw-r--r--Lib/distutils/command/install_headers.py4
-rw-r--r--Lib/distutils/command/install_lib.py20
-rw-r--r--Lib/distutils/command/install_scripts.py18
-rw-r--r--Lib/distutils/command/register.py77
-rw-r--r--Lib/distutils/command/sdist.py51
-rw-r--r--Lib/distutils/command/upload.py120
-rw-r--r--Lib/distutils/command/wininst-9.0-amd64.exebin223744 -> 224256 bytes
-rw-r--r--Lib/distutils/command/wininst-9.0.exebin196096 -> 196096 bytes
-rw-r--r--Lib/distutils/config.py9
-rw-r--r--Lib/distutils/core.py71
-rw-r--r--Lib/distutils/cygwinccompiler.py235
-rw-r--r--Lib/distutils/debug.py2
-rw-r--r--Lib/distutils/dep_util.py67
-rw-r--r--Lib/distutils/dir_util.py37
-rw-r--r--Lib/distutils/dist.py242
-rw-r--r--Lib/distutils/emxccompiler.py24
-rw-r--r--Lib/distutils/errors.py49
-rw-r--r--Lib/distutils/extension.py82
-rw-r--r--Lib/distutils/fancy_getopt.py167
-rw-r--r--Lib/distutils/file_util.py95
-rw-r--r--Lib/distutils/filelist.py93
-rw-r--r--Lib/distutils/log.py4
-rw-r--r--Lib/distutils/msvc9compiler.py59
-rw-r--r--Lib/distutils/msvccompiler.py267
-rw-r--r--Lib/distutils/spawn.py67
-rw-r--r--Lib/distutils/sysconfig.py152
-rw-r--r--Lib/distutils/tests/__init__.py2
-rw-r--r--Lib/distutils/tests/setuptools_build_ext.py287
-rw-r--r--Lib/distutils/tests/setuptools_extension.py51
-rw-r--r--Lib/distutils/tests/support.py28
-rw-r--r--Lib/distutils/tests/test_archive_util.py154
-rw-r--r--Lib/distutils/tests/test_bdist.py6
-rw-r--r--Lib/distutils/tests/test_bdist_dumb.py37
-rw-r--r--Lib/distutils/tests/test_bdist_msi.py2
-rw-r--r--Lib/distutils/tests/test_bdist_rpm.py3
-rw-r--r--Lib/distutils/tests/test_bdist_wininst.py3
-rw-r--r--Lib/distutils/tests/test_build.py2
-rw-r--r--Lib/distutils/tests/test_build_clib.py2
-rw-r--r--Lib/distutils/tests/test_build_ext.py185
-rw-r--r--Lib/distutils/tests/test_build_py.py81
-rw-r--r--Lib/distutils/tests/test_build_scripts.py8
-rw-r--r--Lib/distutils/tests/test_ccompiler.py82
-rw-r--r--Lib/distutils/tests/test_check.py17
-rw-r--r--Lib/distutils/tests/test_clean.py2
-rw-r--r--Lib/distutils/tests/test_cmd.py2
-rw-r--r--Lib/distutils/tests/test_config.py9
-rw-r--r--Lib/distutils/tests/test_config_cmd.py2
-rw-r--r--Lib/distutils/tests/test_core.py18
-rw-r--r--Lib/distutils/tests/test_cygwinccompiler.py155
-rw-r--r--Lib/distutils/tests/test_dep_util.py2
-rw-r--r--Lib/distutils/tests/test_dir_util.py13
-rw-r--r--Lib/distutils/tests/test_dist.py183
-rw-r--r--Lib/distutils/tests/test_extension.py69
-rw-r--r--Lib/distutils/tests/test_file_util.py19
-rw-r--r--Lib/distutils/tests/test_filelist.py2
-rw-r--r--Lib/distutils/tests/test_install.py13
-rw-r--r--Lib/distutils/tests/test_install_data.py2
-rw-r--r--Lib/distutils/tests/test_install_headers.py2
-rw-r--r--Lib/distutils/tests/test_install_lib.py70
-rw-r--r--Lib/distutils/tests/test_install_scripts.py2
-rw-r--r--Lib/distutils/tests/test_log.py37
-rw-r--r--Lib/distutils/tests/test_msvc9compiler.py10
-rw-r--r--Lib/distutils/tests/test_register.py82
-rw-r--r--Lib/distutils/tests/test_sdist.py102
-rw-r--r--Lib/distutils/tests/test_spawn.py8
-rw-r--r--Lib/distutils/tests/test_sysconfig.py61
-rw-r--r--Lib/distutils/tests/test_text_file.py2
-rw-r--r--Lib/distutils/tests/test_unixccompiler.py14
-rw-r--r--Lib/distutils/tests/test_upload.py69
-rw-r--r--Lib/distutils/tests/test_util.py264
-rw-r--r--Lib/distutils/tests/test_version.py6
-rw-r--r--Lib/distutils/tests/test_versionpredicate.py2
-rw-r--r--Lib/distutils/text_file.py91
-rw-r--r--Lib/distutils/unixccompiler.py68
-rw-r--r--Lib/distutils/util.py163
-rw-r--r--Lib/distutils/version.py124
-rw-r--r--Lib/distutils/versionpredicate.py8
100 files changed, 2850 insertions, 3301 deletions
diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py
index 036062cc337..b52a9fe6c40 100644
--- a/Lib/distutils/__init__.py
+++ b/Lib/distutils/__init__.py
@@ -8,12 +8,10 @@ used from a setup script as
setup (...)
"""
-__revision__ = "$Id$"
-
# Distutils version
#
# Updated automatically by the Python release process.
#
#--start constants--
-__version__ = "2.7.3"
+__version__ = "3.2.3"
#--end constants--
diff --git a/Lib/distutils/archive_util.py b/Lib/distutils/archive_util.py
index 834b722ed3f..fcda08e20a2 100644
--- a/Lib/distutils/archive_util.py
+++ b/Lib/distutils/archive_util.py
@@ -3,66 +3,30 @@
Utility functions for creating archive files (tarballs, zip files,
that sort of thing)."""
-__revision__ = "$Id$"
-
import os
from warnings import warn
import sys
-from distutils.errors import DistutilsExecError
-from distutils.spawn import spawn
-from distutils.dir_util import mkpath
-from distutils import log
-
try:
- from pwd import getpwnam
+ import zipfile
except ImportError:
- getpwnam = None
+ zipfile = 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
+from distutils.errors import DistutilsExecError
+from distutils.spawn import spawn
+from distutils.dir_util import mkpath
+from distutils import log
-def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
- owner=None, group=None):
+def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0):
"""Create a (possibly compressed) tar file from all the files under
'base_dir'.
'compress' must be "gzip" (the default), "compress", "bzip2", or None.
- (compress will be deprecated in Python 3.2)
-
- '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.
-
+ Both "tar" and the compression utility named by 'compress' must be on
+ the default program search path, so this is probably Unix-specific.
The output tar file will be named 'base_dir' + ".tar", possibly plus
the appropriate compression extension (".gz", ".bz2" or ".Z").
-
Returns the output filename.
"""
tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''}
@@ -70,9 +34,9 @@ def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
# flags for compression program, each element of list will be an argument
if compress is not None and compress not in compress_ext.keys():
- raise ValueError, \
- ("bad value for 'compress': must be None, 'gzip', 'bzip2' "
- "or 'compress'")
+ raise ValueError(
+ "bad value for 'compress': must be None, 'gzip', 'bzip2' "
+ "or 'compress'")
archive_name = base_name + '.tar'
if compress != 'compress':
@@ -84,23 +48,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
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:
tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
try:
- tar.add(base_dir, filter=_set_uid_gid)
+ tar.add(base_dir)
finally:
tar.close()
@@ -127,11 +78,6 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
available, raises DistutilsExecError. Returns the name of the output zip
file.
"""
- try:
- import zipfile
- except ImportError:
- zipfile = None
-
zip_filename = base_name + ".zip"
mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
@@ -149,18 +95,21 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
except DistutilsExecError:
# XXX really should distinguish between "couldn't find
# external 'zip' command" and "zip failed".
- raise DistutilsExecError, \
- ("unable to create zip file '%s': "
+ raise DistutilsExecError(("unable to create zip file '%s': "
"could neither import the 'zipfile' module nor "
- "find a standalone zip utility") % zip_filename
+ "find a standalone zip utility") % zip_filename)
else:
log.info("creating '%s' and adding '%s' to it",
zip_filename, base_dir)
if not dry_run:
- zip = zipfile.ZipFile(zip_filename, "w",
- compression=zipfile.ZIP_DEFLATED)
+ try:
+ zip = zipfile.ZipFile(zip_filename, "w",
+ compression=zipfile.ZIP_DEFLATED)
+ except RuntimeError:
+ zip = zipfile.ZipFile(zip_filename, "w",
+ compression=zipfile.ZIP_STORED)
for dirpath, dirnames, filenames in os.walk(base_dir):
for name in filenames:
@@ -191,7 +140,7 @@ def check_archive_formats(formats):
return None
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).
'base_name' is the name of the file to create, minus any format-specific
@@ -204,9 +153,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
directories in the archive. 'root_dir' and 'base_dir' both default
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()
if root_dir is not None:
@@ -223,16 +169,11 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
try:
format_info = ARCHIVE_FORMATS[format]
except KeyError:
- raise ValueError, "unknown archive format '%s'" % format
+ raise ValueError("unknown archive format '%s'" % format)
func = format_info[0]
for arg, val in format_info[1]:
kwargs[arg] = val
-
- if format != 'zip':
- kwargs['owner'] = owner
- kwargs['group'] = group
-
try:
filename = func(base_name, base_dir, **kwargs)
finally:
diff --git a/Lib/distutils/bcppcompiler.py b/Lib/distutils/bcppcompiler.py
index f26e7ae4673..9f4c432d90e 100644
--- a/Lib/distutils/bcppcompiler.py
+++ b/Lib/distutils/bcppcompiler.py
@@ -11,13 +11,13 @@ for the Borland C++ compiler.
# someone should sit down and factor out the common code as
# WindowsCCompiler! --GPW
-__revision__ = "$Id$"
import os
-
-from distutils.errors import (DistutilsExecError, CompileError, LibError,
- LinkError, UnknownFileError)
-from distutils.ccompiler import CCompiler, gen_preprocess_options
+from distutils.errors import \
+ 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.dep_util import newer
from distutils import log
@@ -111,8 +111,8 @@ class BCPPCompiler(CCompiler) :
# This needs to be compiled to a .res file -- do it now.
try:
self.spawn (["brcc32", "-fo", obj, src])
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
continue # the 'for' loop
# The next two are both for the real compiler.
@@ -135,8 +135,8 @@ class BCPPCompiler(CCompiler) :
self.spawn ([self.cc] + compile_opts + pp_opts +
[input_opt, output_opt] +
extra_postargs + [src])
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
return objects
@@ -160,8 +160,8 @@ class BCPPCompiler(CCompiler) :
pass # XXX what goes here?
try:
self.spawn ([self.lib] + lib_args)
- except DistutilsExecError, msg:
- raise LibError, msg
+ except DistutilsExecError as msg:
+ raise LibError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
@@ -294,8 +294,8 @@ class BCPPCompiler(CCompiler) :
self.mkpath (os.path.dirname (output_filename))
try:
self.spawn ([self.linker] + ld_args)
- except DistutilsExecError, msg:
- raise LinkError, msg
+ except DistutilsExecError as msg:
+ raise LinkError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
@@ -341,9 +341,8 @@ class BCPPCompiler(CCompiler) :
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
(base, ext) = os.path.splitext (os.path.normcase(src_name))
if ext not in (self.src_extensions + ['.rc','.res']):
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % \
- (ext, src_name)
+ raise UnknownFileError("unknown file type '%s' (from '%s')" % \
+ (ext, src_name))
if strip_dir:
base = os.path.basename (base)
if ext == '.res':
@@ -387,8 +386,8 @@ class BCPPCompiler(CCompiler) :
self.mkpath(os.path.dirname(output_file))
try:
self.spawn(pp_args)
- except DistutilsExecError, msg:
- print msg
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ print(msg)
+ raise CompileError(msg)
# preprocess()
diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py
index 7076b933946..c795c958fec 100644
--- a/Lib/distutils/ccompiler.py
+++ b/Lib/distutils/ccompiler.py
@@ -3,18 +3,12 @@
Contains CCompiler, an abstract base class that defines the interface
for the Distutils compiler abstraction model."""
-__revision__ = "$Id$"
-
-import sys
-import os
-import re
-
-from distutils.errors import (CompileError, LinkError, UnknownFileError,
- DistutilsPlatformError, DistutilsModuleError)
+import sys, os, re
+from distutils.errors import *
from distutils.spawn import spawn
from distutils.file_util import move_file
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 import log
@@ -88,7 +82,7 @@ class CCompiler:
}
language_order = ["c++", "objc", "c"]
- def __init__ (self, verbose=0, dry_run=0, force=0):
+ def __init__(self, verbose=0, dry_run=0, force=0):
self.dry_run = dry_run
self.force = force
self.verbose = verbose
@@ -124,7 +118,7 @@ class CCompiler:
for key in self.executables.keys():
self.set_executable(key, self.executables[key])
- def set_executables(self, **args):
+ def set_executables(self, **kwargs):
"""Define the executables (and options for them) that will be run
to perform the various stages of compilation. The exact set of
executables that may be specified here depends on the compiler
@@ -150,12 +144,11 @@ class CCompiler:
# discovered at run-time, since there are many different ways to do
# basically the same things with Unix C compilers.
- for key in args.keys():
+ for key in kwargs:
if key not in self.executables:
- raise ValueError, \
- "unknown executable '%s' for class %s" % \
- (key, self.__class__.__name__)
- self.set_executable(key, args[key])
+ raise ValueError("unknown executable '%s' for class %s" %
+ (key, self.__class__.__name__))
+ self.set_executable(key, kwargs[key])
def set_executable(self, key, value):
if isinstance(value, str):
@@ -168,7 +161,7 @@ class CCompiler:
for defn in self.macros:
if defn[0] == name:
return i
- i = i + 1
+ i += 1
return None
def _check_macro_definitions(self, definitions):
@@ -178,14 +171,12 @@ class CCompiler:
"""
for defn in definitions:
if not (isinstance(defn, tuple) and
- (len (defn) == 1 or
- (len (defn) == 2 and
- (isinstance(defn[1], str) or defn[1] is None))) and
- isinstance(defn[0], str)):
- raise TypeError, \
- ("invalid macro definition '%s': " % defn) + \
+ (len(defn) in (1, 2) and
+ (isinstance (defn[1], str) or defn[1] is None)) and
+ isinstance (defn[0], str)):
+ raise TypeError(("invalid macro definition '%s': " % defn) + \
"must be tuple (string,), (string, string), or " + \
- "(string, None)"
+ "(string, None)")
# -- Bookkeeping methods -------------------------------------------
@@ -203,8 +194,7 @@ class CCompiler:
if i is not None:
del self.macros[i]
- defn = (name, value)
- self.macros.append (defn)
+ self.macros.append((name, value))
def undefine_macro(self, name):
"""Undefine a preprocessor macro for all compilations driven by
@@ -222,7 +212,7 @@ class CCompiler:
del self.macros[i]
undefn = (name,)
- self.macros.append (undefn)
+ self.macros.append(undefn)
def add_include_dir(self, dir):
"""Add 'dir' to the list of directories that will be searched for
@@ -230,7 +220,7 @@ class CCompiler:
the order in which they are supplied by successive calls to
'add_include_dir()'.
"""
- self.include_dirs.append (dir)
+ self.include_dirs.append(dir)
def set_include_dirs(self, dirs):
"""Set the list of directories that will be searched to 'dirs' (a
@@ -256,7 +246,7 @@ class CCompiler:
names; the linker will be instructed to link against libraries as
many times as they are mentioned.
"""
- self.libraries.append (libname)
+ self.libraries.append(libname)
def set_libraries(self, libnames):
"""Set the list of libraries to be included in all links driven by
@@ -266,7 +256,6 @@ class CCompiler:
"""
self.libraries = libnames[:]
-
def add_library_dir(self, dir):
"""Add 'dir' to the list of directories that will be searched for
libraries specified to 'add_library()' and 'set_libraries()'. The
@@ -324,29 +313,28 @@ class CCompiler:
if outdir is None:
outdir = self.output_dir
elif not isinstance(outdir, str):
- raise TypeError, "'output_dir' must be a string or None"
+ raise TypeError("'output_dir' must be a string or None")
if macros is None:
macros = self.macros
elif isinstance(macros, list):
macros = macros + (self.macros or [])
else:
- raise TypeError, "'macros' (if supplied) must be a list of tuples"
+ raise TypeError("'macros' (if supplied) must be a list of tuples")
if incdirs is None:
incdirs = self.include_dirs
elif isinstance(incdirs, (list, tuple)):
incdirs = list(incdirs) + (self.include_dirs or [])
else:
- raise TypeError, \
- "'include_dirs' (if supplied) must be a list of strings"
+ raise TypeError(
+ "'include_dirs' (if supplied) must be a list of strings")
if extra is None:
extra = []
# Get the list of expected output (object) files
- objects = self.object_filenames(sources,
- strip_dir=0,
+ objects = self.object_filenames(sources, strip_dir=0,
output_dir=outdir)
assert len(objects) == len(sources)
@@ -384,25 +372,41 @@ class CCompiler:
if output_dir is None:
output_dir = self.output_dir
elif not isinstance(output_dir, str):
- raise TypeError, "'output_dir' must be a string or None"
+ raise TypeError("'output_dir' must be a string or None")
if macros is None:
macros = self.macros
elif isinstance(macros, list):
macros = macros + (self.macros or [])
else:
- raise TypeError, "'macros' (if supplied) must be a list of tuples"
+ raise TypeError("'macros' (if supplied) must be a list of tuples")
if include_dirs is None:
include_dirs = self.include_dirs
elif isinstance(include_dirs, (list, tuple)):
- include_dirs = list (include_dirs) + (self.include_dirs or [])
+ include_dirs = list(include_dirs) + (self.include_dirs or [])
else:
- raise TypeError, \
- "'include_dirs' (if supplied) must be a list of strings"
+ raise TypeError(
+ "'include_dirs' (if supplied) must be a list of strings")
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):
"""Typecheck and fix up some arguments supplied to various methods.
Specifically: ensure that 'objects' is a list; if output_dir is
@@ -410,14 +414,13 @@ class CCompiler:
'objects' and 'output_dir'.
"""
if not isinstance(objects, (list, tuple)):
- raise TypeError, \
- "'objects' must be a list or tuple of strings"
- objects = list (objects)
+ raise TypeError("'objects' must be a list or tuple of strings")
+ objects = list(objects)
if output_dir is None:
output_dir = self.output_dir
elif not isinstance(output_dir, str):
- raise TypeError, "'output_dir' must be a string or None"
+ raise TypeError("'output_dir' must be a string or None")
return (objects, output_dir)
@@ -433,26 +436,25 @@ class CCompiler:
elif isinstance(libraries, (list, tuple)):
libraries = list (libraries) + (self.libraries or [])
else:
- raise TypeError, \
- "'libraries' (if supplied) must be a list of strings"
+ raise TypeError(
+ "'libraries' (if supplied) must be a list of strings")
if library_dirs is None:
library_dirs = self.library_dirs
elif isinstance(library_dirs, (list, tuple)):
library_dirs = list (library_dirs) + (self.library_dirs or [])
else:
- raise TypeError, \
- "'library_dirs' (if supplied) must be a list of strings"
+ raise TypeError(
+ "'library_dirs' (if supplied) must be a list of strings")
if runtime_library_dirs is None:
runtime_library_dirs = self.runtime_library_dirs
elif isinstance(runtime_library_dirs, (list, tuple)):
- runtime_library_dirs = (list (runtime_library_dirs) +
+ runtime_library_dirs = (list(runtime_library_dirs) +
(self.runtime_library_dirs or []))
else:
- raise TypeError, \
- "'runtime_library_dirs' (if supplied) " + \
- "must be a list of strings"
+ raise TypeError("'runtime_library_dirs' (if supplied) "
+ "must be a list of strings")
return (libraries, library_dirs, runtime_library_dirs)
@@ -461,7 +463,7 @@ class CCompiler:
to recreate 'output_file'.
"""
if self.force:
- return 1
+ return True
else:
if self.dry_run:
newer = newer_group (objects, output_file, missing='newer')
@@ -489,6 +491,7 @@ class CCompiler:
pass
return lang
+
# -- Worker methods ------------------------------------------------
# (must be implemented by subclasses)
@@ -558,7 +561,6 @@ class CCompiler:
"""
# A concrete compiler class can either override this method
# entirely or implement _compile().
-
macros, objects, extra_postargs, pp_opts, build = \
self._setup_compile(output_dir, macros, include_dirs, sources,
depends, extra_postargs)
@@ -576,7 +578,6 @@ class CCompiler:
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
"""Compile 'src' to product 'obj'."""
-
# A concrete compiler class that does not override compile()
# should implement _compile().
pass
@@ -607,15 +608,26 @@ class CCompiler:
"""
pass
+
# values for target_desc parameter in link()
SHARED_OBJECT = "shared_object"
SHARED_LIBRARY = "shared_library"
EXECUTABLE = "executable"
- def link(self, target_desc, objects, 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):
+ def link(self,
+ target_desc,
+ objects,
+ 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
shared library file.
@@ -664,11 +676,19 @@ class CCompiler:
# Old 'link_*()' methods, rewritten to use the new 'link()' method.
- def link_shared_lib(self, objects, output_libname, 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):
+ def link_shared_lib(self,
+ objects,
+ output_libname,
+ 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):
self.link(CCompiler.SHARED_LIBRARY, objects,
self.library_filename(output_libname, lib_type='shared'),
output_dir,
@@ -677,21 +697,37 @@ class CCompiler:
extra_preargs, extra_postargs, build_temp, target_lang)
- def link_shared_object(self, objects, 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):
+ def link_shared_object(self,
+ objects,
+ 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):
self.link(CCompiler.SHARED_OBJECT, objects,
output_filename, output_dir,
libraries, library_dirs, runtime_library_dirs,
export_symbols, debug,
extra_preargs, extra_postargs, build_temp, target_lang)
- def link_executable(self, objects, output_progname, output_dir=None,
- libraries=None, library_dirs=None,
- runtime_library_dirs=None, debug=0, extra_preargs=None,
- extra_postargs=None, target_lang=None):
+
+ def link_executable(self,
+ objects,
+ output_progname,
+ 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.executable_filename(output_progname), output_dir,
libraries, library_dirs, runtime_library_dirs, None,
@@ -727,7 +763,6 @@ class CCompiler:
the current platform. The optional arguments can be used to
augment the compilation environment.
"""
-
# this can't be included at module scope because it tries to
# import math which might not be available at that point - maybe
# the necessary logic should just be inlined?
@@ -817,8 +852,8 @@ main (int argc, char **argv) {
base = os.path.splitdrive(base)[1] # Chop off the drive
base = base[os.path.isabs(base):] # If abs, chop off leading /
if ext not in self.src_extensions:
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % (ext, src_name)
+ raise UnknownFileError(
+ "unknown file type '%s' (from '%s')" % (ext, src_name))
if strip_dir:
base = os.path.basename(base)
obj_names.append(os.path.join(output_dir,
@@ -828,24 +863,25 @@ main (int argc, char **argv) {
def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
assert output_dir is not None
if strip_dir:
- basename = os.path.basename (basename)
+ basename = os.path.basename(basename)
return os.path.join(output_dir, basename + self.shared_lib_extension)
def executable_filename(self, basename, strip_dir=0, output_dir=''):
assert output_dir is not None
if strip_dir:
- basename = os.path.basename (basename)
+ basename = os.path.basename(basename)
return os.path.join(output_dir, basename + (self.exe_extension or ''))
def library_filename(self, libname, lib_type='static', # or 'shared'
strip_dir=0, output_dir=''):
assert output_dir is not None
if lib_type not in ("static", "shared", "dylib"):
- raise ValueError, "'lib_type' must be \"static\", \"shared\" or \"dylib\""
+ raise ValueError(
+ "'lib_type' must be \"static\", \"shared\" or \"dylib\"")
fmt = getattr(self, lib_type + "_lib_format")
ext = getattr(self, lib_type + "_lib_extension")
- dir, base = os.path.split (libname)
+ dir, base = os.path.split(libname)
filename = fmt % (base, ext)
if strip_dir:
dir = ''
@@ -861,7 +897,7 @@ main (int argc, char **argv) {
def debug_print(self, msg):
from distutils.debug import DEBUG
if DEBUG:
- print msg
+ print(msg)
def warn(self, msg):
sys.stderr.write("warning: %s\n" % msg)
@@ -875,13 +911,10 @@ main (int argc, char **argv) {
def move_file(self, src, dst):
return move_file(src, dst, dry_run=self.dry_run)
- def mkpath(self, name, mode=0777):
+ def mkpath (self, name, mode=0o777):
mkpath(name, mode, dry_run=self.dry_run)
-# class CCompiler
-
-
# Map a sys.platform/os.name ('posix', 'nt') to the default compiler
# type for that platform. Keys are interpreted as re match
# patterns. Order is important; platform mappings are preferred over
@@ -902,15 +935,14 @@ _default_compilers = (
)
def get_default_compiler(osname=None, platform=None):
- """ Determine the default compiler to use for the given platform.
-
- osname should be one of the standard Python OS names (i.e. the
- ones returned by os.name) and platform the common value
- returned by sys.platform for the platform in question.
+ """Determine the default compiler to use for the given platform.
- The default values are os.name and sys.platform in case the
- parameters are not given.
+ osname should be one of the standard Python OS names (i.e. the
+ ones returned by os.name) and platform the common value
+ returned by sys.platform for the platform in question.
+ The default values are os.name and sys.platform in case the
+ parameters are not given.
"""
if osname is None:
osname = os.name
@@ -980,7 +1012,7 @@ def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
msg = "don't know how to compile C/C++ code on platform '%s'" % plat
if compiler is not None:
msg = msg + " with '%s' compiler" % compiler
- raise DistutilsPlatformError, msg
+ raise DistutilsPlatformError(msg)
try:
module_name = "distutils." + module_name
@@ -988,13 +1020,13 @@ def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
module = sys.modules[module_name]
klass = vars(module)[class_name]
except ImportError:
- raise DistutilsModuleError, \
+ raise DistutilsModuleError(
"can't compile C/C++ code: unable to load module '%s'" % \
- module_name
+ module_name)
except KeyError:
- raise DistutilsModuleError, \
- ("can't compile C/C++ code: unable to find class '%s' " +
- "in module '%s'") % (class_name, module_name)
+ raise DistutilsModuleError(
+ "can't compile C/C++ code: unable to find class '%s' "
+ "in module '%s'" % (class_name, module_name))
# XXX The None is necessary to preserve backwards compatibility
# with classes that expect verbose to be the first positional
@@ -1023,42 +1055,36 @@ def gen_preprocess_options(macros, include_dirs):
# redundancies like this should probably be the province of
# CCompiler, since the data structures used are inherited from it
# and therefore common to all CCompiler classes.
-
pp_opts = []
for macro in macros:
-
- if not (isinstance(macro, tuple) and
- 1 <= len (macro) <= 2):
- raise TypeError, \
- ("bad macro definition '%s': " +
- "each element of 'macros' list must be a 1- or 2-tuple") % \
- macro
-
- if len (macro) == 1: # undefine this macro
- pp_opts.append ("-U%s" % macro[0])
- elif len (macro) == 2:
+ if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):
+ raise TypeError(
+ "bad macro definition '%s': "
+ "each element of 'macros' list must be a 1- or 2-tuple"
+ % macro)
+
+ if len(macro) == 1: # undefine this macro
+ pp_opts.append("-U%s" % macro[0])
+ elif len(macro) == 2:
if macro[1] is None: # define with no explicit value
- pp_opts.append ("-D%s" % macro[0])
+ pp_opts.append("-D%s" % macro[0])
else:
# XXX *don't* need to be clever about quoting the
# macro value here, because we're going to avoid the
# shell at all costs when we spawn the command!
- pp_opts.append ("-D%s=%s" % macro)
+ pp_opts.append("-D%s=%s" % macro)
for dir in include_dirs:
- pp_opts.append ("-I%s" % dir)
-
+ pp_opts.append("-I%s" % dir)
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
- linking with specific libraries.
-
- 'libraries' and 'library_dirs' are, respectively, lists of library names
- (not filenames!) and search directories. Returns a list of command-line
- options suitable for use with some compiler (depending on the two format
- strings passed in).
+ linking with specific libraries. 'libraries' and 'library_dirs' are,
+ respectively, lists of library names (not filenames!) and search
+ directories. Returns a list of command-line options suitable for use
+ with some compiler (depending on the two format strings passed in).
"""
lib_opts = []
@@ -1068,7 +1094,7 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
for dir in runtime_library_dirs:
opt = compiler.runtime_library_dir_option(dir)
if isinstance(opt, list):
- lib_opts.extend(opt)
+ lib_opts = lib_opts + opt
else:
lib_opts.append(opt)
@@ -1079,15 +1105,14 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
# pretty nasty way to arrange your C code.
for lib in libraries:
- lib_dir, lib_name = os.path.split(lib)
- if lib_dir != '':
+ (lib_dir, lib_name) = os.path.split(lib)
+ if lib_dir:
lib_file = compiler.find_library_file([lib_dir], lib_name)
- if lib_file is not None:
+ if lib_file:
lib_opts.append(lib_file)
else:
compiler.warn("no library file corresponding to "
"'%s' found (skipping)" % lib)
else:
- lib_opts.append(compiler.library_option(lib))
-
+ lib_opts.append(compiler.library_option (lib))
return lib_opts
diff --git a/Lib/distutils/cmd.py b/Lib/distutils/cmd.py
index 9ad5657e40a..3ea08101acb 100644
--- a/Lib/distutils/cmd.py
+++ b/Lib/distutils/cmd.py
@@ -4,8 +4,6 @@ Provides the Command class, the base class for the command classes
in the distutils.command package.
"""
-__revision__ = "$Id$"
-
import sys, os, re
from distutils.errors import DistutilsOptionError
from distutils import util, dir_util, file_util, archive_util, dep_util
@@ -56,9 +54,9 @@ class Command:
from distutils.dist import Distribution
if not isinstance(dist, Distribution):
- raise TypeError, "dist must be a Distribution instance"
+ raise TypeError("dist must be a Distribution instance")
if self.__class__ is Command:
- raise RuntimeError, "Command is an abstract class"
+ raise RuntimeError("Command is an abstract class")
self.distribution = dist
self.initialize_options()
@@ -102,7 +100,7 @@ class Command:
else:
return myval
else:
- raise AttributeError, attr
+ raise AttributeError(attr)
def ensure_finalized(self):
if not self.finalized:
@@ -132,8 +130,8 @@ class Command:
This method must be implemented by all command classes.
"""
- raise RuntimeError, \
- "abstract method -- subclass %s must override" % self.__class__
+ raise RuntimeError("abstract method -- subclass %s must override"
+ % self.__class__)
def finalize_options(self):
"""Set final values for all the options that this command supports.
@@ -146,8 +144,8 @@ class Command:
This method must be implemented by all command classes.
"""
- raise RuntimeError, \
- "abstract method -- subclass %s must override" % self.__class__
+ raise RuntimeError("abstract method -- subclass %s must override"
+ % self.__class__)
def dump_options(self, header=None, indent=""):
@@ -174,8 +172,8 @@ class Command:
This method must be implemented by all command classes.
"""
- raise RuntimeError, \
- "abstract method -- subclass %s must override" % self.__class__
+ raise RuntimeError("abstract method -- subclass %s must override"
+ % self.__class__)
def announce(self, msg, level=1):
"""If the current verbosity level is of greater than or equal to
@@ -189,7 +187,7 @@ class Command:
"""
from distutils.debug import DEBUG
if DEBUG:
- print msg
+ print(msg)
sys.stdout.flush()
@@ -212,8 +210,8 @@ class Command:
setattr(self, option, default)
return default
elif not isinstance(val, str):
- raise DistutilsOptionError, \
- "'%s' must be a %s (got `%s`)" % (option, what, val)
+ raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
+ % (option, what, val))
return val
def ensure_string(self, option, default=None):
@@ -235,27 +233,20 @@ class Command:
setattr(self, option, re.split(r',\s*|\s+', val))
else:
if isinstance(val, list):
- # checks if all elements are str
- ok = 1
- for element in val:
- if not isinstance(element, str):
- ok = 0
- break
+ ok = all(isinstance(v, str) for v in val)
else:
- ok = 0
-
+ ok = False
if not ok:
- raise DistutilsOptionError, \
- "'%s' must be a list of strings (got %r)" % \
- (option, val)
+ raise DistutilsOptionError(
+ "'%s' must be a list of strings (got %r)"
+ % (option, val))
-
- def _ensure_tested_string(self, option, tester,
- what, error_fmt, default=None):
+ def _ensure_tested_string(self, option, tester, what, error_fmt,
+ default=None):
val = self._ensure_stringlike(option, what, default)
if val is not None and not tester(val):
- raise DistutilsOptionError, \
- ("error in '%s' option: " + error_fmt) % (option, val)
+ raise DistutilsOptionError(("error in '%s' option: " + error_fmt)
+ % (option, val))
def ensure_filename(self, option):
"""Ensure that 'option' is the name of an existing file."""
@@ -291,16 +282,12 @@ class Command:
'src_option' in the 'src_cmd' command object, and copy it to
'dst_option' in the current command object".
"""
-
# Option_pairs: list of (src_option, dst_option) tuples
-
src_cmd_obj = self.distribution.get_command_obj(src_cmd)
src_cmd_obj.ensure_finalized()
for (src_option, dst_option) in option_pairs:
if getattr(self, dst_option) is None:
- setattr(self, dst_option,
- getattr(src_cmd_obj, src_option))
-
+ setattr(self, dst_option, getattr(src_cmd_obj, src_option))
def get_finalized_command(self, command, create=1):
"""Wrapper around Distribution's 'get_command_obj()' method: find
@@ -315,8 +302,8 @@ class Command:
# XXX rename to 'get_reinitialized_command()'? (should do the
# same in dist.py, if so)
def reinitialize_command(self, command, reinit_subcommands=0):
- return self.distribution.reinitialize_command(
- command, reinit_subcommands)
+ return self.distribution.reinitialize_command(command,
+ reinit_subcommands)
def run_command(self, command):
"""Run some other command: uses the 'run_command()' method of
@@ -348,48 +335,39 @@ class Command:
def execute(self, func, args, msg=None, level=1):
util.execute(func, args, msg, dry_run=self.dry_run)
- def mkpath(self, name, mode=0777):
+ def mkpath(self, name, mode=0o777):
dir_util.mkpath(name, mode, dry_run=self.dry_run)
- def copy_file(self, infile, outfile,
- preserve_mode=1, preserve_times=1, link=None, level=1):
+ def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
+ link=None, level=1):
"""Copy a file respecting verbose, dry-run and force flags. (The
former two default to whatever is in the Distribution object, and
the latter defaults to false for commands that don't define it.)"""
+ return file_util.copy_file(infile, outfile, preserve_mode,
+ preserve_times, not self.force, link,
+ dry_run=self.dry_run)
- return file_util.copy_file(
- infile, outfile,
- preserve_mode, preserve_times,
- not self.force,
- link,
- dry_run=self.dry_run)
-
- def copy_tree(self, infile, outfile,
- preserve_mode=1, preserve_times=1, preserve_symlinks=0,
- level=1):
+ def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
+ preserve_symlinks=0, level=1):
"""Copy an entire directory tree respecting verbose, dry-run,
and force flags.
"""
- return dir_util.copy_tree(
- infile, outfile,
- preserve_mode,preserve_times,preserve_symlinks,
- not self.force,
- dry_run=self.dry_run)
+ return dir_util.copy_tree(infile, outfile, preserve_mode,
+ preserve_times, preserve_symlinks,
+ not self.force, dry_run=self.dry_run)
def move_file (self, src, dst, level=1):
"""Move a file respecting dry-run flag."""
- return file_util.move_file(src, dst, dry_run = self.dry_run)
+ return file_util.move_file(src, dst, dry_run=self.dry_run)
- def spawn (self, cmd, search_path=1, level=1):
+ def spawn(self, cmd, search_path=1, level=1):
"""Spawn an external command respecting dry-run flag."""
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,
- owner=None, group=None):
- return archive_util.make_archive(base_name, format, root_dir,
- base_dir, dry_run=self.dry_run,
- owner=owner, group=group)
+ def make_archive(self, base_name, format, root_dir=None, base_dir=None):
+ return archive_util.make_archive(base_name, format, root_dir, base_dir,
+ dry_run=self.dry_run)
def make_file(self, infiles, outfile, func, args,
exec_msg=None, skip_msg=None, level=1):
@@ -408,19 +386,17 @@ class Command:
if isinstance(infiles, str):
infiles = (infiles,)
elif not isinstance(infiles, (list, tuple)):
- raise TypeError, \
- "'infiles' must be a string, or a list or tuple of strings"
+ raise TypeError(
+ "'infiles' must be a string, or a list or tuple of strings")
if exec_msg is None:
- exec_msg = "generating %s from %s" % \
- (outfile, ', '.join(infiles))
+ exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles))
# If 'outfile' must be regenerated (either because it doesn't
# exist, is out-of-date, or the 'force' flag is true) then
# perform the action that presumably regenerates it
if self.force or dep_util.newer_group(infiles, outfile):
self.execute(func, args, exec_msg, level)
-
# Otherwise, print the "skip" message
else:
log.debug(skip_msg)
diff --git a/Lib/distutils/command/__init__.py b/Lib/distutils/command/__init__.py
index 20b159f74ec..481eea9fd4b 100644
--- a/Lib/distutils/command/__init__.py
+++ b/Lib/distutils/command/__init__.py
@@ -3,8 +3,6 @@
Package containing implementation of all the standard Distutils
commands."""
-__revision__ = "$Id$"
-
__all__ = ['build',
'build_py',
'build_ext',
@@ -22,8 +20,8 @@ __all__ = ['build',
'bdist_dumb',
'bdist_rpm',
'bdist_wininst',
- 'upload',
'check',
+ 'upload',
# These two are reserved for future use:
#'bdist_sdux',
#'bdist_pkgtool',
diff --git a/Lib/distutils/command/bdist.py b/Lib/distutils/command/bdist.py
index d7910b14d6e..c5188eb3719 100644
--- a/Lib/distutils/command/bdist.py
+++ b/Lib/distutils/command/bdist.py
@@ -3,13 +3,10 @@
Implements the Distutils 'bdist' command (create a built [binary]
distribution)."""
-__revision__ = "$Id$"
-
import os
-
-from distutils.util import get_platform
from distutils.core import Command
-from distutils.errors import DistutilsPlatformError, DistutilsOptionError
+from distutils.errors import *
+from distutils.util import get_platform
def show_formats():
@@ -40,12 +37,6 @@ class bdist(Command):
"[default: dist]"),
('skip-build', None,
"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']
@@ -87,8 +78,6 @@ class bdist(Command):
self.formats = None
self.dist_dir = None
self.skip_build = 0
- self.group = None
- self.owner = None
def finalize_options(self):
# have to finalize 'plat_name' before 'bdist_base'
@@ -111,9 +100,9 @@ class bdist(Command):
try:
self.formats = [self.default_format[os.name]]
except KeyError:
- raise DistutilsPlatformError, \
- "don't know how to create built distributions " + \
- "on platform %s" % os.name
+ raise DistutilsPlatformError(
+ "don't know how to create built distributions "
+ "on platform %s" % os.name)
if self.dist_dir is None:
self.dist_dir = "dist"
@@ -125,7 +114,7 @@ class bdist(Command):
try:
commands.append(self.format_command[format][0])
except KeyError:
- raise DistutilsOptionError, "invalid format '%s'" % format
+ raise DistutilsOptionError("invalid format '%s'" % format)
# Reinitialize and run each command.
for i in range(len(self.formats)):
@@ -134,11 +123,6 @@ class bdist(Command):
if cmd_name not in self.no_format_option:
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
# keep its temporary files around so subsequent runs go faster.
if cmd_name in commands[i+1:]:
diff --git a/Lib/distutils/command/bdist_dumb.py b/Lib/distutils/command/bdist_dumb.py
index 2f3c66829a1..1ab09d16163 100644
--- a/Lib/distutils/command/bdist_dumb.py
+++ b/Lib/distutils/command/bdist_dumb.py
@@ -4,21 +4,17 @@ Implements the Distutils 'bdist_dumb' command (create a "dumb" built
distribution -- i.e., just an archive to be unpacked under $prefix or
$exec_prefix)."""
-__revision__ = "$Id$"
-
import os
-
-from sysconfig import get_python_version
-
-from distutils.util import get_platform
from distutils.core import Command
+from distutils.util import get_platform
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
-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',
"temporary directory for creating the distribution"),
@@ -37,12 +33,6 @@ class bdist_dumb (Command):
('relative', None,
"build the archive using relative paths"
"(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']
@@ -51,8 +41,7 @@ class bdist_dumb (Command):
'nt': 'zip',
'os2': 'zip' }
-
- def initialize_options (self):
+ def initialize_options(self):
self.bdist_dir = None
self.plat_name = None
self.format = None
@@ -60,8 +49,6 @@ class bdist_dumb (Command):
self.dist_dir = None
self.skip_build = None
self.relative = 0
- self.owner = None
- self.group = None
def finalize_options(self):
if self.bdist_dir is None:
@@ -72,9 +59,9 @@ class bdist_dumb (Command):
try:
self.format = self.default_format[os.name]
except KeyError:
- raise DistutilsPlatformError, \
- ("don't know how to create dumb built distributions " +
- "on platform %s") % os.name
+ raise DistutilsPlatformError(
+ "don't know how to create dumb built distributions "
+ "on platform %s" % os.name)
self.set_undefined_options('bdist',
('dist_dir', 'dist_dir'),
@@ -109,8 +96,8 @@ class bdist_dumb (Command):
else:
if (self.distribution.has_ext_modules() and
(install.install_base != install.install_platbase)):
- raise DistutilsPlatformError, \
- ("can't make a dumb built distribution where "
+ raise DistutilsPlatformError(
+ "can't make a dumb built distribution where "
"base and platbase are different (%s, %s)"
% (repr(install.install_base),
repr(install.install_platbase)))
@@ -120,8 +107,7 @@ class bdist_dumb (Command):
# Make the archive
filename = self.make_archive(pseudoinstall_root,
- self.format, root_dir=archive_root,
- owner=self.owner, group=self.group)
+ self.format, root_dir=archive_root)
if self.distribution.has_ext_modules():
pyversion = get_python_version()
else:
diff --git a/Lib/distutils/command/bdist_msi.py b/Lib/distutils/command/bdist_msi.py
index 703f873b164..b3cfe9ceff7 100644
--- a/Lib/distutils/command/bdist_msi.py
+++ b/Lib/distutils/command/bdist_msi.py
@@ -1,21 +1,19 @@
-# -*- coding: iso-8859-1 -*-
-# Copyright (C) 2005, 2006 Martin von Löwis
+# Copyright (C) 2005, 2006 Martin von Löwis
# Licensed to PSF under a Contributor Agreement.
# The bdist_wininst command proper
# based on bdist_wininst
"""
Implements the bdist_msi command.
"""
-import sys, os
-from sysconfig import get_python_version
+import sys, os
from distutils.core import Command
from distutils.dir_util import remove_tree
+from distutils.sysconfig import get_python_version
from distutils.version import StrictVersion
from distutils.errors import DistutilsOptionError
-from distutils import log
from distutils.util import get_platform
-
+from distutils import log
import msilib
from msilib import schema, sequence, text
from msilib import Directory, Feature, Dialog, add_data
@@ -29,6 +27,7 @@ class PyDialog(Dialog):
default, cancel, bitmap=true)"""
Dialog.__init__(self, *args)
ruler = self.h - 36
+ bmwidth = 152*ruler/328
#if kw.get("bitmap", True):
# self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin")
self.line("BottomLine", 0, ruler, self.w, 0)
@@ -81,7 +80,7 @@ class PyDialog(Dialog):
Return the button, so that events can be associated"""
return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next)
-class bdist_msi (Command):
+class bdist_msi(Command):
description = "create a Microsoft Installer (.msi) binary distribution"
@@ -123,7 +122,7 @@ class bdist_msi (Command):
'3.5', '3.6', '3.7', '3.8', '3.9']
other_version = 'X'
- def initialize_options (self):
+ def initialize_options(self):
self.bdist_dir = None
self.plat_name = None
self.keep_temp = 0
@@ -136,7 +135,7 @@ class bdist_msi (Command):
self.pre_install_script = None
self.versions = None
- def finalize_options (self):
+ def finalize_options(self):
self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
if self.bdist_dir is None:
@@ -151,9 +150,9 @@ class bdist_msi (Command):
self.versions = [self.target_version]
if not self.skip_build and self.distribution.has_ext_modules()\
and self.target_version != short_version:
- raise DistutilsOptionError, \
- "target version can only be %s, or the '--skip-build'" \
- " option must be specified" % (short_version,)
+ raise DistutilsOptionError(
+ "target version can only be %s, or the '--skip-build'"
+ " option must be specified" % (short_version,))
else:
self.versions = list(self.all_versions)
@@ -163,21 +162,20 @@ class bdist_msi (Command):
)
if self.pre_install_script:
- raise DistutilsOptionError, "the pre-install-script feature is not yet implemented"
+ raise DistutilsOptionError(
+ "the pre-install-script feature is not yet implemented")
if self.install_script:
for script in self.distribution.scripts:
if self.install_script == os.path.basename(script):
break
else:
- raise DistutilsOptionError, \
- "install_script '%s' not found in scripts" % \
- self.install_script
+ raise DistutilsOptionError(
+ "install_script '%s' not found in scripts"
+ % self.install_script)
self.install_script_key = None
- # finalize_options()
-
- def run (self):
+ def run(self):
if not self.skip_build:
self.run_command('build')
@@ -424,6 +422,7 @@ class bdist_msi (Command):
# see "Dialog Style Bits"
modal = 3 # visible | modal
modeless = 1 # visible
+ track_disk_space = 32
# UI customization properties
add_data(db, "Property",
diff --git a/Lib/distutils/command/bdist_rpm.py b/Lib/distutils/command/bdist_rpm.py
index 595824367e3..ac4621791d5 100644
--- a/Lib/distutils/command/bdist_rpm.py
+++ b/Lib/distutils/command/bdist_rpm.py
@@ -3,20 +3,16 @@
Implements the Distutils 'bdist_rpm' command (create RPM source and binary
distributions)."""
-__revision__ = "$Id$"
-
-import sys
-import os
-import string
-
+import subprocess, sys, os
from distutils.core import Command
from distutils.debug import DEBUG
+from distutils.util import get_platform
from distutils.file_util import write_file
-from distutils.errors import (DistutilsOptionError, DistutilsPlatformError,
- DistutilsFileError, DistutilsExecError)
+from distutils.errors import *
+from distutils.sysconfig import get_python_version
from distutils import log
-class bdist_rpm (Command):
+class bdist_rpm(Command):
description = "create an RPM distribution"
@@ -137,7 +133,7 @@ class bdist_rpm (Command):
'rpm2-mode': 'rpm3-mode'}
- def initialize_options (self):
+ def initialize_options(self):
self.bdist_base = None
self.rpm_base = None
self.dist_dir = None
@@ -182,33 +178,29 @@ class bdist_rpm (Command):
self.force_arch = None
self.quiet = 0
- # initialize_options()
-
-
- def finalize_options (self):
+ def finalize_options(self):
self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
if self.rpm_base is None:
if not self.rpm3_mode:
- raise DistutilsOptionError, \
- "you must specify --rpm-base in RPM 2 mode"
+ raise DistutilsOptionError(
+ "you must specify --rpm-base in RPM 2 mode")
self.rpm_base = os.path.join(self.bdist_base, "rpm")
if self.python is None:
if self.fix_python:
self.python = sys.executable
else:
- self.python = "python"
+ self.python = "python3"
elif self.fix_python:
- raise DistutilsOptionError, \
- "--python and --fix-python are mutually exclusive options"
+ raise DistutilsOptionError(
+ "--python and --fix-python are mutually exclusive options")
if os.name != 'posix':
- raise DistutilsPlatformError, \
- ("don't know how to create RPM "
+ raise DistutilsPlatformError("don't know how to create RPM "
"distributions on platform %s" % os.name)
if self.binary_only and self.source_only:
- raise DistutilsOptionError, \
- "cannot supply both '--source-only' and '--binary-only'"
+ raise DistutilsOptionError(
+ "cannot supply both '--source-only' and '--binary-only'")
# don't pass CFLAGS to pure python distributions
if not self.distribution.has_ext_modules():
@@ -217,9 +209,7 @@ class bdist_rpm (Command):
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
self.finalize_package_data()
- # finalize_options()
-
- def finalize_package_data (self):
+ def finalize_package_data(self):
self.ensure_string('group', "Development/Libraries")
self.ensure_string('vendor',
"%s <%s>" % (self.distribution.get_contact(),
@@ -263,17 +253,14 @@ class bdist_rpm (Command):
self.ensure_string_list('obsoletes')
self.ensure_string('force_arch')
- # finalize_package_data ()
-
-
- def run (self):
+ def run(self):
if DEBUG:
- print "before _get_package_data():"
- print "vendor =", self.vendor
- print "packager =", self.packager
- print "doc_files =", self.doc_files
- print "changelog =", self.changelog
+ print("before _get_package_data():")
+ print("vendor =", self.vendor)
+ print("packager =", self.packager)
+ print("doc_files =", self.doc_files)
+ print("changelog =", self.changelog)
# make directories
if self.spec_only:
@@ -317,9 +304,8 @@ class bdist_rpm (Command):
if os.path.exists(self.icon):
self.copy_file(self.icon, source_dir)
else:
- raise DistutilsFileError, \
- "icon file '%s' does not exist" % self.icon
-
+ raise DistutilsFileError(
+ "icon file '%s' does not exist" % self.icon)
# build package
log.info("building RPMs")
@@ -334,6 +320,7 @@ class bdist_rpm (Command):
rpm_cmd.append('-bb')
else:
rpm_cmd.append('-ba')
+ rpm_cmd.extend(['--define', '__python %s' % self.python])
if self.rpm3_mode:
rpm_cmd.extend(['--define',
'_topdir %s' % os.path.abspath(self.rpm_base)])
@@ -358,11 +345,11 @@ class bdist_rpm (Command):
try:
binary_rpms = []
source_rpm = None
- while 1:
+ while True:
line = out.readline()
if not line:
break
- l = string.split(string.strip(line))
+ l = line.strip().split()
assert(len(l) == 2)
binary_rpms.append(l[1])
# The source rpm is named after the first entry in the spec file
@@ -401,7 +388,6 @@ class bdist_rpm (Command):
os.path.basename(rpm))
self.distribution.dist_files.append(
('bdist_rpm', pyversion, filename))
- # run()
def _dist_path(self, path):
return os.path.join(self.dist_dir, os.path.basename(path))
@@ -420,6 +406,21 @@ class bdist_rpm (Command):
'Summary: ' + self.distribution.get_description(),
]
+ # Workaround for #14443 which affects some RPM based systems such as
+ # RHEL6 (and probably derivatives)
+ vendor_hook = subprocess.getoutput('rpm --eval %{__os_install_post}')
+ # Generate a potential replacement value for __os_install_post (whilst
+ # normalizing the whitespace to simplify the test for whether the
+ # invocation of brp-python-bytecompile passes in __python):
+ vendor_hook = '\n'.join([' %s \\' % line.strip()
+ for line in vendor_hook.splitlines()])
+ problem = "brp-python-bytecompile \\\n"
+ fixed = "brp-python-bytecompile %{__python} \\\n"
+ fixed_hook = vendor_hook.replace(problem, fixed)
+ if fixed_hook != vendor_hook:
+ spec_file.append('# Workaround for http://bugs.python.org/issue14443')
+ spec_file.append('%define __os_install_post ' + fixed_hook + '\n')
+
# put locale summaries into spec file
# XXX not supported for now (hard to put a dictionary
# in a config file -- arg!)
@@ -460,9 +461,9 @@ class bdist_rpm (Command):
'Conflicts',
'Obsoletes',
):
- val = getattr(self, string.lower(field))
+ val = getattr(self, field.lower())
if isinstance(val, list):
- spec_file.append('%s: %s' % (field, string.join(val)))
+ spec_file.append('%s: %s' % (field, ' '.join(val)))
elif val is not None:
spec_file.append('%s: %s' % (field, val))
@@ -475,7 +476,7 @@ class bdist_rpm (Command):
if self.build_requires:
spec_file.append('BuildRequires: ' +
- string.join(self.build_requires))
+ ' '.join(self.build_requires))
if self.icon:
spec_file.append('Icon: ' + os.path.basename(self.icon))
@@ -536,7 +537,7 @@ class bdist_rpm (Command):
'',
'%' + rpm_opt,])
if val:
- spec_file.extend(string.split(open(val, 'r').read(), '\n'))
+ spec_file.extend(open(val, 'r').read().split('\n'))
else:
spec_file.append(default)
@@ -549,7 +550,7 @@ class bdist_rpm (Command):
])
if self.doc_files:
- spec_file.append('%doc ' + string.join(self.doc_files))
+ spec_file.append('%doc ' + ' '.join(self.doc_files))
if self.changelog:
spec_file.extend([
@@ -559,16 +560,14 @@ class bdist_rpm (Command):
return spec_file
- # _make_spec_file ()
-
def _format_changelog(self, changelog):
"""Format the changelog correctly and convert it to a list of strings
"""
if not changelog:
return changelog
new_changelog = []
- for line in string.split(string.strip(changelog), '\n'):
- line = string.strip(line)
+ for line in changelog.strip().split('\n'):
+ line = line.strip()
if line[0] == '*':
new_changelog.extend(['', line])
elif line[0] == '-':
@@ -581,7 +580,3 @@ class bdist_rpm (Command):
del new_changelog[0]
return new_changelog
-
- # _format_changelog()
-
-# class bdist_rpm
diff --git a/Lib/distutils/command/bdist_wininst.py b/Lib/distutils/command/bdist_wininst.py
index aa9383af98b..e3ed3ad82c1 100644
--- a/Lib/distutils/command/bdist_wininst.py
+++ b/Lib/distutils/command/bdist_wininst.py
@@ -3,21 +3,15 @@
Implements the Distutils 'bdist_wininst' command: create a windows installer
exe-program."""
-__revision__ = "$Id$"
-
-import sys
-import os
-import string
-
-from sysconfig import get_python_version
-
+import sys, os
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.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):
description = "create an executable installer for MS Windows"
@@ -61,7 +55,7 @@ class bdist_wininst (Command):
boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
'skip-build']
- def initialize_options (self):
+ def initialize_options(self):
self.bdist_dir = None
self.plat_name = None
self.keep_temp = 0
@@ -76,10 +70,8 @@ class bdist_wininst (Command):
self.pre_install_script = None
self.user_access_control = None
- # initialize_options()
-
- def finalize_options (self):
+ def finalize_options(self):
self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
if self.bdist_dir is None:
@@ -98,9 +90,9 @@ class bdist_wininst (Command):
if not self.skip_build and self.distribution.has_ext_modules():
short_version = get_python_version()
if self.target_version and self.target_version != short_version:
- raise DistutilsOptionError, \
+ raise DistutilsOptionError(
"target version can only be %s, or the '--skip-build'" \
- " option must be specified" % (short_version,)
+ " option must be specified" % (short_version,))
self.target_version = short_version
self.set_undefined_options('bdist',
@@ -113,13 +105,11 @@ class bdist_wininst (Command):
if self.install_script == os.path.basename(script):
break
else:
- raise DistutilsOptionError, \
- "install_script '%s' not found in scripts" % \
- self.install_script
- # finalize_options()
-
+ raise DistutilsOptionError(
+ "install_script '%s' not found in scripts"
+ % self.install_script)
- def run (self):
+ def run(self):
if (sys.platform != "win32" and
(self.distribution.has_ext_modules() or
self.distribution.has_c_libraries())):
@@ -160,7 +150,7 @@ class bdist_wininst (Command):
# Use a custom scheme for the zip-file, because we have to decide
# at installation time which scheme to use.
for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
- value = string.upper(key)
+ value = key.upper()
if key == 'headers':
value = value + '/Include/$dist_name'
setattr(install,
@@ -200,11 +190,8 @@ class bdist_wininst (Command):
if not self.keep_temp:
remove_tree(self.bdist_dir, dry_run=self.dry_run)
- # run()
-
- def get_inidata (self):
+ def get_inidata(self):
# Return data describing the installation.
-
lines = []
metadata = self.distribution.metadata
@@ -217,14 +204,14 @@ class bdist_wininst (Command):
# Escape newline characters
def escape(s):
- return string.replace(s, "\n", "\\n")
+ return s.replace("\n", "\\n")
for name in ["author", "author_email", "description", "maintainer",
"maintainer_email", "name", "url", "version"]:
data = getattr(metadata, name, "")
if data:
info = info + ("\n %s: %s" % \
- (string.capitalize(name), escape(data)))
+ (name.capitalize(), escape(data)))
lines.append("%s=%s" % (name, escape(data)))
# The [setup] section contains entries controlling
@@ -247,11 +234,9 @@ class bdist_wininst (Command):
build_info = "Built %s with distutils-%s" % \
(time.ctime(time.time()), distutils.__version__)
lines.append("build_info=%s" % build_info)
- return string.join(lines, "\n")
-
- # get_inidata()
+ return "\n".join(lines)
- def create_exe (self, arcname, fullname, bitmap=None):
+ def create_exe(self, arcname, fullname, bitmap=None):
import struct
self.mkpath(self.dist_dir)
@@ -273,22 +258,22 @@ class bdist_wininst (Command):
file.write(bitmapdata)
# Convert cfgdata from unicode to ascii, mbcs encoded
- try:
- unicode
- except NameError:
- pass
- else:
- if isinstance(cfgdata, unicode):
- cfgdata = cfgdata.encode("mbcs")
+ if isinstance(cfgdata, str):
+ cfgdata = cfgdata.encode("mbcs")
# Append the pre-install script
- cfgdata = cfgdata + "\0"
+ cfgdata = cfgdata + b"\0"
if self.pre_install_script:
- script_data = open(self.pre_install_script, "r").read()
- cfgdata = cfgdata + script_data + "\n\0"
+ # We need to normalize newlines, so we open in text mode and
+ # convert back to bytes. "latin1" simply avoids any possible
+ # failures.
+ with open(self.pre_install_script, "r",
+ encoding="latin1") as script:
+ script_data = script.read().encode("latin1")
+ cfgdata = cfgdata + script_data + b"\n\0"
else:
# empty pre-install script
- cfgdata = cfgdata + "\0"
+ cfgdata = cfgdata + b"\0"
file.write(cfgdata)
# The 'magic number' 0x1234567B is used to make sure that the
@@ -304,8 +289,6 @@ class bdist_wininst (Command):
file.write(header)
file.write(open(arcname, "rb").read())
- # create_exe()
-
def get_installer_filename(self, fullname):
# Factored out to allow overriding in subclasses
if self.target_version:
@@ -318,9 +301,8 @@ class bdist_wininst (Command):
installer_name = os.path.join(self.dist_dir,
"%s.%s.exe" % (fullname, self.plat_name))
return installer_name
- # get_installer_filename()
- def get_exe_bytes (self):
+ def get_exe_bytes(self):
from distutils.msvccompiler import get_build_version
# If a target-version other than the current version has been
# specified, then using the MSVC version from *this* build is no good.
@@ -365,4 +347,3 @@ class bdist_wininst (Command):
return f.read()
finally:
f.close()
-# class bdist_wininst
diff --git a/Lib/distutils/command/build.py b/Lib/distutils/command/build.py
index f84bf359dc6..cfc15cf0ddc 100644
--- a/Lib/distutils/command/build.py
+++ b/Lib/distutils/command/build.py
@@ -2,18 +2,17 @@
Implements the Distutils 'build' command."""
-__revision__ = "$Id$"
-
import sys, os
-
-from distutils.util import get_platform
from distutils.core import Command
from distutils.errors import DistutilsOptionError
+from distutils.util import get_platform
+
def show_compilers():
from distutils.ccompiler import show_compilers
show_compilers()
+
class build(Command):
description = "build everything needed to install"
@@ -126,20 +125,22 @@ class build(Command):
for cmd_name in self.get_sub_commands():
self.run_command(cmd_name)
+
# -- Predicates for the sub-command list ---------------------------
- def has_pure_modules (self):
+ def has_pure_modules(self):
return self.distribution.has_pure_modules()
- def has_c_libraries (self):
+ def has_c_libraries(self):
return self.distribution.has_c_libraries()
- def has_ext_modules (self):
+ def has_ext_modules(self):
return self.distribution.has_ext_modules()
- def has_scripts (self):
+ def has_scripts(self):
return self.distribution.has_scripts()
+
sub_commands = [('build_py', has_pure_modules),
('build_clib', has_c_libraries),
('build_ext', has_ext_modules),
diff --git a/Lib/distutils/command/build_clib.py b/Lib/distutils/command/build_clib.py
index 205587e7fc9..3e20ef23cd8 100644
--- a/Lib/distutils/command/build_clib.py
+++ b/Lib/distutils/command/build_clib.py
@@ -4,8 +4,6 @@ Implements the Distutils 'build_clib' command, to build a C/C++ library
that is included in the module distribution and needed by an extension
module."""
-__revision__ = "$Id$"
-
# XXX this module has *lots* of code ripped-off quite transparently from
# build_ext.py -- not surprisingly really, as the work required to build
@@ -18,7 +16,7 @@ __revision__ = "$Id$"
import os
from distutils.core import Command
-from distutils.errors import DistutilsSetupError
+from distutils.errors import *
from distutils.sysconfig import customize_compiler
from distutils import log
@@ -92,6 +90,7 @@ class build_clib(Command):
# XXX same as for build_ext -- what about 'self.define' and
# 'self.undef' ?
+
def run(self):
if not self.libraries:
return
@@ -127,30 +126,30 @@ class build_clib(Command):
just returns otherwise.
"""
if not isinstance(libraries, list):
- raise DistutilsSetupError, \
- "'libraries' option must be a list of tuples"
+ raise DistutilsSetupError(
+ "'libraries' option must be a list of tuples")
for lib in libraries:
if not isinstance(lib, tuple) and len(lib) != 2:
- raise DistutilsSetupError, \
- "each element of 'libraries' must a 2-tuple"
+ raise DistutilsSetupError(
+ "each element of 'libraries' must a 2-tuple")
name, build_info = lib
if not isinstance(name, str):
- raise DistutilsSetupError, \
- "first element of each tuple in 'libraries' " + \
- "must be a string (the library name)"
+ raise DistutilsSetupError(
+ "first element of each tuple in 'libraries' "
+ "must be a string (the library name)")
+
if '/' in name or (os.sep != '/' and os.sep in name):
- raise DistutilsSetupError, \
- ("bad library name '%s': " +
- "may not contain directory separators") % \
- lib[0]
+ raise DistutilsSetupError("bad library name '%s': "
+ "may not contain directory separators" % lib[0])
if not isinstance(build_info, dict):
- raise DistutilsSetupError, \
- "second element of each tuple in 'libraries' " + \
- "must be a dictionary (build info)"
+ raise DistutilsSetupError(
+ "second element of each tuple in 'libraries' "
+ "must be a dictionary (build info)")
+
def get_library_names(self):
# Assume the library list is valid -- 'check_library_list()' is
@@ -170,22 +169,23 @@ class build_clib(Command):
for (lib_name, build_info) in self.libraries:
sources = build_info.get('sources')
if sources is None or not isinstance(sources, (list, tuple)):
- raise DistutilsSetupError, \
- ("in 'libraries' option (library '%s'), "
+ raise DistutilsSetupError(
+ "in 'libraries' option (library '%s'), "
"'sources' must be present and must be "
- "a list of source filenames") % lib_name
+ "a list of source filenames" % lib_name)
filenames.extend(sources)
return filenames
+
def build_libraries(self, libraries):
for (lib_name, build_info) in libraries:
sources = build_info.get('sources')
if sources is None or not isinstance(sources, (list, tuple)):
- raise DistutilsSetupError, \
- ("in 'libraries' option (library '%s'), " +
- "'sources' must be present and must be " +
- "a list of source filenames") % lib_name
+ raise DistutilsSetupError(
+ "in 'libraries' option (library '%s'), "
+ "'sources' must be present and must be "
+ "a list of source filenames" % lib_name)
sources = list(sources)
log.info("building '%s' library", lib_name)
diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py
index 923197bac43..34b61bdb828 100644
--- a/Lib/distutils/command/build_ext.py
+++ b/Lib/distutils/command/build_ext.py
@@ -4,13 +4,7 @@ Implements the Distutils 'build_ext' command, for building extension
modules (currently limited to C extensions, should accommodate C++
extensions ASAP)."""
-# This module should be kept compatible with Python 2.1.
-
-__revision__ = "$Id$"
-
-import sys, os, string, re
-from types import *
-from site import USER_BASE, USER_SITE
+import sys, os, re
from distutils.core import Command
from distutils.errors import *
from distutils.sysconfig import customize_compiler, get_python_version
@@ -19,6 +13,14 @@ from distutils.extension import Extension
from distutils.util import get_platform
from distutils import log
+# this keeps compatibility from 2.3 to 2.5
+if sys.version < "2.6":
+ USER_BASE = None
+ HAS_USER_SITE = False
+else:
+ from site import USER_BASE
+ HAS_USER_SITE = True
+
if os.name == 'nt':
from distutils.msvccompiler import get_build_version
MSVC_VERSION = int(get_build_version())
@@ -34,7 +36,7 @@ def show_compilers ():
show_compilers()
-class build_ext (Command):
+class build_ext(Command):
description = "build C/C++ extensions (compile/link to build directory)"
@@ -94,18 +96,21 @@ class build_ext (Command):
"list of SWIG command line options"),
('swig=', None,
"path to the SWIG executable"),
- ('user', None,
- "add user include, library and rpath"),
]
- boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user']
+ boolean_options = ['inplace', 'debug', 'force', 'swig-cpp']
+
+ if HAS_USER_SITE:
+ user_options.append(('user', None,
+ "add user include, library and rpath"))
+ boolean_options.append('user')
help_options = [
('help-compiler', None,
"list available compilers", show_compilers),
]
- def initialize_options (self):
+ def initialize_options(self):
self.extensions = None
self.build_lib = None
self.plat_name = None
@@ -168,13 +173,13 @@ class build_ext (Command):
self.libraries = []
if self.library_dirs is None:
self.library_dirs = []
- elif type(self.library_dirs) is StringType:
- self.library_dirs = string.split(self.library_dirs, os.pathsep)
+ elif isinstance(self.library_dirs, str):
+ self.library_dirs = self.library_dirs.split(os.pathsep)
if self.rpath is None:
self.rpath = []
- elif type(self.rpath) is StringType:
- self.rpath = string.split(self.rpath, os.pathsep)
+ elif isinstance(self.rpath, str):
+ self.rpath = self.rpath.split(os.pathsep)
# for extensions under windows use different directories
# for Release and Debug builds.
@@ -251,7 +256,7 @@ class build_ext (Command):
if self.define:
defines = self.define.split(',')
- self.define = map(lambda symbol: (symbol, '1'), defines)
+ self.define = [(symbol, '1') for symbol in defines]
# The option for macros to undefine is also a string from the
# option parsing, but has to be a list. Multiple symbols can also
@@ -349,8 +354,8 @@ class build_ext (Command):
just returns otherwise.
"""
if not isinstance(extensions, list):
- raise DistutilsSetupError, \
- "'ext_modules' option must be a list of Extension instances"
+ raise DistutilsSetupError(
+ "'ext_modules' option must be a list of Extension instances")
for i, ext in enumerate(extensions):
if isinstance(ext, Extension):
@@ -358,8 +363,8 @@ class build_ext (Command):
# by Extension constructor)
if not isinstance(ext, tuple) or len(ext) != 2:
- raise DistutilsSetupError, \
- ("each element of 'ext_modules' option must be an "
+ raise DistutilsSetupError(
+ "each element of 'ext_modules' option must be an "
"Extension instance or 2-tuple")
ext_name, build_info = ext
@@ -370,13 +375,13 @@ class build_ext (Command):
if not (isinstance(ext_name, str) and
extension_name_re.match(ext_name)):
- raise DistutilsSetupError, \
- ("first element of each tuple in 'ext_modules' "
+ raise DistutilsSetupError(
+ "first element of each tuple in 'ext_modules' "
"must be the extension name (a string)")
if not isinstance(build_info, dict):
- raise DistutilsSetupError, \
- ("second element of each tuple in 'ext_modules' "
+ raise DistutilsSetupError(
+ "second element of each tuple in 'ext_modules' "
"must be a dictionary (build info)")
# OK, the (ext_name, build_info) dict is type-safe: convert it
@@ -406,9 +411,9 @@ class build_ext (Command):
ext.undef_macros = []
for macro in macros:
if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
- raise DistutilsSetupError, \
- ("'macros' element of build info dict "
- "must be 1- or 2-tuple")
+ raise DistutilsSetupError(
+ "'macros' element of build info dict "
+ "must be 1- or 2-tuple")
if len(macro) == 1:
ext.undef_macros.append(macro[0])
elif len(macro) == 2:
@@ -423,7 +428,6 @@ class build_ext (Command):
# Wouldn't it be neat if we knew the names of header files too...
for ext in self.extensions:
filenames.extend(ext.sources)
-
return filenames
def get_outputs(self):
@@ -445,15 +449,21 @@ class build_ext (Command):
self.check_extensions_list(self.extensions)
for ext in self.extensions:
- self.build_extension(ext)
+ try:
+ self.build_extension(ext)
+ except (CCompilerError, DistutilsError, CompileError) as e:
+ if not ext.optional:
+ raise
+ self.warn('building extension "%s" failed: %s' %
+ (ext.name, e))
def build_extension(self, ext):
sources = ext.sources
- if sources is None or type(sources) not in (ListType, TupleType):
- raise DistutilsSetupError, \
- ("in 'ext_modules' option (extension '%s'), " +
- "'sources' must be present and must be " +
- "a list of source filenames") % ext.name
+ if sources is None or not isinstance(sources, (list, tuple)):
+ raise DistutilsSetupError(
+ "in 'ext_modules' option (extension '%s'), "
+ "'sources' must be present and must be "
+ "a list of source filenames" % ext.name)
sources = list(sources)
ext_path = self.get_ext_fullpath(ext.name)
@@ -529,15 +539,12 @@ class build_ext (Command):
build_temp=self.build_temp,
target_lang=language)
-
- def swig_sources (self, sources, extension):
-
+ def swig_sources(self, sources, extension):
"""Walk the list of source files in 'sources', looking for SWIG
interface (.i) files. Run SWIG on all that are found, and
return a modified 'sources' list with SWIG source files replaced
by the generated C (or C++) files.
"""
-
new_sources = []
swig_sources = []
swig_targets = {}
@@ -586,18 +593,14 @@ class build_ext (Command):
return new_sources
- # swig_sources ()
-
- def find_swig (self):
+ def find_swig(self):
"""Return the name of the SWIG executable. On Unix, this is
just "swig" -- it should be in the PATH. Tries a bit harder on
Windows.
"""
-
if os.name == "posix":
return "swig"
elif os.name == "nt":
-
# Look for SWIG in its standard installation directory on
# Windows (or so I presume!). If we find it there, great;
# if not, act like Unix and assume it's in the PATH.
@@ -607,17 +610,13 @@ class build_ext (Command):
return fn
else:
return "swig.exe"
-
elif os.name == "os2":
# assume swig available in the PATH.
return "swig.exe"
-
else:
- raise DistutilsPlatformError, \
- ("I don't know how to find (much less run) SWIG "
- "on platform '%s'") % os.name
-
- # find_swig ()
+ raise DistutilsPlatformError(
+ "I don't know how to find (much less run) SWIG "
+ "on platform '%s'" % os.name)
# -- Name generators -----------------------------------------------
# (extension names, filenames, whatever)
@@ -627,14 +626,9 @@ class build_ext (Command):
The file is located in `build_lib` or directly in the package
(inplace option).
"""
- # makes sure the extension name is only using dots
- all_dots = string.maketrans('/'+os.sep, '..')
- ext_name = ext_name.translate(all_dots)
-
fullname = self.get_ext_fullname(ext_name)
modpath = fullname.split('.')
- filename = self.get_ext_filename(ext_name)
- filename = os.path.split(filename)[-1]
+ filename = self.get_ext_filename(modpath[-1])
if not self.inplace:
# no further work needed
@@ -668,7 +662,7 @@ class build_ext (Command):
"foo\bar.pyd").
"""
from distutils.sysconfig import get_config_var
- ext_path = string.split(ext_name, '.')
+ ext_path = ext_name.split('.')
# OS/2 has an 8 character module (extension) limit :-(
if os.name == "os2":
ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
@@ -678,18 +672,18 @@ class build_ext (Command):
return os.path.join(*ext_path) + '_d' + so_ext
return os.path.join(*ext_path) + so_ext
- def get_export_symbols (self, ext):
+ def get_export_symbols(self, ext):
"""Return the list of symbols that a shared extension has to
export. This either uses 'ext.export_symbols' or, if it's not
- provided, "init" + module_name. Only relevant on Windows, where
- the .pyd file (DLL) must export the module "init" function.
+ provided, "PyInit_" + module_name. Only relevant on Windows, where
+ the .pyd file (DLL) must export the module "PyInit_" function.
"""
- initfunc_name = "init" + ext.name.split('.')[-1]
+ initfunc_name = "PyInit_" + ext.name.split('.')[-1]
if initfunc_name not in ext.export_symbols:
ext.export_symbols.append(initfunc_name)
return ext.export_symbols
- def get_libraries (self, ext):
+ def get_libraries(self, ext):
"""Return the list of libraries to link against when building a
shared extension. On most platforms, this is just 'ext.libraries';
on Windows and OS/2, we add the Python library (eg. python20.dll).
@@ -748,7 +742,6 @@ class build_ext (Command):
# don't extend ext.libraries, it may be shared with other
# extensions, it is a reference to the original list
return ext.libraries + [pythonlib, "m"] + extra
-
elif sys.platform == 'darwin':
# Don't use the default code below
return ext.libraries
@@ -758,11 +751,9 @@ class build_ext (Command):
else:
from distutils import sysconfig
if sysconfig.get_config_var('Py_ENABLE_SHARED'):
- template = "python%d.%d"
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+ pythonlib = 'python{}.{}{}'.format(
+ sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff,
+ sys.abiflags)
return ext.libraries + [pythonlib]
else:
return ext.libraries
-
-# class build_ext
diff --git a/Lib/distutils/command/build_py.py b/Lib/distutils/command/build_py.py
index 04c455f0eb9..1371b3d6ff9 100644
--- a/Lib/distutils/command/build_py.py
+++ b/Lib/distutils/command/build_py.py
@@ -2,18 +2,17 @@
Implements the Distutils 'build_py' command."""
-__revision__ = "$Id$"
-
import os
+import imp
import sys
from glob import glob
from distutils.core import Command
-from distutils.errors import DistutilsOptionError, DistutilsFileError
-from distutils.util import convert_path
+from distutils.errors import *
+from distutils.util import convert_path, Mixin2to3
from distutils import log
-class build_py(Command):
+class build_py (Command):
description = "\"build\" pure Python modules (copy to build directory)"
@@ -133,6 +132,7 @@ class build_py(Command):
def build_package_data(self):
"""Copy data files into build directory"""
+ lastdir = None
for package, src_dir, build_dir, filenames in self.data_files:
for filename in filenames:
target = os.path.join(build_dir, filename)
@@ -144,7 +144,6 @@ class build_py(Command):
"""Return the directory, relative to the top of the source
distribution, where package 'package' should be found
(at least according to the 'package_dir' option, if any)."""
-
path = package.split('.')
if not self.package_dir:
@@ -313,9 +312,11 @@ class build_py(Command):
outputs.append(filename)
if include_bytecode:
if self.compile:
- outputs.append(filename + "c")
+ outputs.append(imp.cache_from_source(filename,
+ debug_override=True))
if self.optimize > 0:
- outputs.append(filename + "o")
+ outputs.append(imp.cache_from_source(filename,
+ debug_override=False))
outputs += [
os.path.join(build_dir, filename)
@@ -343,7 +344,6 @@ class build_py(Command):
def build_modules(self):
modules = self.find_modules()
for (package, module, module_file) in modules:
-
# Now "build" the module -- ie. copy the source file to
# self.build_lib (the build directory for Python source).
# (Actually, it gets copied to the directory for this package
@@ -352,7 +352,6 @@ class build_py(Command):
def build_packages(self):
for package in self.packages:
-
# Get list of (package, module, module_file) tuples based on
# scanning the package directory. 'package' is only included
# in the tuple so that 'find_modules()' and
@@ -384,10 +383,33 @@ class build_py(Command):
# XXX this code is essentially the same as the 'byte_compile()
# method of the "install_lib" command, except for the determination
# of the 'prefix' string. Hmmm.
-
if self.compile:
byte_compile(files, optimize=0,
force=self.force, prefix=prefix, dry_run=self.dry_run)
if self.optimize > 0:
byte_compile(files, optimize=self.optimize,
force=self.force, prefix=prefix, dry_run=self.dry_run)
+
+class build_py_2to3(build_py, Mixin2to3):
+ def run(self):
+ self.updated_files = []
+
+ # Base class code
+ if self.py_modules:
+ self.build_modules()
+ if self.packages:
+ self.build_packages()
+ self.build_package_data()
+
+ # 2to3
+ self.run_2to3(self.updated_files)
+
+ # Remaining base class code
+ self.byte_compile(self.get_outputs(include_bytecode=0))
+
+ def build_module(self, module, module_file, package):
+ res = build_py.build_module(self, module, module_file, package)
+ if res[1]:
+ # file was copied
+ self.updated_files.append(res[0])
+ return res
diff --git a/Lib/distutils/command/build_scripts.py b/Lib/distutils/command/build_scripts.py
index 567df6587ec..ec434770610 100644
--- a/Lib/distutils/command/build_scripts.py
+++ b/Lib/distutils/command/build_scripts.py
@@ -2,19 +2,19 @@
Implements the Distutils 'build_scripts' command."""
-__revision__ = "$Id$"
-
import os, re
from stat import ST_MODE
+from distutils import sysconfig
from distutils.core import Command
from distutils.dep_util import newer
-from distutils.util import convert_path
+from distutils.util import convert_path, Mixin2to3
from distutils import log
+import tokenize
# check if Python is called on the first line with this expression
-first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
+first_line_re = re.compile(b'^#!.*python[0-9.]*([ \t].*)?$')
-class build_scripts (Command):
+class build_scripts(Command):
description = "\"build\" scripts (copy and fixup #! line)"
@@ -27,14 +27,14 @@ class build_scripts (Command):
boolean_options = ['force']
- def initialize_options (self):
+ def initialize_options(self):
self.build_dir = None
self.scripts = None
self.force = None
self.executable = None
self.outfiles = None
- def finalize_options (self):
+ def finalize_options(self):
self.set_undefined_options('build',
('build_scripts', 'build_dir'),
('force', 'force'),
@@ -44,23 +44,23 @@ class build_scripts (Command):
def get_source_files(self):
return self.scripts
- def run (self):
+ def run(self):
if not self.scripts:
return
self.copy_scripts()
- def copy_scripts (self):
+ def copy_scripts(self):
"""Copy each script listed in 'self.scripts'; if it's marked as a
Python script in the Unix way (first line matches 'first_line_re',
ie. starts with "\#!" and contains "python"), then adjust the first
line to refer to the current Python interpreter as we copy.
"""
- _sysconfig = __import__('sysconfig')
self.mkpath(self.build_dir)
outfiles = []
+ updated_files = []
for script in self.scripts:
- adjust = 0
+ adjust = False
script = convert_path(script)
outfile = os.path.join(self.build_dir, os.path.basename(script))
outfiles.append(outfile)
@@ -73,12 +73,14 @@ class build_scripts (Command):
# that way, we'll get accurate feedback if we can read the
# script.
try:
- f = open(script, "r")
+ f = open(script, "rb")
except IOError:
if not self.dry_run:
raise
f = None
else:
+ encoding, lines = tokenize.detect_encoding(f.readline)
+ f.seek(0)
first_line = f.readline()
if not first_line:
self.warn("%s is an empty file (skipping)" % script)
@@ -86,25 +88,46 @@ class build_scripts (Command):
match = first_line_re.match(first_line)
if match:
- adjust = 1
- post_interp = match.group(1) or ''
+ adjust = True
+ post_interp = match.group(1) or b''
if adjust:
log.info("copying and adjusting %s -> %s", script,
self.build_dir)
+ updated_files.append(outfile)
if not self.dry_run:
- outf = open(outfile, "w")
- if not _sysconfig.is_python_build():
- outf.write("#!%s%s\n" %
- (self.executable,
- post_interp))
+ if not sysconfig.python_build:
+ executable = self.executable
else:
- outf.write("#!%s%s\n" %
- (os.path.join(
- _sysconfig.get_config_var("BINDIR"),
- "python%s%s" % (_sysconfig.get_config_var("VERSION"),
- _sysconfig.get_config_var("EXE"))),
- post_interp))
+ executable = os.path.join(
+ sysconfig.get_config_var("BINDIR"),
+ "python%s%s" % (sysconfig.get_config_var("VERSION"),
+ sysconfig.get_config_var("EXE")))
+ executable = os.fsencode(executable)
+ shebang = b"#!" + executable + post_interp + b"\n"
+ # Python parser starts to read a script using UTF-8 until
+ # it gets a #coding:xxx cookie. The shebang has to be the
+ # first line of a file, the #coding:xxx cookie cannot be
+ # written before. So the shebang has to be decodable from
+ # UTF-8.
+ try:
+ shebang.decode('utf-8')
+ except UnicodeDecodeError:
+ raise ValueError(
+ "The shebang ({!r}) is not decodable "
+ "from utf-8".format(shebang))
+ # If the script is encoded to a custom encoding (use a
+ # #coding:xxx cookie), the shebang has to be decodable from
+ # the script encoding too.
+ try:
+ shebang.decode(encoding)
+ except UnicodeDecodeError:
+ raise ValueError(
+ "The shebang ({!r}) is not decodable "
+ "from the script encoding ({})"
+ .format(shebang, encoding))
+ outf = open(outfile, "wb")
+ outf.write(shebang)
outf.writelines(f.readlines())
outf.close()
if f:
@@ -112,6 +135,7 @@ class build_scripts (Command):
else:
if f:
f.close()
+ updated_files.append(outfile)
self.copy_file(script, outfile)
if os.name == 'posix':
@@ -119,13 +143,19 @@ class build_scripts (Command):
if self.dry_run:
log.info("changing mode of %s", file)
else:
- oldmode = os.stat(file)[ST_MODE] & 07777
- newmode = (oldmode | 0555) & 07777
+ oldmode = os.stat(file)[ST_MODE] & 0o7777
+ newmode = (oldmode | 0o555) & 0o7777
if newmode != oldmode:
log.info("changing mode of %s from %o to %o",
file, oldmode, newmode)
os.chmod(file, newmode)
+ # XXX should we modify self.outfiles?
+ return outfiles, updated_files
- # copy_scripts ()
+class build_scripts_2to3(build_scripts, Mixin2to3):
-# class build_scripts
+ def copy_scripts(self):
+ outfiles, updated_files = build_scripts.copy_scripts(self)
+ if not self.dry_run:
+ self.run_2to3(updated_files)
+ return outfiles, updated_files
diff --git a/Lib/distutils/command/check.py b/Lib/distutils/command/check.py
index 152bf0de98b..22b9349dd60 100644
--- a/Lib/distutils/command/check.py
+++ b/Lib/distutils/command/check.py
@@ -2,10 +2,7 @@
Implements the Distutils 'check' command.
"""
-__revision__ = "$Id$"
-
from distutils.core import Command
-from distutils.dist import PKG_INFO_ENCODING
from distutils.errors import DistutilsSetupError
try:
@@ -14,7 +11,7 @@ try:
from docutils.parsers.rst import Parser
from docutils import frontend
from docutils import nodes
- from StringIO import StringIO
+ from io import StringIO
class SilentReporter(Reporter):
@@ -31,8 +28,9 @@ try:
*children, **kwargs)
HAS_DOCUTILS = True
-except ImportError:
- # docutils is not installed
+except Exception:
+ # Catch all exceptions because exceptions besides ImportError probably
+ # indicate that docutils is not ported to Py3k.
HAS_DOCUTILS = False
class check(Command):
@@ -112,8 +110,6 @@ class check(Command):
def check_restructuredtext(self):
"""Checks if the long string fields are reST-compliant."""
data = self.distribution.get_long_description()
- if not isinstance(data, unicode):
- data = data.decode(PKG_INFO_ENCODING)
for warning in self._check_rst_data(data):
line = warning[-1].get('line')
if line is None:
diff --git a/Lib/distutils/command/clean.py b/Lib/distutils/command/clean.py
index 90ef35f1ca7..0cb27016621 100644
--- a/Lib/distutils/command/clean.py
+++ b/Lib/distutils/command/clean.py
@@ -4,8 +4,6 @@ Implements the Distutils 'clean' command."""
# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18
-__revision__ = "$Id$"
-
import os
from distutils.core import Command
from distutils.dir_util import remove_tree
@@ -76,5 +74,3 @@ class clean(Command):
log.info("removing '%s'", self.build_base)
except OSError:
pass
-
-# class clean
diff --git a/Lib/distutils/command/command_template b/Lib/distutils/command/command_template
index 50bbab7b6ec..6106819db84 100644
--- a/Lib/distutils/command/command_template
+++ b/Lib/distutils/command/command_template
@@ -10,7 +10,7 @@ __revision__ = "$Id$"
from distutils.core import Command
-class x (Command):
+class x(Command):
# Brief (40-50 characters) description of the command
description = ""
@@ -21,25 +21,13 @@ class x (Command):
""),
]
-
- def initialize_options (self):
+ def initialize_options(self):
self. = None
self. = None
self. = None
- # initialize_options()
-
-
- def finalize_options (self):
+ def finalize_options(self):
if self.x is None:
self.x =
- # finalize_options()
-
-
- def run (self):
-
-
- # run()
-
-# class x
+ def run(self):
diff --git a/Lib/distutils/command/config.py b/Lib/distutils/command/config.py
index b084913563a..847e8581605 100644
--- a/Lib/distutils/command/config.py
+++ b/Lib/distutils/command/config.py
@@ -9,17 +9,14 @@ configure-like tasks: "try to compile this C code", or "figure out where
this header file lives".
"""
-__revision__ = "$Id$"
-
-import os
-import re
+import sys, os, re
from distutils.core import Command
from distutils.errors import DistutilsExecError
from distutils.sysconfig import customize_compiler
from distutils import log
-LANG_EXT = {'c': '.c', 'c++': '.cxx'}
+LANG_EXT = {"c": ".c", "c++": ".cxx"}
class config(Command):
@@ -85,7 +82,6 @@ class config(Command):
def run(self):
pass
-
# Utility methods for actual "config" commands. The interfaces are
# loosely based on Autoconf macros of similar names. Sub-classes
# may use these freely.
@@ -108,7 +104,6 @@ class config(Command):
if self.library_dirs:
self.compiler.set_library_dirs(self.library_dirs)
-
def _gen_temp_sourcefile(self, body, headers, lang):
filename = "_configtest" + LANG_EXT[lang]
file = open(filename, "w")
@@ -184,11 +179,11 @@ class config(Command):
"""
from distutils.ccompiler import CompileError
self._check_compiler()
- ok = 1
+ ok = True
try:
self._preprocess(body, headers, include_dirs, lang)
except CompileError:
- ok = 0
+ ok = False
self._clean()
return ok
@@ -209,13 +204,13 @@ class config(Command):
pattern = re.compile(pattern)
file = open(out)
- match = 0
- while 1:
+ match = False
+ while True:
line = file.readline()
if line == '':
break
if pattern.search(line):
- match = 1
+ match = True
break
file.close()
@@ -230,9 +225,9 @@ class config(Command):
self._check_compiler()
try:
self._compile(body, headers, include_dirs, lang)
- ok = 1
+ ok = True
except CompileError:
- ok = 0
+ ok = False
log.info(ok and "success!" or "failure.")
self._clean()
@@ -249,9 +244,9 @@ class config(Command):
try:
self._link(body, headers, include_dirs,
libraries, library_dirs, lang)
- ok = 1
+ ok = True
except (CompileError, LinkError):
- ok = 0
+ ok = False
log.info(ok and "success!" or "failure.")
self._clean()
@@ -269,9 +264,9 @@ class config(Command):
src, obj, exe = self._link(body, headers, include_dirs,
libraries, library_dirs, lang)
self.spawn([exe])
- ok = 1
+ ok = True
except (CompileError, LinkError, DistutilsExecError):
- ok = 0
+ ok = False
log.info(ok and "success!" or "failure.")
self._clean()
@@ -284,7 +279,6 @@ class config(Command):
def check_func(self, func, headers=None, include_dirs=None,
libraries=None, library_dirs=None, decl=0, call=0):
-
"""Determine if function 'func' is available by constructing a
source file that refers to 'func', and compiles and links it.
If everything succeeds, returns true; otherwise returns false.
@@ -298,7 +292,6 @@ class config(Command):
calls it. 'libraries' and 'library_dirs' are used when
linking.
"""
-
self._check_compiler()
body = []
if decl:
@@ -314,8 +307,6 @@ class config(Command):
return self.try_link(body, headers, include_dirs,
libraries, library_dirs)
- # check_func ()
-
def check_lib(self, library, library_dirs=None, headers=None,
include_dirs=None, other_libraries=[]):
"""Determine if 'library' is available to be linked against,
@@ -327,9 +318,8 @@ class config(Command):
has symbols that depend on other libraries.
"""
self._check_compiler()
- return self.try_link("int main (void) { }",
- headers, include_dirs,
- [library]+other_libraries, library_dirs)
+ return self.try_link("int main (void) { }", headers, include_dirs,
+ [library] + other_libraries, library_dirs)
def check_header(self, header, include_dirs=None, library_dirs=None,
lang="c"):
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
index f1f3bd5c6f5..0161898f49a 100644
--- a/Lib/distutils/command/install.py
+++ b/Lib/distutils/command/install.py
@@ -2,14 +2,10 @@
Implements the Distutils 'install' command."""
-from distutils import log
-
-# This module should be kept compatible with Python 2.1.
+import sys
+import os
-__revision__ = "$Id$"
-
-import sys, os, string
-from types import *
+from distutils import log
from distutils.core import Command
from distutils.debug import DEBUG
from distutils.sysconfig import get_config_vars
@@ -18,9 +14,16 @@ from distutils.file_util import write_file
from distutils.util import convert_path, subst_vars, change_root
from distutils.util import get_platform
from distutils.errors import DistutilsOptionError
-from site import USER_BASE
-from site import USER_SITE
+# 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":
WINDOWS_SCHEME = {
@@ -43,7 +46,7 @@ INSTALL_SCHEMES = {
'unix_prefix': {
'purelib': '$base/lib/python$py_version_short/site-packages',
'platlib': '$platbase/lib/python$py_version_short/site-packages',
- 'headers': '$base/include/python$py_version_short/$dist_name',
+ 'headers': '$base/include/python$py_version_short$abiflags/$dist_name',
'scripts': '$base/bin',
'data' : '$base',
},
@@ -54,21 +57,7 @@ INSTALL_SCHEMES = {
'scripts': '$base/bin',
'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_user': {
- 'purelib': '$usersite',
- 'platlib': '$usersite',
- 'headers': '$userbase/Python$py_version_nodot/Include/$dist_name',
- 'scripts': '$userbase/Scripts',
- 'data' : '$userbase',
- },
'os2': {
'purelib': '$base/Lib/site-packages',
'platlib': '$base/Lib/site-packages',
@@ -76,14 +65,34 @@ INSTALL_SCHEMES = {
'scripts': '$base/Scripts',
'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',
+ 'platlib': '$usersite',
+ 'headers':
+ '$userbase/include/python$py_version_short$abiflags/$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,
@@ -91,7 +100,7 @@ INSTALL_SCHEMES = {
SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
-class install (Command):
+class install(Command):
description = "install everything from build directory"
@@ -103,8 +112,6 @@ class install (Command):
"(Unix only) prefix for platform-specific files"),
('home=', None,
"(Unix only) home directory to install under"),
- ('user', None,
- "install in user site-package '%s'" % USER_SITE),
# Or, just set the base director(y|ies)
('install-base=', None,
@@ -156,12 +163,18 @@ class install (Command):
"filename in which to record list of installed files"),
]
- boolean_options = ['compile', 'force', 'skip-build', 'user']
- negative_opt = {'no-compile' : 'compile'}
+ boolean_options = ['compile', 'force', 'skip-build']
+ if HAS_USER_SITE:
+ user_options.append(('user', None,
+ "install in user site-package '%s'" % USER_SITE))
+ boolean_options.append('user')
+
+ negative_opt = {'no-compile' : 'compile'}
- def initialize_options (self):
+ def initialize_options(self):
+ """Initializes options."""
# High-level options: these select both an installation base
# and scheme.
self.prefix = None
@@ -237,8 +250,8 @@ class install (Command):
# party Python modules on various platforms given a wide
# array of user input is decided. Yes, it's quite complex!)
- def finalize_options (self):
-
+ def finalize_options(self):
+ """Finalizes options."""
# This method (and its pliant slaves, like 'finalize_unix()',
# 'finalize_other()', and 'select_scheme()') is where the default
# installation directories for modules, extension modules, and
@@ -255,13 +268,13 @@ class install (Command):
if ((self.prefix or self.exec_prefix or self.home) and
(self.install_base or self.install_platbase)):
- raise DistutilsOptionError, \
- ("must supply either prefix/exec-prefix/home or " +
+ raise DistutilsOptionError(
+ "must supply either prefix/exec-prefix/home or " +
"install-base/install-platbase -- not both")
if self.home and (self.prefix or self.exec_prefix):
- raise DistutilsOptionError, \
- "must supply either home or prefix/exec-prefix -- not both"
+ raise DistutilsOptionError(
+ "must supply either home or prefix/exec-prefix -- not both")
if self.user and (self.prefix or self.exec_prefix or self.home or
self.install_base or self.install_platbase):
@@ -296,8 +309,13 @@ class install (Command):
# $platbase in the other installation directories and not worry
# about needing recursive variable expansion (shudder).
- py_version = (string.split(sys.version))[0]
+ py_version = sys.version.split()[0]
(prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
+ try:
+ abiflags = sys.abiflags
+ except AttributeError:
+ # sys.abiflags may not be defined on all platforms.
+ abiflags = ''
self.config_vars = {'dist_name': self.distribution.get_name(),
'dist_version': self.distribution.get_version(),
'dist_fullname': self.distribution.get_fullname(),
@@ -308,9 +326,13 @@ class install (Command):
'prefix': prefix,
'sys_exec_prefix': exec_prefix,
'exec_prefix': exec_prefix,
- 'userbase': self.install_userbase,
- 'usersite': self.install_usersite,
+ 'abiflags': abiflags,
}
+
+ if HAS_USER_SITE:
+ self.config_vars['userbase'] = self.install_userbase
+ self.config_vars['usersite'] = self.install_usersite
+
self.expand_basedirs()
self.dump_dirs("post-expand_basedirs()")
@@ -322,7 +344,7 @@ class install (Command):
if DEBUG:
from pprint import pprint
- print "config vars:"
+ print("config vars:")
pprint(self.config_vars)
# Expand "~" and configuration variables in the installation
@@ -376,29 +398,27 @@ class install (Command):
# Punt on doc directories for now -- after all, we're punting on
# documentation completely!
- # finalize_options ()
-
-
- def dump_dirs (self, msg):
- if DEBUG:
- from distutils.fancy_getopt import longopt_xlate
- print msg + ":"
- for opt in self.user_options:
- opt_name = opt[0]
- if opt_name[-1] == "=":
- opt_name = opt_name[0:-1]
- if opt_name in self.negative_opt:
- opt_name = string.translate(self.negative_opt[opt_name],
- longopt_xlate)
- val = not getattr(self, opt_name)
- else:
- opt_name = string.translate(opt_name, longopt_xlate)
- val = getattr(self, opt_name)
- print " %s: %s" % (opt_name, val)
-
-
- def finalize_unix (self):
+ def dump_dirs(self, msg):
+ """Dumps the list of user options."""
+ if not DEBUG:
+ return
+ from distutils.fancy_getopt import longopt_xlate
+ log.debug(msg + ":")
+ for opt in self.user_options:
+ opt_name = opt[0]
+ if opt_name[-1] == "=":
+ opt_name = opt_name[0:-1]
+ if opt_name in self.negative_opt:
+ opt_name = self.negative_opt[opt_name]
+ opt_name = opt_name.translate(longopt_xlate)
+ val = not getattr(self, opt_name)
+ else:
+ opt_name = opt_name.translate(longopt_xlate)
+ val = getattr(self, opt_name)
+ log.debug(" %s: %s" % (opt_name, val))
+ def finalize_unix(self):
+ """Finalizes options for posix platforms."""
if self.install_base is not None or self.install_platbase is not None:
if ((self.install_lib is None and
self.install_purelib is None and
@@ -406,8 +426,8 @@ class install (Command):
self.install_headers is None or
self.install_scripts is None or
self.install_data is None):
- raise DistutilsOptionError, \
- ("install-base or install-platbase supplied, but "
+ raise DistutilsOptionError(
+ "install-base or install-platbase supplied, but "
"installation scheme is incomplete")
return
@@ -423,8 +443,8 @@ class install (Command):
else:
if self.prefix is None:
if self.exec_prefix is not None:
- raise DistutilsOptionError, \
- "must not supply exec-prefix without prefix"
+ raise DistutilsOptionError(
+ "must not supply exec-prefix without prefix")
self.prefix = os.path.normpath(sys.prefix)
self.exec_prefix = os.path.normpath(sys.exec_prefix)
@@ -437,11 +457,8 @@ class install (Command):
self.install_platbase = self.exec_prefix
self.select_scheme("unix_prefix")
- # finalize_unix ()
-
-
- def finalize_other (self): # Windows and Mac OS for now
-
+ def finalize_other(self):
+ """Finalizes options for non-posix platforms"""
if self.user:
if self.install_userbase is None:
raise DistutilsPlatformError(
@@ -459,13 +476,11 @@ class install (Command):
try:
self.select_scheme(os.name)
except KeyError:
- raise DistutilsPlatformError, \
- "I don't know how to install stuff on '%s'" % os.name
-
- # finalize_other ()
-
+ raise DistutilsPlatformError(
+ "I don't know how to install stuff on '%s'" % os.name)
- def select_scheme (self, name):
+ def select_scheme(self, name):
+ """Sets the install directories by applying the install schemes."""
# it's the caller's problem if they supply a bad name!
scheme = INSTALL_SCHEMES[name]
for key in SCHEME_KEYS:
@@ -473,8 +488,7 @@ class install (Command):
if getattr(self, attrname) is None:
setattr(self, attrname, scheme[key])
-
- def _expand_attrs (self, attrs):
+ def _expand_attrs(self, attrs):
for attr in attrs:
val = getattr(self, attr)
if val is not None:
@@ -483,49 +497,44 @@ class install (Command):
val = subst_vars(val, self.config_vars)
setattr(self, attr, val)
+ def expand_basedirs(self):
+ """Calls `os.path.expanduser` on install_base, install_platbase and
+ root."""
+ self._expand_attrs(['install_base', 'install_platbase', 'root'])
- def expand_basedirs (self):
- self._expand_attrs(['install_base',
- 'install_platbase',
- 'root'])
-
- def expand_dirs (self):
- self._expand_attrs(['install_purelib',
- 'install_platlib',
- 'install_lib',
- 'install_headers',
- 'install_scripts',
- 'install_data',])
+ def expand_dirs(self):
+ """Calls `os.path.expanduser` on install dirs."""
+ self._expand_attrs(['install_purelib', 'install_platlib',
+ 'install_lib', 'install_headers',
+ 'install_scripts', 'install_data',])
-
- def convert_paths (self, *names):
+ def convert_paths(self, *names):
+ """Call `convert_path` over `names`."""
for name in names:
attr = "install_" + name
setattr(self, attr, convert_path(getattr(self, attr)))
-
- def handle_extra_path (self):
-
+ def handle_extra_path(self):
+ """Set `path_file` and `extra_dirs` using `extra_path`."""
if self.extra_path is None:
self.extra_path = self.distribution.extra_path
if self.extra_path is not None:
- if type(self.extra_path) is StringType:
- self.extra_path = string.split(self.extra_path, ',')
+ if isinstance(self.extra_path, str):
+ self.extra_path = self.extra_path.split(',')
if len(self.extra_path) == 1:
path_file = extra_dirs = self.extra_path[0]
elif len(self.extra_path) == 2:
- (path_file, extra_dirs) = self.extra_path
+ path_file, extra_dirs = self.extra_path
else:
- raise DistutilsOptionError, \
- ("'extra_path' option must be a list, tuple, or "
+ raise DistutilsOptionError(
+ "'extra_path' option must be a list, tuple, or "
"comma-separated string with 1 or 2 elements")
# convert to local form in case Unix notation used (as it
# should be in setup scripts)
extra_dirs = convert_path(extra_dirs)
-
else:
path_file = None
extra_dirs = ''
@@ -535,29 +544,26 @@ class install (Command):
self.path_file = path_file
self.extra_dirs = extra_dirs
- # handle_extra_path ()
-
-
- def change_roots (self, *names):
+ def change_roots(self, *names):
+ """Change the install direcories pointed by name using root."""
for name in names:
attr = "install_" + name
setattr(self, attr, change_root(self.root, getattr(self, attr)))
def create_home_path(self):
- """Create directories under ~
- """
+ """Create directories under ~."""
if not self.user:
return
home = convert_path(os.path.expanduser("~"))
- for name, path in self.config_vars.iteritems():
+ for name, path in self.config_vars.items():
if path.startswith(home) and not os.path.isdir(path):
- self.debug_print("os.makedirs('%s', 0700)" % path)
- os.makedirs(path, 0700)
+ self.debug_print("os.makedirs('%s', 0o700)" % path)
+ os.makedirs(path, 0o700)
# -- Command execution methods -------------------------------------
- def run (self):
-
+ def run(self):
+ """Runs the command."""
# Obviously have to build before we can install
if not self.skip_build:
self.run_command('build')
@@ -582,7 +588,7 @@ class install (Command):
outputs = self.get_outputs()
if self.root: # strip any package prefix
root_len = len(self.root)
- for counter in xrange(len(outputs)):
+ for counter in range(len(outputs)):
outputs[counter] = outputs[counter][root_len:]
self.execute(write_file,
(self.record, outputs),
@@ -600,9 +606,8 @@ class install (Command):
"you'll have to change the search path yourself"),
self.install_lib)
- # run ()
-
- def create_path_file (self):
+ def create_path_file(self):
+ """Creates the .pth file"""
filename = os.path.join(self.install_libbase,
self.path_file + ".pth")
if self.install_path_file:
@@ -615,8 +620,8 @@ class install (Command):
# -- Reporting methods ---------------------------------------------
- def get_outputs (self):
- # Assemble the outputs of all the sub-commands.
+ def get_outputs(self):
+ """Assembles the outputs of all the sub-commands."""
outputs = []
for cmd_name in self.get_sub_commands():
cmd = self.get_finalized_command(cmd_name)
@@ -632,7 +637,8 @@ class install (Command):
return outputs
- def get_inputs (self):
+ def get_inputs(self):
+ """Returns the inputs of all the sub-commands"""
# XXX gee, this looks familiar ;-(
inputs = []
for cmd_name in self.get_sub_commands():
@@ -641,25 +647,29 @@ class install (Command):
return inputs
-
# -- Predicates for sub-command list -------------------------------
- def has_lib (self):
- """Return true if the current distribution has any Python
+ def has_lib(self):
+ """Returns true if the current distribution has any Python
modules to install."""
return (self.distribution.has_pure_modules() or
self.distribution.has_ext_modules())
- def has_headers (self):
+ def has_headers(self):
+ """Returns true if the current distribution has any headers to
+ install."""
return self.distribution.has_headers()
- def has_scripts (self):
+ def has_scripts(self):
+ """Returns true if the current distribution has any scripts to.
+ install."""
return self.distribution.has_scripts()
- def has_data (self):
+ def has_data(self):
+ """Returns true if the current distribution has any data to.
+ install."""
return self.distribution.has_data_files()
-
# 'sub_commands': a list of commands this command might have to run to
# get its work done. See cmd.py for more info.
sub_commands = [('install_lib', has_lib),
@@ -668,5 +678,3 @@ class install (Command):
('install_data', has_data),
('install_egg_info', lambda self:True),
]
-
-# class install
diff --git a/Lib/distutils/command/install_data.py b/Lib/distutils/command/install_data.py
index ab40797b986..947cd76a99e 100644
--- a/Lib/distutils/command/install_data.py
+++ b/Lib/distutils/command/install_data.py
@@ -5,8 +5,6 @@ platform-independent data files."""
# contributed by Bastian Kleineidam
-__revision__ = "$Id$"
-
import os
from distutils.core import Command
from distutils.util import change_root, convert_path
diff --git a/Lib/distutils/command/install_egg_info.py b/Lib/distutils/command/install_egg_info.py
index c8880310dfc..c2a7d649c0c 100644
--- a/Lib/distutils/command/install_egg_info.py
+++ b/Lib/distutils/command/install_egg_info.py
@@ -40,9 +40,8 @@ class install_egg_info(Command):
"Creating "+self.install_dir)
log.info("Writing %s", target)
if not self.dry_run:
- f = open(target, 'w')
- self.distribution.metadata.write_pkg_file(f)
- f.close()
+ with open(target, 'w', encoding='UTF-8') as f:
+ self.distribution.metadata.write_pkg_file(f)
def get_outputs(self):
return self.outputs
diff --git a/Lib/distutils/command/install_headers.py b/Lib/distutils/command/install_headers.py
index d892416a8cc..9bb0b18dc0d 100644
--- a/Lib/distutils/command/install_headers.py
+++ b/Lib/distutils/command/install_headers.py
@@ -3,8 +3,6 @@
Implements the Distutils 'install_headers' command, to install C/C++ header
files to the Python include directory."""
-__revision__ = "$Id$"
-
from distutils.core import Command
@@ -47,5 +45,3 @@ class install_headers(Command):
def get_outputs(self):
return self.outfiles
-
-# class install_headers
diff --git a/Lib/distutils/command/install_lib.py b/Lib/distutils/command/install_lib.py
index 043e8b6e271..15c08f12492 100644
--- a/Lib/distutils/command/install_lib.py
+++ b/Lib/distutils/command/install_lib.py
@@ -3,9 +3,8 @@
Implements the Distutils 'install_lib' command
(install all Python modules)."""
-__revision__ = "$Id$"
-
import os
+import imp
import sys
from distutils.core import Command
@@ -13,10 +12,7 @@ from distutils.errors import DistutilsOptionError
# Extension for Python source files.
-if hasattr(os, 'extsep'):
- PYTHON_SOURCE_EXTENSION = os.extsep + "py"
-else:
- PYTHON_SOURCE_EXTENSION = ".py"
+PYTHON_SOURCE_EXTENSION = ".py"
class install_lib(Command):
@@ -75,9 +71,9 @@ class install_lib(Command):
)
if self.compile is None:
- self.compile = 1
+ self.compile = True
if self.optimize is None:
- self.optimize = 0
+ self.optimize = False
if not isinstance(self.optimize, int):
try:
@@ -85,7 +81,7 @@ class install_lib(Command):
if self.optimize not in (0, 1, 2):
raise AssertionError
except (ValueError, AssertionError):
- raise DistutilsOptionError, "optimize must be 0, 1, or 2"
+ raise DistutilsOptionError("optimize must be 0, 1, or 2")
def run(self):
# Make sure we have built everything we need first
@@ -169,9 +165,11 @@ class install_lib(Command):
if ext != PYTHON_SOURCE_EXTENSION:
continue
if self.compile:
- bytecode_files.append(py_file + "c")
+ bytecode_files.append(imp.cache_from_source(
+ py_file, debug_override=True))
if self.optimize > 0:
- bytecode_files.append(py_file + "o")
+ bytecode_files.append(imp.cache_from_source(
+ py_file, debug_override=False))
return bytecode_files
diff --git a/Lib/distutils/command/install_scripts.py b/Lib/distutils/command/install_scripts.py
index 29cd9e7a0e3..31a1130ee54 100644
--- a/Lib/distutils/command/install_scripts.py
+++ b/Lib/distutils/command/install_scripts.py
@@ -5,14 +5,13 @@ Python scripts."""
# contributed by Bastian Kleineidam
-__revision__ = "$Id$"
-
import os
from distutils.core import Command
from distutils import log
from stat import ST_MODE
-class install_scripts (Command):
+
+class install_scripts(Command):
description = "install scripts (Python or otherwise)"
@@ -25,14 +24,13 @@ class install_scripts (Command):
boolean_options = ['force', 'skip-build']
-
- def initialize_options (self):
+ def initialize_options(self):
self.install_dir = None
self.force = 0
self.build_dir = None
self.skip_build = None
- def finalize_options (self):
+ def finalize_options(self):
self.set_undefined_options('build', ('build_scripts', 'build_dir'))
self.set_undefined_options('install',
('install_scripts', 'install_dir'),
@@ -40,7 +38,7 @@ class install_scripts (Command):
('skip_build', 'skip_build'),
)
- def run (self):
+ def run(self):
if not self.skip_build:
self.run_command('build_scripts')
self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
@@ -51,14 +49,12 @@ class install_scripts (Command):
if self.dry_run:
log.info("changing mode of %s", file)
else:
- mode = ((os.stat(file)[ST_MODE]) | 0555) & 07777
+ mode = ((os.stat(file)[ST_MODE]) | 0o555) & 0o7777
log.info("changing mode of %s to %o", file, mode)
os.chmod(file, mode)
- def get_inputs (self):
+ def get_inputs(self):
return self.distribution.scripts or []
def get_outputs(self):
return self.outfiles or []
-
-# class install_scripts
diff --git a/Lib/distutils/command/register.py b/Lib/distutils/command/register.py
index edb42b955d6..99545affa4a 100644
--- a/Lib/distutils/command/register.py
+++ b/Lib/distutils/command/register.py
@@ -5,14 +5,13 @@ Implements the Distutils 'register' command (register with the repository).
# created 2002/10/21, Richard Jones
-__revision__ = "$Id$"
-
-import urllib2
-import getpass
-import urlparse
+import os, string, getpass
+import io
+import urllib.parse, urllib.request
from warnings import warn
from distutils.core import PyPIRCCommand
+from distutils.errors import *
from distutils import log
class register(PyPIRCCommand):
@@ -86,7 +85,8 @@ class register(PyPIRCCommand):
def classifiers(self):
''' Fetch the list of classifiers from the server.
'''
- response = urllib2.urlopen(self.repository+'?:action=list_classifiers')
+ url = self.repository+'?:action=list_classifiers'
+ response = urllib.request.urlopen(url)
log.info(response.read())
def verify_metadata(self):
@@ -96,7 +96,6 @@ class register(PyPIRCCommand):
(code, result) = self.post_to_server(self.build_post_data('verify'))
log.info('Server response (%s): %s' % (code, result))
-
def send_metadata(self):
''' Send the metadata to the package index server.
@@ -145,23 +144,22 @@ We need to know who you are, so please choose either:
3. have the server generate a new password for you (and email it to you), or
4. quit
Your selection [default 1]: ''', log.INFO)
-
- choice = raw_input()
+ choice = input()
if not choice:
choice = '1'
elif choice not in choices:
- print 'Please choose one of the four options!'
+ print('Please choose one of the four options!')
if choice == '1':
# get the username and password
while not username:
- username = raw_input('Username: ')
+ username = input('Username: ')
while not password:
password = getpass.getpass('Password: ')
# set up the authentication
- auth = urllib2.HTTPPasswordMgr()
- host = urlparse.urlparse(self.repository)[1]
+ auth = urllib.request.HTTPPasswordMgr()
+ host = urllib.parse.urlparse(self.repository)[1]
auth.add_password(self.realm, host, username, password)
# send the info to the server and report the result
code, result = self.post_to_server(self.build_post_data('submit'),
@@ -182,7 +180,7 @@ Your selection [default 1]: ''', log.INFO)
self._get_rc_file(), log.INFO)
choice = 'X'
while choice.lower() not in 'yn':
- choice = raw_input('Save your login (y/N)?')
+ choice = input('Save your login (y/N)?')
if not choice:
choice = 'n'
if choice.lower() == 'y':
@@ -193,7 +191,7 @@ Your selection [default 1]: ''', log.INFO)
data['name'] = data['password'] = data['email'] = ''
data['confirm'] = None
while not data['name']:
- data['name'] = raw_input('Username: ')
+ data['name'] = input('Username: ')
while data['password'] != data['confirm']:
while not data['password']:
data['password'] = getpass.getpass('Password: ')
@@ -202,9 +200,9 @@ Your selection [default 1]: ''', log.INFO)
if data['password'] != data['confirm']:
data['password'] = ''
data['confirm'] = None
- print "Password and confirm don't match!"
+ print("Password and confirm don't match!")
while not data['email']:
- data['email'] = raw_input(' EMail: ')
+ data['email'] = input(' EMail: ')
code, result = self.post_to_server(data)
if code != 200:
log.info('Server response (%s): %s' % (code, result))
@@ -216,7 +214,7 @@ Your selection [default 1]: ''', log.INFO)
data = {':action': 'password_reset'}
data['email'] = ''
while not data['email']:
- data['email'] = raw_input('Your email address: ')
+ data['email'] = input('Your email address: ')
code, result = self.post_to_server(data)
log.info('Server response (%s): %s' % (code, result))
@@ -253,56 +251,48 @@ Your selection [default 1]: ''', log.INFO)
'''
if 'name' in data:
self.announce('Registering %s to %s' % (data['name'],
- self.repository),
- log.INFO)
+ self.repository),
+ log.INFO)
# Build up the MIME payload for the urllib2 POST data
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = '\n--' + boundary
end_boundary = sep_boundary + '--'
- chunks = []
+ body = io.StringIO()
for key, value in data.items():
# handle multiple entries for the same name
if type(value) not in (type([]), type( () )):
value = [value]
for value in value:
- chunks.append(sep_boundary)
- chunks.append('\nContent-Disposition: form-data; name="%s"'%key)
- chunks.append("\n\n")
- chunks.append(value)
+ value = str(value)
+ body.write(sep_boundary)
+ body.write('\nContent-Disposition: form-data; name="%s"'%key)
+ body.write("\n\n")
+ body.write(value)
if value and value[-1] == '\r':
- chunks.append('\n') # write an extra newline (lurve Macs)
- chunks.append(end_boundary)
- chunks.append("\n")
-
- # chunks may be bytes (str) or unicode objects that we need to encode
- body = []
- for chunk in chunks:
- if isinstance(chunk, unicode):
- body.append(chunk.encode('utf-8'))
- else:
- body.append(chunk)
-
- body = ''.join(body)
+ body.write('\n') # write an extra newline (lurve Macs)
+ body.write(end_boundary)
+ body.write("\n")
+ body = body.getvalue().encode("utf-8")
# build the Request
headers = {
'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary,
'Content-length': str(len(body))
}
- req = urllib2.Request(self.repository, body, headers)
+ req = urllib.request.Request(self.repository, body, headers)
# handle HTTP and include the Basic Auth handler
- opener = urllib2.build_opener(
- urllib2.HTTPBasicAuthHandler(password_mgr=auth)
+ opener = urllib.request.build_opener(
+ urllib.request.HTTPBasicAuthHandler(password_mgr=auth)
)
data = ''
try:
result = opener.open(req)
- except urllib2.HTTPError, e:
+ except urllib.error.HTTPError as e:
if self.show_response:
data = e.fp.read()
result = e.code, e.msg
- except urllib2.URLError, e:
+ except urllib.error.URLError as e:
result = 500, str(e)
else:
if self.show_response:
@@ -311,5 +301,4 @@ Your selection [default 1]: ''', log.INFO)
if self.show_response:
dashes = '-' * 75
self.announce('%s%s%s' % (dashes, data, dashes))
-
return result
diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py
index d30de10673c..a9429a4296a 100644
--- a/Lib/distutils/command/sdist.py
+++ b/Lib/distutils/command/sdist.py
@@ -2,19 +2,17 @@
Implements the Distutils 'sdist' command (create a source distribution)."""
-__revision__ = "$Id$"
-
import os
import string
import sys
+from types import *
from glob import glob
from warnings import warn
from distutils.core import Command
from distutils import dir_util, dep_util, file_util, archive_util
from distutils.text_file import TextFile
-from distutils.errors import (DistutilsPlatformError, DistutilsOptionError,
- DistutilsTemplateError)
+from distutils.errors import *
from distutils.filelist import FileList
from distutils import log
from distutils.util import convert_path
@@ -76,10 +74,6 @@ class sdist(Command):
('metadata-check', None,
"Ensure that all required elements of meta-data "
"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',
@@ -119,8 +113,6 @@ class sdist(Command):
self.archive_files = None
self.metadata_check = 1
- self.owner = None
- self.group = None
def finalize_options(self):
if self.manifest is None:
@@ -133,14 +125,14 @@ class sdist(Command):
try:
self.formats = [self.default_format[os.name]]
except KeyError:
- raise DistutilsPlatformError, \
- "don't know how to create source distributions " + \
- "on platform %s" % os.name
+ raise DistutilsPlatformError(
+ "don't know how to create source distributions "
+ "on platform %s" % os.name)
bad_format = archive_util.check_archive_formats(self.formats)
if bad_format:
- raise DistutilsOptionError, \
- "unknown archive format '%s'" % bad_format
+ raise DistutilsOptionError(
+ "unknown archive format '%s'" % bad_format)
if self.dist_dir is None:
self.dist_dir = "dist"
@@ -229,21 +221,20 @@ class sdist(Command):
Warns if (README or README.txt) or setup.py are missing; everything
else is optional.
"""
-
standards = [('README', 'README.txt'), self.distribution.script_name]
for fn in standards:
if isinstance(fn, tuple):
alts = fn
- got_it = 0
+ got_it = False
for fn in alts:
if os.path.exists(fn):
- got_it = 1
+ got_it = True
self.filelist.append(fn)
break
if not got_it:
self.warn("standard file not found: should have one of " +
- string.join(alts, ', '))
+ ', '.join(alts))
else:
if os.path.exists(fn):
self.filelist.append(fn)
@@ -253,8 +244,7 @@ class sdist(Command):
optional = ['test/test*.py', 'setup.cfg']
for pattern in optional:
files = filter(os.path.isfile, glob(pattern))
- if files:
- self.filelist.extend(files)
+ self.filelist.extend(files)
# build_py is used to get:
# - python modules
@@ -304,16 +294,12 @@ class sdist(Command):
'self.filelist', which updates itself accordingly.
"""
log.info("reading manifest template '%s'", self.template)
- template = TextFile(self.template,
- strip_comments=1,
- skip_blanks=1,
- join_lines=1,
- lstrip_ws=1,
- rstrip_ws=1,
+ template = TextFile(self.template, strip_comments=1, skip_blanks=1,
+ join_lines=1, lstrip_ws=1, rstrip_ws=1,
collapse_join=1)
try:
- while 1:
+ while True:
line = template.readline()
if line is None: # end of file
break
@@ -344,8 +330,6 @@ class sdist(Command):
self.filelist.exclude_pattern(None, prefix=build.build_base)
self.filelist.exclude_pattern(None, prefix=base_dir)
- # pruning out vcs directories
- # both separators are used under win32
if sys.platform == 'win32':
seps = r'/|\\'
else:
@@ -372,11 +356,11 @@ class sdist(Command):
"writing manifest file '%s'" % self.manifest)
def _manifest_is_not_generated(self):
- # check for special comment used in 2.7.1 and higher
+ # check for special comment used in 3.1.3 and higher
if not os.path.isfile(self.manifest):
return False
- fp = open(self.manifest, 'rU')
+ fp = open(self.manifest)
try:
first_line = fp.readline()
finally:
@@ -460,8 +444,7 @@ class sdist(Command):
self.formats.append(self.formats.pop(self.formats.index('tar')))
for fmt in self.formats:
- file = self.make_archive(base_name, fmt, base_dir=base_dir,
- owner=self.owner, group=self.group)
+ file = self.make_archive(base_name, fmt, base_dir=base_dir)
archive_files.append(file)
self.distribution.dist_files.append(('sdist', '', file))
diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py
index d0133353a63..8b36851d256 100644
--- a/Lib/distutils/command/upload.py
+++ b/Lib/distutils/command/upload.py
@@ -1,19 +1,25 @@
"""distutils.command.upload
Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
-import os
-import socket
-import platform
-from urllib2 import urlopen, Request, HTTPError
-from base64 import standard_b64encode
-import urlparse
-import cStringIO as StringIO
-from hashlib import md5
-from distutils.errors import DistutilsOptionError
+from distutils.errors import *
from distutils.core import PyPIRCCommand
from distutils.spawn import spawn
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):
@@ -60,15 +66,6 @@ class upload(PyPIRCCommand):
self.upload_file(command, pyversion, filename)
def upload_file(self, command, pyversion, filename):
- # Makes sure the repository URL is compliant
- schema, netloc, url, params, query, fragments = \
- urlparse.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
if self.sign:
gpg_args = ["gpg", "--detach-sign", "-a", filename]
@@ -128,67 +125,78 @@ class upload(PyPIRCCommand):
if self.sign:
data['gpg_signature'] = (os.path.basename(filename) + ".asc",
- open(filename+".asc").read())
+ open(filename+".asc", "rb").read())
# set up the authentication
- auth = "Basic " + standard_b64encode(self.username + ":" +
- self.password)
+ user_pass = (self.username + ":" + self.password).encode('ascii')
+ # The exact encoding of the authentication string is debated.
+ # Anyway PyPI only accepts ascii for both username or password.
+ auth = "Basic " + standard_b64encode(user_pass).decode('ascii')
# Build up the MIME payload for the POST data
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
- sep_boundary = '\n--' + boundary
- end_boundary = sep_boundary + '--'
- body = StringIO.StringIO()
+ sep_boundary = b'\n--' + boundary.encode('ascii')
+ end_boundary = sep_boundary + b'--'
+ body = io.BytesIO()
for key, value in data.items():
+ title = '\nContent-Disposition: form-data; name="%s"' % key
# handle multiple entries for the same name
- if not isinstance(value, list):
+ if type(value) != type([]):
value = [value]
for value in value:
- if isinstance(value, tuple):
- fn = ';filename="%s"' % value[0]
+ if type(value) is tuple:
+ title += '; filename="%s"' % value[0]
value = value[1]
else:
- fn = ""
-
+ value = str(value).encode('utf-8')
body.write(sep_boundary)
- body.write('\nContent-Disposition: form-data; name="%s"'%key)
- body.write(fn)
- body.write("\n\n")
+ body.write(title.encode('utf-8'))
+ body.write(b"\n\n")
body.write(value)
- if value and value[-1] == '\r':
- body.write('\n') # write an extra newline (lurve Macs)
+ if value and value[-1:] == b'\r':
+ body.write(b'\n') # write an extra newline (lurve Macs)
body.write(end_boundary)
- body.write("\n")
+ body.write(b"\n")
body = body.getvalue()
self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
# build the Request
- headers = {'Content-type':
- 'multipart/form-data; boundary=%s' % boundary,
- 'Content-length': str(len(body)),
- 'Authorization': auth}
-
- request = Request(self.repository, data=body,
- headers=headers)
- # send the data
+ # We can't use urllib since we need to send the Basic
+ # auth right with the first request
+ # TODO(jhylton): Can we fix urllib?
+ schema, netloc, url, params, query, fragments = \
+ urllib.parse.urlparse(self.repository)
+ assert not params and not query and not fragments
+ if schema == 'http':
+ http = httpclient.HTTPConnection(netloc)
+ elif schema == 'https':
+ http = httpclient.HTTPSConnection(netloc)
+ else:
+ raise AssertionError("unsupported schema "+schema)
+
+ data = ''
+ loglevel = log.INFO
try:
- result = urlopen(request)
- status = result.getcode()
- reason = result.msg
- if self.show_response:
- msg = '\n'.join(('-' * 75, r.read(), '-' * 75))
- self.announce(msg, log.INFO)
- except socket.error, e:
+ http.connect()
+ http.putrequest("POST", url)
+ 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:
self.announce(str(e), log.ERROR)
return
- except HTTPError, e:
- status = e.code
- reason = e.msg
- if status == 200:
- self.announce('Server response (%s): %s' % (status, reason),
+ r = http.getresponse()
+ if r.status == 200:
+ self.announce('Server response (%s): %s' % (r.status, r.reason),
log.INFO)
else:
- self.announce('Upload failed (%s): %s' % (status, reason),
+ self.announce('Upload failed (%s): %s' % (r.status, r.reason),
log.ERROR)
+ if self.show_response:
+ msg = '\n'.join(('-' * 75, r.read(), '-' * 75))
+ self.announce(msg, log.INFO)
diff --git a/Lib/distutils/command/wininst-9.0-amd64.exe b/Lib/distutils/command/wininst-9.0-amd64.exe
index 11d8011c717..94fbd4341b2 100644
--- a/Lib/distutils/command/wininst-9.0-amd64.exe
+++ b/Lib/distutils/command/wininst-9.0-amd64.exe
Binary files differ
diff --git a/Lib/distutils/command/wininst-9.0.exe b/Lib/distutils/command/wininst-9.0.exe
index dadb31d8938..2ec261f9fdc 100644
--- a/Lib/distutils/command/wininst-9.0.exe
+++ b/Lib/distutils/command/wininst-9.0.exe
Binary files differ
diff --git a/Lib/distutils/config.py b/Lib/distutils/config.py
index 1d327143bea..1fd53346e96 100644
--- a/Lib/distutils/config.py
+++ b/Lib/distutils/config.py
@@ -4,7 +4,7 @@ Provides the PyPIRCCommand class, the base class for the command classes
that uses .pypirc in the distutils.command package.
"""
import os
-from ConfigParser import ConfigParser
+from configparser import ConfigParser
from distutils.cmd import Command
@@ -42,11 +42,8 @@ class PyPIRCCommand(Command):
def _store_pypirc(self, username, password):
"""Creates a default .pypirc file."""
rc = self._get_rc_file()
- f = os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0600), 'w')
- try:
+ with os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f:
f.write(DEFAULT_PYPIRC % (username, password))
- finally:
- f.close()
def _read_pypirc(self):
"""Reads the .pypirc file."""
@@ -54,6 +51,8 @@ class PyPIRCCommand(Command):
if os.path.exists(rc):
self.announce('Using PyPI login from %s' % rc)
repository = self.repository or self.DEFAULT_REPOSITORY
+ realm = self.realm or self.DEFAULT_REALM
+
config = ConfigParser()
config.read(rc)
sections = config.sections()
diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py
index b89557d7679..260332a2ac6 100644
--- a/Lib/distutils/core.py
+++ b/Lib/distutils/core.py
@@ -6,14 +6,11 @@ indirectly provides the Distribution and Command classes, although they are
really defined in distutils.dist and distutils.cmd.
"""
-__revision__ = "$Id$"
-
-import sys
import os
+import sys
from distutils.debug import DEBUG
-from distutils.errors import (DistutilsSetupError, DistutilsArgError,
- DistutilsError, CCompilerError)
+from distutils.errors import *
from distutils.util import grok_environment_error
# Mainly import these so setup scripts can "from distutils.core import" them.
@@ -33,9 +30,9 @@ usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: %(script)s cmd --help
"""
-def gen_usage(script_name):
+def gen_usage (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()'.
@@ -58,7 +55,7 @@ extension_keywords = ('name', 'sources', 'include_dirs',
'extra_objects', 'extra_compile_args', 'extra_link_args',
'swig_opts', 'export_symbols', 'depends', 'language')
-def setup(**attrs):
+def setup (**attrs):
"""The gateway to the Distutils: do everything your setup script needs
to do, in a highly flexible and user-driven way. Briefly: create a
Distribution instance; find and parse config files; parse the command
@@ -103,19 +100,19 @@ def setup(**attrs):
if 'script_name' not in attrs:
attrs['script_name'] = os.path.basename(sys.argv[0])
- if 'script_args' not in attrs:
+ if 'script_args' not in attrs:
attrs['script_args'] = sys.argv[1:]
# Create the Distribution instance, using the remaining arguments
# (ie. everything except distclass) to initialize it
try:
_setup_distribution = dist = klass(attrs)
- except DistutilsSetupError, msg:
- if 'name' in attrs:
- raise SystemExit, "error in %s setup command: %s" % \
- (attrs['name'], msg)
+ except DistutilsSetupError as msg:
+ if 'name' not in attrs:
+ raise SystemExit("error in setup command: %s" % msg)
else:
- raise SystemExit, "error in setup command: %s" % msg
+ raise SystemExit("error in %s setup command: %s" % \
+ (attrs['name'], msg))
if _setup_stop_after == "init":
return dist
@@ -125,22 +122,21 @@ def setup(**attrs):
dist.parse_config_files()
if DEBUG:
- print "options (after parsing config files):"
+ print("options (after parsing config files):")
dist.dump_option_dicts()
if _setup_stop_after == "config":
return dist
- # Parse the command line and override config files; any
- # command-line errors are the end user's fault, so turn them into
- # SystemExit to suppress tracebacks.
+ # Parse the command line; any command-line errors are the end user's
+ # fault, so turn them into SystemExit to suppress tracebacks.
try:
ok = dist.parse_command_line()
- except DistutilsArgError, msg:
- raise SystemExit, gen_usage(dist.script_name) + "\nerror: %s" % msg
+ except DistutilsArgError as msg:
+ raise SystemExit(gen_usage(dist.script_name) + "\nerror: %s" % msg)
if DEBUG:
- print "options (after parsing command line):"
+ print("options (after parsing command line):")
dist.dump_option_dicts()
if _setup_stop_after == "commandline":
@@ -151,34 +147,36 @@ def setup(**attrs):
try:
dist.run_commands()
except KeyboardInterrupt:
- raise SystemExit, "interrupted"
- except (IOError, os.error), exc:
+ raise SystemExit("interrupted")
+ except (IOError, os.error) as exc:
error = grok_environment_error(exc)
if DEBUG:
sys.stderr.write(error + "\n")
raise
else:
- raise SystemExit, error
+ raise SystemExit(error)
except (DistutilsError,
- CCompilerError), msg:
+ CCompilerError) as msg:
if DEBUG:
raise
else:
- raise SystemExit, "error: " + str(msg)
+ raise SystemExit("error: " + str(msg))
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
return the Distribution instance that drives things. This is useful
if you need to find out the distribution meta-data (passed as
keyword args from 'script' to 'setup()', or the contents of the
config files or command-line.
- 'script_name' is a file that will be run with 'execfile()';
+ 'script_name' is a file that will be read and run with 'exec()';
'sys.argv[0]' will be replaced with 'script' for the duration of the
call. 'script_args' is a list of strings; if supplied,
'sys.argv[1:]' will be replaced by 'script_args' for the duration of
@@ -203,7 +201,7 @@ def run_setup(script_name, script_args=None, stop_after="run"):
used to drive the Distutils.
"""
if stop_after not in ('init', 'config', 'commandline', 'run'):
- raise ValueError, "invalid value for 'stop_after': %r" % (stop_after,)
+ raise ValueError("invalid value for 'stop_after': %r" % (stop_after,))
global _setup_stop_after, _setup_distribution
_setup_stop_after = stop_after
@@ -216,11 +214,8 @@ def run_setup(script_name, script_args=None, stop_after="run"):
sys.argv[0] = script_name
if script_args is not None:
sys.argv[1:] = script_args
- f = open(script_name)
- try:
- exec f.read() in g, l
- finally:
- f.close()
+ with open(script_name, 'rb') as f:
+ exec(f.read(), g, l)
finally:
sys.argv = save_argv
_setup_stop_after = None
@@ -232,11 +227,13 @@ def run_setup(script_name, script_args=None, stop_after="run"):
raise
if _setup_distribution is None:
- raise RuntimeError, \
- ("'distutils.core.setup()' was never called -- "
+ raise RuntimeError(("'distutils.core.setup()' was never called -- "
"perhaps '%s' is not a Distutils setup script?") % \
- script_name
+ script_name)
# I wonder if the setup script's namespace -- g and l -- would be of
# any interest to callers?
+ #print "_setup_distribution:", _setup_distribution
return _setup_distribution
+
+# run_setup ()
diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py
index a1ee815c6cc..819e1a97be3 100644
--- a/Lib/distutils/cygwinccompiler.py
+++ b/Lib/distutils/cygwinccompiler.py
@@ -45,16 +45,19 @@ cygwin in no-cygwin mode).
# * mingw gcc 3.2/ld 2.13 works
# (ld supports -shared)
-# This module should be kept compatible with Python 2.1.
+import os
+import sys
+import copy
+from subprocess import Popen, PIPE
+import re
-__revision__ = "$Id$"
-
-import os,sys,copy
from distutils.ccompiler import gen_preprocess_options, gen_lib_options
from distutils.unixccompiler import UnixCCompiler
from distutils.file_util import write_file
from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
from distutils import log
+from distutils.version import LooseVersion
+from distutils.spawn import find_executable
def get_msvcr():
"""Include the appropriate MSVC runtime library if Python was built
@@ -79,8 +82,9 @@ def get_msvcr():
raise ValueError("Unknown MS Compiler version %s " % msc_ver)
-class CygwinCCompiler (UnixCCompiler):
-
+class CygwinCCompiler(UnixCCompiler):
+ """ Handles the Cygwin port of the GNU C compiler to Windows.
+ """
compiler_type = 'cygwin'
obj_extension = ".o"
static_lib_extension = ".a"
@@ -89,11 +93,11 @@ class CygwinCCompiler (UnixCCompiler):
shared_lib_format = "%s%s"
exe_extension = ".exe"
- def __init__ (self, verbose=0, dry_run=0, force=0):
+ def __init__(self, verbose=0, dry_run=0, force=0):
- UnixCCompiler.__init__ (self, verbose, dry_run, force)
+ UnixCCompiler.__init__(self, verbose, dry_run, force)
- (status, details) = check_config_h()
+ status, details = check_config_h()
self.debug_print("Python's GCC status: %s (details: %s)" %
(status, details))
if status is not CONFIG_H_OK:
@@ -148,38 +152,26 @@ class CygwinCCompiler (UnixCCompiler):
# with MSVC 7.0 or later.
self.dll_libraries = get_msvcr()
- # __init__ ()
-
-
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ """Compiles the source by spawning GCC and windres if needed."""
if ext == '.rc' or ext == '.res':
# gcc needs '.res' and '.rc' compiled to object files !!!
try:
self.spawn(["windres", "-i", src, "-o", obj])
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
else: # for other files use the C-compiler
try:
self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- def link (self,
- target_desc,
- objects,
- 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):
-
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+
+ def link(self, target_desc, objects, 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 the objects."""
# use separate copies, so we can modify the lists
extra_preargs = copy.copy(extra_preargs or [])
libraries = copy.copy(libraries or [])
@@ -244,64 +236,44 @@ class CygwinCCompiler (UnixCCompiler):
if not debug:
extra_preargs.append("-s")
- UnixCCompiler.link(self,
- target_desc,
- objects,
- output_filename,
- output_dir,
- libraries,
- library_dirs,
+ UnixCCompiler.link(self, target_desc, objects, output_filename,
+ output_dir, libraries, library_dirs,
runtime_library_dirs,
None, # export_symbols, we do this in our def-file
- debug,
- extra_preargs,
- extra_postargs,
- build_temp,
+ debug, extra_preargs, extra_postargs, build_temp,
target_lang)
- # link ()
-
# -- Miscellaneous methods -----------------------------------------
- # overwrite the one from CCompiler to support rc and res-files
- def object_filenames (self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
- if output_dir is None: output_dir = ''
+ def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
+ """Adds supports for rc and res files."""
+ if output_dir is None:
+ output_dir = ''
obj_names = []
for src_name in source_filenames:
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
- (base, ext) = os.path.splitext (os.path.normcase(src_name))
+ base, ext = os.path.splitext(os.path.normcase(src_name))
if ext not in (self.src_extensions + ['.rc','.res']):
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % \
- (ext, src_name)
+ raise UnknownFileError("unknown file type '%s' (from '%s')" % \
+ (ext, src_name))
if strip_dir:
base = os.path.basename (base)
- if ext == '.res' or ext == '.rc':
+ if ext in ('.res', '.rc'):
# these need to be compiled to object files
- obj_names.append (os.path.join (output_dir,
- base + ext + self.obj_extension))
+ obj_names.append (os.path.join(output_dir,
+ base + ext + self.obj_extension))
else:
- obj_names.append (os.path.join (output_dir,
- base + self.obj_extension))
+ obj_names.append (os.path.join(output_dir,
+ base + self.obj_extension))
return obj_names
- # object_filenames ()
-
-# class CygwinCCompiler
-
-
# the same as cygwin plus some additional parameters
-class Mingw32CCompiler (CygwinCCompiler):
-
+class Mingw32CCompiler(CygwinCCompiler):
+ """ Handles the Mingw32 port of the GNU C compiler to Windows.
+ """
compiler_type = 'mingw32'
- def __init__ (self,
- verbose=0,
- dry_run=0,
- force=0):
+ def __init__(self, verbose=0, dry_run=0, force=0):
CygwinCCompiler.__init__ (self, verbose, dry_run, force)
@@ -337,10 +309,6 @@ class Mingw32CCompiler (CygwinCCompiler):
# with MSVC 7.0 or later.
self.dll_libraries = get_msvcr()
- # __init__ ()
-
-# class Mingw32CCompiler
-
# Because these compilers aren't configured in Python's pyconfig.h file by
# default, we should at least warn the user if he is using a unmodified
# version.
@@ -350,16 +318,16 @@ CONFIG_H_NOTOK = "not ok"
CONFIG_H_UNCERTAIN = "uncertain"
def check_config_h():
+ """Check if the current Python installation appears amenable to building
+ extensions with GCC.
+
+ Returns a tuple (status, details), where 'status' is one of the following
+ constants:
+
+ - CONFIG_H_OK: all is well, go ahead and compile
+ - CONFIG_H_NOTOK: doesn't look good
+ - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
- """Check if the current Python installation (specifically, pyconfig.h)
- appears amenable to building extensions with GCC. Returns a tuple
- (status, details), where 'status' is one of the following constants:
- CONFIG_H_OK
- all is well, go ahead and compile
- CONFIG_H_NOTOK
- doesn't look good
- CONFIG_H_UNCERTAIN
- not sure -- unable to read pyconfig.h
'details' is a human-readable string explaining the situation.
Note there are two ways to conclude "OK": either 'sys.version' contains
@@ -371,79 +339,54 @@ def check_config_h():
# "pyconfig.h" check -- should probably be renamed...
from distutils import sysconfig
- import string
- # if sys.version contains GCC then python was compiled with
- # GCC, and the pyconfig.h file should be OK
- if string.find(sys.version,"GCC") >= 0:
- return (CONFIG_H_OK, "sys.version mentions 'GCC'")
+ # if sys.version contains GCC then python was compiled with GCC, and the
+ # pyconfig.h file should be OK
+ if "GCC" in sys.version:
+ return CONFIG_H_OK, "sys.version mentions 'GCC'"
+
+ # let's see if __GNUC__ is mentioned in python.h
fn = sysconfig.get_config_h_filename()
try:
- # It would probably better to read single lines to search.
- # But we do this only once, and it is fast enough
- f = open(fn)
+ config_h = open(fn)
try:
- s = f.read()
+ if "__GNUC__" in config_h.read():
+ return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
+ else:
+ return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
finally:
- f.close()
-
- except IOError, exc:
- # if we can't read this file, we cannot say it is wrong
- # the compiler will complain later about this file as missing
+ config_h.close()
+ except IOError as exc:
return (CONFIG_H_UNCERTAIN,
"couldn't read '%s': %s" % (fn, exc.strerror))
- else:
- # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
- if string.find(s,"__GNUC__") >= 0:
- return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
- else:
- return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
+RE_VERSION = re.compile(b'(\d+\.\d+(\.\d+)*)')
+def _find_exe_version(cmd):
+ """Find the version of an executable by running `cmd` in the shell.
+ If the command is not found, or the output does not match
+ `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():
""" Try to find out the versions of gcc, ld and dllwrap.
- If not possible it returns None for it.
- """
- from distutils.version import LooseVersion
- from distutils.spawn import find_executable
- 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)
- if result:
- gcc_version = LooseVersion(result.group(1))
- else:
- gcc_version = None
- else:
- gcc_version = None
- ld_exe = find_executable('ld')
- if ld_exe:
- out = os.popen(ld_exe + ' -v','r')
- out_string = out.read()
- out.close()
- result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
- if result:
- ld_version = LooseVersion(result.group(1))
- else:
- ld_version = None
- else:
- ld_version = None
- dllwrap_exe = find_executable('dllwrap')
- if dllwrap_exe:
- out = os.popen(dllwrap_exe + ' --version','r')
- out_string = out.read()
- out.close()
- result = re.search(' (\d+\.\d+(\.\d+)*)',out_string)
- if result:
- dllwrap_version = LooseVersion(result.group(1))
- else:
- dllwrap_version = None
- else:
- dllwrap_version = None
- return (gcc_version, ld_version, dllwrap_version)
+ If not possible it returns None for it.
+ """
+ commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
+ return tuple([_find_exe_version(cmd) for cmd in commands])
diff --git a/Lib/distutils/debug.py b/Lib/distutils/debug.py
index 2886744402e..daf1660f0d8 100644
--- a/Lib/distutils/debug.py
+++ b/Lib/distutils/debug.py
@@ -1,7 +1,5 @@
import os
-__revision__ = "$Id$"
-
# If DISTUTILS_DEBUG is anything other than the empty string, we run in
# debug mode.
DEBUG = os.environ.get('DISTUTILS_DEBUG')
diff --git a/Lib/distutils/dep_util.py b/Lib/distutils/dep_util.py
index 2b759056ea8..d74f5e4e92f 100644
--- a/Lib/distutils/dep_util.py
+++ b/Lib/distutils/dep_util.py
@@ -4,56 +4,56 @@ Utility functions for simple, timestamp-based dependency of files
and groups of files; also, function based entirely on such
timestamp dependency analysis."""
-__revision__ = "$Id$"
-
import os
-from stat import ST_MTIME
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
- 'target', or if 'source' exists and 'target' doesn't.
-
- Return false if both exist and 'target' is the same age or younger
- than 'source'. 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".
+def newer (source, target):
+ """Return true if 'source' exists and is more recently modified than
+ 'target', or if 'source' exists and 'target' doesn't. Return false if
+ both exist and 'target' is the same age or younger than 'source'.
+ Raise DistutilsFileError if 'source' does not exist.
"""
if not os.path.exists(source):
raise DistutilsFileError("file '%s' does not exist" %
os.path.abspath(source))
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
- return os.stat(source)[ST_MTIME] > os.stat(target)[ST_MTIME]
+# newer ()
-def newer_pairwise(sources, targets):
+
+def newer_pairwise (sources, targets):
"""Walk two filename lists in parallel, testing if each source is newer
than its corresponding target. Return a pair of lists (sources,
targets) where source is newer than target, according to the semantics
of 'newer()'.
"""
if len(sources) != len(targets):
- raise ValueError, "'sources' and 'targets' must be same length"
+ raise ValueError("'sources' and 'targets' must be same length")
# build a pair of lists (sources, targets) where source is newer
n_sources = []
n_targets = []
- for source, target in zip(sources, targets):
- if newer(source, target):
- n_sources.append(source)
- n_targets.append(target)
+ for i in range(len(sources)):
+ if newer(sources[i], targets[i]):
+ n_sources.append(sources[i])
+ 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.
'missing' controls what we do when a source file is missing; the
default ("error") is to blow up with an OSError from inside 'stat()';
@@ -66,14 +66,14 @@ def newer_group(sources, target, missing='error'):
"""
# If the target doesn't even exist, then it's definitely out-of-date.
if not os.path.exists(target):
- return True
+ return 1
# 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
# 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.
+ from stat import ST_MTIME
target_mtime = os.stat(target)[ST_MTIME]
-
for source in sources:
if not os.path.exists(source):
if missing == 'error': # blow up when we stat() the file
@@ -81,9 +81,12 @@ def newer_group(sources, target, missing='error'):
elif missing == 'ignore': # missing source dropped from
continue # target's dependency list
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:
- return True
+ source_mtime = os.stat(source)[ST_MTIME]
+ if source_mtime > target_mtime:
+ return 1
+ else:
+ return 0
- return False
+# newer_group ()
diff --git a/Lib/distutils/dir_util.py b/Lib/distutils/dir_util.py
index 5026e246685..2826ff805d7 100644
--- a/Lib/distutils/dir_util.py
+++ b/Lib/distutils/dir_util.py
@@ -2,9 +2,7 @@
Utility functions for manipulating directories and directory trees."""
-__revision__ = "$Id$"
-
-import os
+import os, sys
import errno
from distutils.errors import DistutilsFileError, DistutilsInternalError
from distutils import log
@@ -16,7 +14,7 @@ _path_created = {}
# I don't use os.makedirs because a) it's new to Python 1.5.2, and
# b) it blows up if the directory already exists (I want to silently
# succeed in that case).
-def mkpath(name, mode=0777, verbose=1, dry_run=0):
+def mkpath(name, mode=0o777, verbose=1, dry_run=0):
"""Create a directory and any missing ancestor directories.
If the directory already exists (or if 'name' is the empty string, which
@@ -30,9 +28,9 @@ def mkpath(name, mode=0777, verbose=1, dry_run=0):
global _path_created
# Detect a common bug -- name is None
- if not isinstance(name, basestring):
- raise DistutilsInternalError, \
- "mkpath: 'name' must be a string (got %r)" % (name,)
+ if not isinstance(name, str):
+ raise DistutilsInternalError(
+ "mkpath: 'name' must be a string (got %r)" % (name,))
# XXX what's the better way to handle verbosity? print as we create
# each directory in the path (the current behaviour), or only announce
@@ -70,7 +68,7 @@ def mkpath(name, mode=0777, verbose=1, dry_run=0):
if not dry_run:
try:
os.mkdir(head, mode)
- except OSError, exc:
+ except OSError as exc:
if not (exc.errno == errno.EEXIST and os.path.isdir(head)):
raise DistutilsFileError(
"could not create '%s': %s" % (head, exc.args[-1]))
@@ -79,7 +77,7 @@ def mkpath(name, mode=0777, verbose=1, dry_run=0):
_path_created[abs_head] = 1
return created_dirs
-def create_tree(base_dir, files, mode=0777, verbose=1, dry_run=0):
+def create_tree(base_dir, files, mode=0o777, verbose=1, dry_run=0):
"""Create all the empty directories under 'base_dir' needed to put 'files'
there.
@@ -90,14 +88,12 @@ def create_tree(base_dir, files, mode=0777, verbose=1, dry_run=0):
'dry_run' flags are as for 'mkpath()'.
"""
# First get the list of directories to create
- need_dir = {}
+ need_dir = set()
for file in files:
- need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
- need_dirs = need_dir.keys()
- need_dirs.sort()
+ need_dir.add(os.path.join(base_dir, os.path.dirname(file)))
# Now create them
- for dir in need_dirs:
+ for dir in sorted(need_dir):
mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
def copy_tree(src, dst, preserve_mode=1, preserve_times=1,
@@ -124,16 +120,17 @@ def copy_tree(src, dst, preserve_mode=1, preserve_times=1,
from distutils.file_util import copy_file
if not dry_run and not os.path.isdir(src):
- raise DistutilsFileError, \
- "cannot copy tree '%s': not a directory" % src
+ raise DistutilsFileError(
+ "cannot copy tree '%s': not a directory" % src)
try:
names = os.listdir(src)
- except os.error, (errno, errstr):
+ except os.error as e:
+ (errno, errstr) = e
if dry_run:
names = []
else:
- raise DistutilsFileError, \
- "error listing files in '%s': %s" % (src, errstr)
+ raise DistutilsFileError(
+ "error listing files in '%s': %s" % (src, errstr))
if not dry_run:
mkpath(dst, verbose=verbose)
@@ -201,7 +198,7 @@ def remove_tree(directory, verbose=1, dry_run=0):
abspath = os.path.abspath(cmd[1])
if abspath in _path_created:
del _path_created[abspath]
- except (IOError, OSError), exc:
+ except (IOError, OSError) as exc:
log.warn(grok_environment_error(
exc, "error removing %s: " % directory))
diff --git a/Lib/distutils/dist.py b/Lib/distutils/dist.py
index e025313dbd9..a7025682781 100644
--- a/Lib/distutils/dist.py
+++ b/Lib/distutils/dist.py
@@ -4,26 +4,19 @@ Provides the Distribution class, which represents the module distribution
being built/installed/distributed.
"""
-__revision__ = "$Id$"
-
import sys, os, re
-from email import message_from_file
try:
import warnings
except ImportError:
warnings = None
-from distutils.errors import (DistutilsOptionError, DistutilsArgError,
- DistutilsModuleError, DistutilsClassError)
+from distutils.errors import *
from distutils.fancy_getopt import FancyGetopt, translate_longopt
from distutils.util import check_environ, strtobool, rfc822_escape
from distutils import log
from distutils.debug import DEBUG
-# Encoding used for the PKG-INFO files
-PKG_INFO_ENCODING = 'utf-8'
-
# Regex to define acceptable Distutils command names. This is not *quite*
# the same as a Python NAME -- I don't allow leading underscores. The fact
# that they're very similar is no coincidence; the default naming scheme is
@@ -58,9 +51,7 @@ class Distribution:
('quiet', 'q', "run quietly (turns verbosity off)"),
('dry-run', 'n', "don't actually do anything"),
('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
# usage of the setup script.
@@ -116,8 +107,7 @@ Common commands: (see '--help-commands' for more)
('obsoletes', None,
"print the list of packages/modules made obsolete")
]
- display_option_names = map(lambda x: translate_longopt(x[0]),
- display_options)
+ display_option_names = [translate_longopt(x[0]) for x in display_options]
# negative options are options that exclude other options
negative_opt = {'quiet': 'verbose'}
@@ -268,22 +258,6 @@ Common commands: (see '--help-commands' for more)
else:
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()
def get_option_dict(self, command):
@@ -301,8 +275,7 @@ Common commands: (see '--help-commands' for more)
from pprint import pformat
if commands is None: # dump all command option dicts
- commands = self.command_options.keys()
- commands.sort()
+ commands = sorted(self.command_options.keys())
if header is not None:
self.announce(indent + header)
@@ -336,10 +309,7 @@ Common commands: (see '--help-commands' for more)
Distutils installation directory (ie. where the top-level
Distutils __inst__.py file lives), a file in the user's home
directory named .pydistutils.cfg on Unix and pydistutils.cfg
- 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.
+ on Windows/Mac, and setup.cfg in the current directory.
"""
files = []
check_environ()
@@ -359,23 +329,19 @@ Common commands: (see '--help-commands' for more)
user_filename = "pydistutils.cfg"
# And look for the user config file
- if self.want_user_cfg:
- user_file = os.path.join(os.path.expanduser('~'), user_filename)
- if os.path.isfile(user_file):
- files.append(user_file)
+ user_file = os.path.join(os.path.expanduser('~'), user_filename)
+ if os.path.isfile(user_file):
+ files.append(user_file)
# All platforms support local setup.cfg
local_file = "setup.cfg"
if os.path.isfile(local_file):
files.append(local_file)
- if DEBUG:
- self.announce("using config files: %s" % ', '.join(files))
-
return files
def parse_config_files(self, filenames=None):
- from ConfigParser import ConfigParser
+ from configparser import ConfigParser
if filenames is None:
filenames = self.find_config_files()
@@ -415,8 +381,8 @@ Common commands: (see '--help-commands' for more)
setattr(self, opt, strtobool(val))
else:
setattr(self, opt, val)
- except ValueError, msg:
- raise DistutilsOptionError, msg
+ except ValueError as msg:
+ raise DistutilsOptionError(msg)
# -- Command-line parsing methods ----------------------------------
@@ -482,10 +448,10 @@ Common commands: (see '--help-commands' for more)
# Oops, no commands found -- an end-user error
if not self.commands:
- raise DistutilsArgError, "no commands supplied"
+ raise DistutilsArgError("no commands supplied")
# All is well: return true
- return 1
+ return True
def _get_toplevel_options(self):
"""Return the non-display options recognized at the top level.
@@ -513,7 +479,7 @@ Common commands: (see '--help-commands' for more)
# Pull the current command from the head of the command line
command = args[0]
if not command_re.match(command):
- raise SystemExit, "invalid command name '%s'" % command
+ raise SystemExit("invalid command name '%s'" % command)
self.commands.append(command)
# Dig up the command class that implements this command, so we
@@ -521,23 +487,22 @@ Common commands: (see '--help-commands' for more)
# it takes.
try:
cmd_class = self.get_command_class(command)
- except DistutilsModuleError, msg:
- raise DistutilsArgError, msg
+ except DistutilsModuleError as msg:
+ raise DistutilsArgError(msg)
# Require that the command class be derived from Command -- want
# to be sure that the basic "command" interface is implemented.
if not issubclass(cmd_class, Command):
- raise DistutilsClassError, \
- "command class %s must subclass Command" % cmd_class
+ raise DistutilsClassError(
+ "command class %s must subclass Command" % cmd_class)
# Also make sure that the command object provides a list of its
# known options.
if not (hasattr(cmd_class, 'user_options') and
isinstance(cmd_class.user_options, list)):
- raise DistutilsClassError, \
- ("command class %s must provide " +
+ raise DistutilsClassError(("command class %s must provide " +
"'user_options' attribute (a list of tuples)") % \
- cmd_class
+ cmd_class)
# If the command class has a list of negative alias options,
# merge it in with the global negative aliases.
@@ -572,7 +537,7 @@ Common commands: (see '--help-commands' for more)
for (help_option, short, desc, func) in cmd_class.help_options:
if hasattr(opts, parser.get_attr_name(help_option)):
help_option_found=1
- if hasattr(func, '__call__'):
+ if callable(func):
func()
else:
raise DistutilsClassError(
@@ -739,7 +704,7 @@ Common commands: (see '--help-commands' for more)
"Standard commands",
max_length)
if extra_commands:
- print
+ print()
self.print_command_list(extra_commands,
"Extra commands",
max_length)
@@ -753,7 +718,6 @@ Common commands: (see '--help-commands' for more)
"""
# Currently this is only used on Mac OS, for the Mac-only GUI
# Distutils interface (by Jack Jansen)
-
import distutils.command
std_commands = distutils.command.__all__
is_std = {}
@@ -820,16 +784,15 @@ Common commands: (see '--help-commands' for more)
try:
klass = getattr(module, klass_name)
except AttributeError:
- raise DistutilsModuleError, \
- "invalid command '%s' (no class '%s' in module '%s')" \
- % (command, klass_name, module_name)
+ raise DistutilsModuleError(
+ "invalid command '%s' (no class '%s' in module '%s')"
+ % (command, klass_name, module_name))
self.cmdclass[command] = klass
return klass
raise DistutilsModuleError("invalid command '%s'" % command)
-
def get_command_obj(self, command, create=1):
"""Return the command object for 'command'. Normally this object
is cached on a previous call to 'get_command_obj()'; if no command
@@ -877,7 +840,8 @@ Common commands: (see '--help-commands' for more)
self.announce(" %s = %s (from %s)" % (option, value,
source))
try:
- bool_opts = map(translate_longopt, command_obj.boolean_options)
+ bool_opts = [translate_longopt(o)
+ for o in command_obj.boolean_options]
except AttributeError:
bool_opts = []
try:
@@ -894,11 +858,11 @@ Common commands: (see '--help-commands' for more)
elif hasattr(command_obj, option):
setattr(command_obj, option, value)
else:
- raise DistutilsOptionError, \
- ("error in %s: command '%s' has no such option '%s'"
- % (source, command_name, option))
- except ValueError, msg:
- raise DistutilsOptionError, msg
+ raise DistutilsOptionError(
+ "error in %s: command '%s' has no such option '%s'"
+ % (source, command_name, option))
+ except ValueError as msg:
+ raise DistutilsOptionError(msg)
def reinitialize_command(self, command, reinit_subcommands=0):
"""Reinitializes a command to the state it was in when first
@@ -1023,89 +987,32 @@ class DistributionMetadata:
"provides", "requires", "obsoletes",
)
- def __init__(self, path=None):
- if path is not None:
- self.read_pkg_file(open(path))
- else:
- self.name = 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')
+ def __init__ (self):
+ self.name = None
+ self.version = None
+ self.author = None
+ self.author_email = None
self.maintainer = None
- self.author_email = _read_field('author-email')
self.maintainer_email = None
- self.url = _read_field('home-page')
- self.license = _read_field('license')
-
- if 'download-url' in msg:
- self.download_url = _read_field('download-url')
- else:
- self.download_url = None
-
- self.long_description = _read_field('description')
- self.description = _read_field('summary')
-
- if 'keywords' in msg:
- 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
+ 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 write_pkg_info(self, base_dir):
"""Write the PKG-INFO file into the release tree.
"""
- pkg_info = open(os.path.join(base_dir, 'PKG-INFO'), 'w')
- try:
+ with open(os.path.join(base_dir, 'PKG-INFO'), 'w',
+ encoding='UTF-8') as pkg_info:
self.write_pkg_file(pkg_info)
- finally:
- pkg_info.close()
def write_pkg_file(self, file):
"""Write the PKG-INFO format data to a file object.
@@ -1115,23 +1022,23 @@ class DistributionMetadata:
self.classifiers or self.download_url):
version = '1.1'
- self._write_field(file, 'Metadata-Version', version)
- self._write_field(file, 'Name', self.get_name())
- self._write_field(file, 'Version', self.get_version())
- self._write_field(file, 'Summary', self.get_description())
- self._write_field(file, 'Home-page', self.get_url())
- self._write_field(file, 'Author', self.get_contact())
- self._write_field(file, 'Author-email', self.get_contact_email())
- self._write_field(file, 'License', self.get_license())
+ file.write('Metadata-Version: %s\n' % version)
+ file.write('Name: %s\n' % self.get_name() )
+ file.write('Version: %s\n' % self.get_version() )
+ file.write('Summary: %s\n' % self.get_description() )
+ file.write('Home-page: %s\n' % self.get_url() )
+ file.write('Author: %s\n' % self.get_contact() )
+ file.write('Author-email: %s\n' % self.get_contact_email() )
+ file.write('License: %s\n' % self.get_license() )
if self.download_url:
- self._write_field(file, 'Download-URL', self.download_url)
+ file.write('Download-URL: %s\n' % self.download_url)
long_desc = rfc822_escape(self.get_long_description())
- self._write_field(file, 'Description', long_desc)
+ file.write('Description: %s\n' % long_desc)
keywords = ','.join(self.get_keywords())
if keywords:
- self._write_field(file, 'Keywords', keywords)
+ file.write('Keywords: %s\n' % keywords )
self._write_list(file, 'Platform', self.get_platforms())
self._write_list(file, 'Classifier', self.get_classifiers())
@@ -1141,19 +1048,9 @@ class DistributionMetadata:
self._write_list(file, 'Provides', self.get_provides())
self._write_list(file, 'Obsoletes', self.get_obsoletes())
- def _write_field(self, file, name, value):
- file.write('%s: %s\n' % (name, self._encode_field(value)))
-
- def _write_list (self, file, name, values):
+ def _write_list(self, file, name, values):
for value in values:
- self._write_field(file, name, value)
-
- def _encode_field(self, value):
- if value is None:
- return None
- if isinstance(value, unicode):
- return value.encode(PKG_INFO_ENCODING)
- return str(value)
+ file.write('%s: %s\n' % (name, value))
# -- Metadata query methods ----------------------------------------
@@ -1167,20 +1064,19 @@ class DistributionMetadata:
return "%s-%s" % (self.get_name(), self.get_version())
def get_author(self):
- return self._encode_field(self.author) or "UNKNOWN"
+ return self.author or "UNKNOWN"
def get_author_email(self):
return self.author_email or "UNKNOWN"
def get_maintainer(self):
- return self._encode_field(self.maintainer) or "UNKNOWN"
+ return self.maintainer or "UNKNOWN"
def get_maintainer_email(self):
return self.maintainer_email or "UNKNOWN"
def get_contact(self):
- return (self._encode_field(self.maintainer) or
- self._encode_field(self.author) or "UNKNOWN")
+ return self.maintainer or self.author or "UNKNOWN"
def get_contact_email(self):
return self.maintainer_email or self.author_email or "UNKNOWN"
@@ -1193,10 +1089,10 @@ class DistributionMetadata:
get_licence = get_license
def get_description(self):
- return self._encode_field(self.description) or "UNKNOWN"
+ return self.description or "UNKNOWN"
def get_long_description(self):
- return self._encode_field(self.long_description) or "UNKNOWN"
+ return self.long_description or "UNKNOWN"
def get_keywords(self):
return self.keywords or []
diff --git a/Lib/distutils/emxccompiler.py b/Lib/distutils/emxccompiler.py
index a0172058a38..3675f8df9c8 100644
--- a/Lib/distutils/emxccompiler.py
+++ b/Lib/distutils/emxccompiler.py
@@ -19,8 +19,6 @@ handles the EMX port of the GNU C compiler to OS/2.
#
# * EMX gcc 2.81/EMX 0.9d fix03
-__revision__ = "$Id$"
-
import os,sys,copy
from distutils.ccompiler import gen_preprocess_options, gen_lib_options
from distutils.unixccompiler import UnixCCompiler
@@ -79,14 +77,14 @@ class EMXCCompiler (UnixCCompiler):
# gcc requires '.rc' compiled to binary ('.res') files !!!
try:
self.spawn(["rc", "-r", src])
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
else: # for other files use the C-compiler
try:
self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
def link (self,
target_desc,
@@ -189,9 +187,8 @@ class EMXCCompiler (UnixCCompiler):
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
(base, ext) = os.path.splitext (os.path.normcase(src_name))
if ext not in (self.src_extensions + ['.rc']):
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % \
- (ext, src_name)
+ raise UnknownFileError("unknown file type '%s' (from '%s')" % \
+ (ext, src_name))
if strip_dir:
base = os.path.basename (base)
if ext == '.rc':
@@ -261,10 +258,9 @@ def check_config_h():
# "pyconfig.h" check -- should probably be renamed...
from distutils import sysconfig
- import string
# if sys.version contains GCC then python was compiled with
# GCC, and the pyconfig.h file should be OK
- if string.find(sys.version,"GCC") >= 0:
+ if sys.version.find("GCC") >= 0:
return (CONFIG_H_OK, "sys.version mentions 'GCC'")
fn = sysconfig.get_config_h_filename()
@@ -277,7 +273,7 @@ def check_config_h():
finally:
f.close()
- except IOError, exc:
+ except IOError as exc:
# if we can't read this file, we cannot say it is wrong
# the compiler will complain later about this file as missing
return (CONFIG_H_UNCERTAIN,
@@ -285,7 +281,7 @@ def check_config_h():
else:
# "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
- if string.find(s,"__GNUC__") >= 0:
+ if s.find("__GNUC__") >= 0:
return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
else:
return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
@@ -306,7 +302,7 @@ def get_versions():
out_string = out.read()
finally:
out.close()
- result = re.search('(\d+\.\d+\.\d+)',out_string)
+ result = re.search('(\d+\.\d+\.\d+)', out_string, re.ASCII)
if result:
gcc_version = StrictVersion(result.group(1))
else:
diff --git a/Lib/distutils/errors.py b/Lib/distutils/errors.py
index d9c47c761cb..eb13c983e92 100644
--- a/Lib/distutils/errors.py
+++ b/Lib/distutils/errors.py
@@ -8,81 +8,90 @@ usually raised for errors that are obviously the end-user's fault
This module is safe to use in "from ... import *" mode; it only exports
symbols whose names start with "Distutils" and end with "Error"."""
-__revision__ = "$Id$"
-
-class DistutilsError(Exception):
+class DistutilsError (Exception):
"""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
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
feels a need to subclass Distribution) is found not to be holding
up its end of the bargain, ie. implementing some part of the
"command "interface."""
+ pass
-class DistutilsGetoptError(DistutilsError):
+class DistutilsGetoptError (DistutilsError):
"""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
error in the command line usage."""
+ pass
-class DistutilsFileError(DistutilsError):
+class DistutilsFileError (DistutilsError):
"""Any problems in the filesystem: expected file not found, etc.
Typically this is for problems that we detect before IOError or
OSError could be raised."""
+ pass
-class DistutilsOptionError(DistutilsError):
+class DistutilsOptionError (DistutilsError):
"""Syntactic/semantic errors in command options, such as use of
mutually conflicting options, or inconsistent options,
badly-spelled values, etc. No distinction is made between option
values originating in the setup script, the command line, config
files, or what-have-you -- but if we *know* something originated in
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,
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 do know how to do it on some platform) -- eg. trying to compile
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
compiler, when compiling C files)."""
+ pass
-class DistutilsInternalError(DistutilsError):
+class DistutilsInternalError (DistutilsError):
"""Internal inconsistencies or impossibilities (obviously, this
should never be seen if the code is working!)."""
+ pass
-class DistutilsTemplateError(DistutilsError):
+class DistutilsTemplateError (DistutilsError):
"""Syntax error in a file list template."""
class DistutilsByteCompileError(DistutilsError):
"""Byte compile error."""
# Exception classes used by the CCompiler implementation classes
-class CCompilerError(Exception):
+class CCompilerError (Exception):
"""Some compile/link operation failed."""
-class PreprocessError(CCompilerError):
+class PreprocessError (CCompilerError):
"""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."""
-class LibError(CCompilerError):
+class LibError (CCompilerError):
"""Failure to create a static library from one or more C/C++ object
files."""
-class LinkError(CCompilerError):
+class LinkError (CCompilerError):
"""Failure to link one or more C/C++ object files into an executable
or shared library file."""
-class UnknownFileError(CCompilerError):
+class UnknownFileError (CCompilerError):
"""Attempt to process an unknown file type."""
diff --git a/Lib/distutils/extension.py b/Lib/distutils/extension.py
index 9a67ca8b3ea..a93655af2cf 100644
--- a/Lib/distutils/extension.py
+++ b/Lib/distutils/extension.py
@@ -3,15 +3,9 @@
Provides the Extension class, used to describe C/C++ extension
modules in setup scripts."""
-__revision__ = "$Id$"
-
-import os, string, sys
-from types import *
-
-try:
- import warnings
-except ImportError:
- warnings = None
+import os
+import sys
+import warnings
# This class is really only used by the "build_ext" command, so it might
# make sense to put it in distutils.command.build_ext. However, that
@@ -83,11 +77,14 @@ class Extension:
language : string
extension language (i.e. "c", "c++", "objc"). Will be detected
from the source extensions if not provided.
+ optional : boolean
+ specifies that a build failure in the extension should not abort the
+ build process, but simply not install the failing extension.
"""
# When adding arguments to this constructor, be sure to update
# setup_keywords in core.py.
- def __init__ (self, name, sources,
+ def __init__(self, name, sources,
include_dirs=None,
define_macros=None,
undef_macros=None,
@@ -101,12 +98,14 @@ class Extension:
swig_opts = None,
depends=None,
language=None,
+ optional=None,
**kw # To catch unknown keywords
):
- assert type(name) is StringType, "'name' must be a string"
- assert (type(sources) is ListType and
- map(type, sources) == [StringType]*len(sources)), \
- "'sources' must be a list of strings"
+ if not isinstance(name, str):
+ raise AssertionError("'name' must be a string")
+ if not (isinstance(sources, list) and
+ all(isinstance(v, str) for v in sources)):
+ raise AssertionError("'sources' must be a list of strings")
self.name = name
self.sources = sources
@@ -123,22 +122,20 @@ class Extension:
self.swig_opts = swig_opts or []
self.depends = depends or []
self.language = language
+ self.optional = optional
# If there are unknown keyword options, warn about them
- if len(kw):
- L = kw.keys() ; L.sort()
- L = map(repr, L)
- msg = "Unknown Extension options: " + string.join(L, ', ')
- if warnings is not None:
- warnings.warn(msg)
- else:
- sys.stderr.write(msg + '\n')
-# class Extension
-
-
-def read_setup_file (filename):
- from distutils.sysconfig import \
- parse_makefile, expand_makefile_vars, _variable_rx
+ if len(kw) > 0:
+ options = [repr(option) for option in kw]
+ options = ', '.join(sorted(options))
+ msg = "Unknown Extension options: %s" % options
+ warnings.warn(msg)
+
+def read_setup_file(filename):
+ """Reads a Setup file and returns Extension instances."""
+ from distutils.sysconfig import (parse_makefile, expand_makefile_vars,
+ _variable_rx)
+
from distutils.text_file import TextFile
from distutils.util import split_quoted
@@ -153,21 +150,19 @@ def read_setup_file (filename):
try:
extensions = []
- while 1:
+ while True:
line = file.readline()
if line is None: # eof
break
if _variable_rx.match(line): # VAR=VALUE, handled in first pass
continue
- if line[0] == line[-1] == "*":
- file.warn("'%s' lines not handled yet" % line)
- continue
+ if line[0] == line[-1] == "*":
+ file.warn("'%s' lines not handled yet" % line)
+ continue
- #print "original line: " + line
line = expand_makefile_vars(line, vars)
words = split_quoted(line)
- #print "expanded line: " + line
# NB. this parses a slightly different syntax than the old
# makesetup script: here, there must be exactly one extension per
@@ -196,7 +191,7 @@ def read_setup_file (filename):
elif switch == "-I":
ext.include_dirs.append(value)
elif switch == "-D":
- equals = string.find(value, "=")
+ equals = value.find("=")
if equals == -1: # bare "-DFOO" -- no value
ext.define_macros.append((value, None))
else: # "-DFOO=blah"
@@ -222,12 +217,6 @@ def read_setup_file (filename):
ext.extra_link_args.append(word)
if not value:
append_next_word = ext.extra_link_args
- elif word == "-Xcompiler":
- append_next_word = ext.extra_compile_args
- elif switch == "-u":
- ext.extra_link_args.append(word)
- if not value:
- append_next_word = ext.extra_link_args
elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
# NB. a really faithful emulation of makesetup would
# append a .o file to extra_objects only if it
@@ -241,15 +230,4 @@ def read_setup_file (filename):
finally:
file.close()
- #print "module:", module
- #print "source files:", source_files
- #print "cpp args:", cpp_args
- #print "lib args:", library_args
-
- #extensions[module] = { 'sources': source_files,
- # 'cpp_args': cpp_args,
- # 'lib_args': library_args }
-
return extensions
-
-# read_setup_file ()
diff --git a/Lib/distutils/fancy_getopt.py b/Lib/distutils/fancy_getopt.py
index 2dea9480259..7d170dd2773 100644
--- a/Lib/distutils/fancy_getopt.py
+++ b/Lib/distutils/fancy_getopt.py
@@ -8,13 +8,9 @@ additional features:
* options set attributes of a passed-in object
"""
-__revision__ = "$Id$"
-
-import sys
-import string
-import re
+import sys, string, re
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
# the same as a Python NAME -- except, in the spirit of most GNU
@@ -28,7 +24,7 @@ neg_alias_re = re.compile("^(%s)=!(%s)$" % (longopt_pat, longopt_pat))
# This is used to translate long options to legitimate Python identifiers
# (for use as attributes of some object).
-longopt_xlate = string.maketrans('-', '_')
+longopt_xlate = str.maketrans('-', '_')
class FancyGetopt:
"""Wrapper around the standard 'getopt()' module that provides some
@@ -42,8 +38,7 @@ class FancyGetopt:
on the command line sets 'verbose' to false
"""
- def __init__ (self, option_table=None):
-
+ def __init__(self, option_table=None):
# The option table is (currently) a list of tuples. The
# tuples may have 3 or four values:
# (long_option, short_option, help_string [, repeatable])
@@ -83,58 +78,51 @@ class FancyGetopt:
# but expands short options, converts aliases, etc.
self.option_order = []
- # __init__ ()
-
-
- def _build_index (self):
+ def _build_index(self):
self.option_index.clear()
for option in self.option_table:
self.option_index[option[0]] = option
- def set_option_table (self, option_table):
+ def set_option_table(self, option_table):
self.option_table = option_table
self._build_index()
- def add_option (self, long_option, short_option=None, help_string=None):
+ def add_option(self, long_option, short_option=None, help_string=None):
if long_option in self.option_index:
- raise DistutilsGetoptError, \
- "option conflict: already an option '%s'" % long_option
+ raise DistutilsGetoptError(
+ "option conflict: already an option '%s'" % long_option)
else:
option = (long_option, short_option, help_string)
self.option_table.append(option)
self.option_index[long_option] = option
-
- def has_option (self, long_option):
+ def has_option(self, long_option):
"""Return true if the option table for this parser has an
option with long name 'long_option'."""
return long_option in self.option_index
- def get_attr_name (self, long_option):
+ def get_attr_name(self, long_option):
"""Translate long option name 'long_option' to the form it
has as an attribute of some object: ie., translate hyphens
to underscores."""
- return string.translate(long_option, longopt_xlate)
-
+ return long_option.translate(longopt_xlate)
- def _check_alias_dict (self, aliases, what):
+ def _check_alias_dict(self, aliases, what):
assert isinstance(aliases, dict)
for (alias, opt) in aliases.items():
if alias not in self.option_index:
- raise DistutilsGetoptError, \
- ("invalid %s '%s': "
- "option '%s' not defined") % (what, alias, alias)
+ raise DistutilsGetoptError(("invalid %s '%s': "
+ "option '%s' not defined") % (what, alias, alias))
if opt not in self.option_index:
- raise DistutilsGetoptError, \
- ("invalid %s '%s': "
- "aliased option '%s' not defined") % (what, alias, opt)
+ raise DistutilsGetoptError(("invalid %s '%s': "
+ "aliased option '%s' not defined") % (what, alias, opt))
- def set_aliases (self, alias):
+ def set_aliases(self, alias):
"""Set the aliases for this option parser."""
self._check_alias_dict(alias, "alias")
self.alias = alias
- def set_negative_aliases (self, negative_alias):
+ def set_negative_aliases(self, negative_alias):
"""Set the negative aliases for this option parser.
'negative_alias' should be a dictionary mapping option names to
option names, both the key and value must already be defined
@@ -142,8 +130,7 @@ class FancyGetopt:
self._check_alias_dict(negative_alias, "negative alias")
self.negative_alias = negative_alias
-
- def _grok_option_table (self):
+ def _grok_option_table(self):
"""Populate the various data structures that keep tabs on the
option table. Called by 'getopt()' before it can do anything
worthwhile.
@@ -162,19 +149,17 @@ class FancyGetopt:
else:
# the option table is part of the code, so simply
# assert that it is correct
- raise ValueError, "invalid option tuple: %r" % (option,)
+ raise ValueError("invalid option tuple: %r" % (option,))
# Type- and value-check the option names
if not isinstance(long, str) or len(long) < 2:
- raise DistutilsGetoptError, \
- ("invalid long option '%s': "
- "must be a string of length >= 2") % long
+ raise DistutilsGetoptError(("invalid long option '%s': "
+ "must be a string of length >= 2") % long)
if (not ((short is None) or
(isinstance(short, str) and len(short) == 1))):
- raise DistutilsGetoptError, \
- ("invalid short option '%s': "
- "must a single character or None") % short
+ raise DistutilsGetoptError("invalid short option '%s': "
+ "must a single character or None" % short)
self.repeat[long] = repeat
self.long_opts.append(long)
@@ -184,54 +169,45 @@ class FancyGetopt:
long = long[0:-1]
self.takes_arg[long] = 1
else:
-
# Is option is a "negative alias" for some other option (eg.
# "quiet" == "!verbose")?
alias_to = self.negative_alias.get(long)
if alias_to is not None:
if self.takes_arg[alias_to]:
- raise DistutilsGetoptError, \
- ("invalid negative alias '%s': "
- "aliased option '%s' takes a value") % \
- (long, alias_to)
+ raise DistutilsGetoptError(
+ "invalid negative alias '%s': "
+ "aliased option '%s' takes a value"
+ % (long, alias_to))
self.long_opts[-1] = long # XXX redundant?!
- self.takes_arg[long] = 0
-
- else:
- self.takes_arg[long] = 0
+ self.takes_arg[long] = 0
# If this is an alias option, make sure its "takes arg" flag is
# the same as the option it's aliased to.
alias_to = self.alias.get(long)
if alias_to is not None:
if self.takes_arg[long] != self.takes_arg[alias_to]:
- raise DistutilsGetoptError, \
- ("invalid alias '%s': inconsistent with "
- "aliased option '%s' (one of them takes a value, "
- "the other doesn't") % (long, alias_to)
-
+ raise DistutilsGetoptError(
+ "invalid alias '%s': inconsistent with "
+ "aliased option '%s' (one of them takes a value, "
+ "the other doesn't"
+ % (long, alias_to))
# Now enforce some bondage on the long option name, so we can
# later translate it to an attribute name on some object. Have
# to do this a bit late to make sure we've removed any trailing
# '='.
if not longopt_re.match(long):
- raise DistutilsGetoptError, \
- ("invalid long option name '%s' " +
- "(must be letters, numbers, hyphens only") % long
+ raise DistutilsGetoptError(
+ "invalid long option name '%s' "
+ "(must be letters, numbers, hyphens only" % long)
self.attr_name[long] = self.get_attr_name(long)
if short:
self.short_opts.append(short)
self.short2long[short[0]] = long
- # for option_table
-
- # _grok_option_table()
-
-
- def getopt (self, args=None, object=None):
+ def getopt(self, args=None, object=None):
"""Parse command-line options in args. Store as attributes on object.
If 'args' is None or not supplied, uses 'sys.argv[1:]'. If
@@ -246,17 +222,17 @@ class FancyGetopt:
args = sys.argv[1:]
if object is None:
object = OptionDummy()
- created_object = 1
+ created_object = True
else:
- created_object = 0
+ created_object = False
self._grok_option_table()
- short_opts = string.join(self.short_opts)
+ short_opts = ' '.join(self.short_opts)
try:
opts, args = getopt.getopt(args, short_opts, self.long_opts)
- except getopt.error, msg:
- raise DistutilsArgError, msg
+ except getopt.error as msg:
+ raise DistutilsArgError(msg)
for opt, val in opts:
if len(opt) == 2 and opt[0] == '-': # it's a short option
@@ -292,21 +268,17 @@ class FancyGetopt:
else:
return args
- # getopt()
-
-
- def get_option_order (self):
+ def get_option_order(self):
"""Returns the list of (option, value) tuples processed by the
previous run of 'getopt()'. Raises RuntimeError if
'getopt()' hasn't been called yet.
"""
if self.option_order is None:
- raise RuntimeError, "'getopt()' hasn't been called yet"
+ raise RuntimeError("'getopt()' hasn't been called yet")
else:
return self.option_order
-
- def generate_help (self, header=None):
+ def generate_help(self, header=None):
"""Generate help text (a list of strings, one per suggested line of
output) from the option table for this FancyGetopt object.
"""
@@ -383,50 +355,41 @@ class FancyGetopt:
for l in text[1:]:
lines.append(big_indent + l)
-
- # for self.option_table
-
return lines
- # generate_help ()
-
- def print_help (self, header=None, file=None):
+ def print_help(self, header=None, file=None):
if file is None:
file = sys.stdout
for line in self.generate_help(header):
file.write(line + "\n")
-# class FancyGetopt
-
-def fancy_getopt (options, negative_opt, object, args):
+def fancy_getopt(options, negative_opt, object, args):
parser = FancyGetopt(options)
parser.set_negative_aliases(negative_opt)
return parser.getopt(args, object)
-WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace))
+WS_TRANS = {ord(_wschar) : ' ' for _wschar in string.whitespace}
-def wrap_text (text, width):
+def wrap_text(text, width):
"""wrap_text(text : string, width : int) -> [string]
Split 'text' into multiple lines of no more than 'width' characters
each, and return the list of strings that results.
"""
-
if text is None:
return []
if len(text) <= width:
return [text]
- text = string.expandtabs(text)
- text = string.translate(text, WS_TRANS)
+ text = text.expandtabs()
+ text = text.translate(WS_TRANS)
chunks = re.split(r'( +|-+)', text)
- chunks = filter(None, chunks) # ' - ' results in empty strings
+ chunks = [ch for ch in chunks if ch] # ' - ' results in empty strings
lines = []
while chunks:
-
cur_line = [] # list of chunks (to-be-joined)
cur_len = 0 # length of current line
@@ -443,7 +406,6 @@ def wrap_text (text, width):
break
if chunks: # any chunks left to process?
-
# if the current line is still empty, then we had a single
# chunk that's too big too fit on a line -- so we break
# down and break it up at the line width
@@ -459,9 +421,7 @@ def wrap_text (text, width):
# and store this line in the list-of-all-lines -- as a single
# string, of course!
- lines.append(string.join(cur_line, ''))
-
- # while chunks
+ lines.append(''.join(cur_line))
return lines
@@ -470,15 +430,28 @@ def translate_longopt(opt):
"""Convert a long option name to a valid Python identifier by
changing "-" to "_".
"""
- return string.translate(opt, longopt_xlate)
+ return opt.translate(longopt_xlate)
class OptionDummy:
"""Dummy class just used as a place to hold command-line option
values as instance attributes."""
- def __init__ (self, options=[]):
+ def __init__(self, options=[]):
"""Create a new OptionDummy instance. The attributes listed in
'options' will be initialized to None."""
for opt in options:
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()
diff --git a/Lib/distutils/file_util.py b/Lib/distutils/file_util.py
index b9f07861335..9bdd14e42e3 100644
--- a/Lib/distutils/file_util.py
+++ b/Lib/distutils/file_util.py
@@ -3,25 +3,22 @@
Utility functions for operating on single files.
"""
-__revision__ = "$Id$"
-
import os
from distutils.errors import DistutilsFileError
from distutils import log
# for generating verbose output in 'copy_file()'
-_copy_action = {None: 'copying',
- 'hard': 'hard linking',
- 'sym': 'symbolically linking'}
+_copy_action = { None: 'copying',
+ 'hard': 'hard linking',
+ 'sym': 'symbolically linking' }
def _copy_file_contents(src, dst, buffer_size=16*1024):
- """Copy the file 'src' to 'dst'.
-
- Both must be filenames. Any error opening either file, reading from
- 'src', or writing to 'dst', raises DistutilsFileError. Data is
- read/written in chunks of 'buffer_size' bytes (default 16k). No attempt
- is made to handle anything apart from regular files.
+ """Copy the file 'src' to 'dst'; both must be filenames. Any error
+ opening either file, reading from 'src', or writing to 'dst', raises
+ DistutilsFileError. Data is read/written in chunks of 'buffer_size'
+ bytes (default 16k). No attempt is made to handle anything apart from
+ regular files.
"""
# Stolen from shutil module in the standard library, but with
# custom error-handling added.
@@ -30,38 +27,37 @@ def _copy_file_contents(src, dst, buffer_size=16*1024):
try:
try:
fsrc = open(src, 'rb')
- except os.error, (errno, errstr):
- raise DistutilsFileError("could not open '%s': %s" % (src, errstr))
+ except os.error as e:
+ raise DistutilsFileError("could not open '%s': %s" % (src, e.strerror))
if os.path.exists(dst):
try:
os.unlink(dst)
- except os.error, (errno, errstr):
+ except os.error as e:
raise DistutilsFileError(
- "could not delete '%s': %s" % (dst, errstr))
+ "could not delete '%s': %s" % (dst, e.strerror))
try:
fdst = open(dst, 'wb')
- except os.error, (errno, errstr):
+ except os.error as e:
raise DistutilsFileError(
- "could not create '%s': %s" % (dst, errstr))
+ "could not create '%s': %s" % (dst, e.strerror))
- while 1:
+ while True:
try:
buf = fsrc.read(buffer_size)
- except os.error, (errno, errstr):
+ except os.error as e:
raise DistutilsFileError(
- "could not read from '%s': %s" % (src, errstr))
+ "could not read from '%s': %s" % (src, e.strerror))
if not buf:
break
try:
fdst.write(buf)
- except os.error, (errno, errstr):
+ except os.error as e:
raise DistutilsFileError(
- "could not write to '%s': %s" % (dst, errstr))
-
+ "could not write to '%s': %s" % (dst, e.strerror))
finally:
if fdst:
fdst.close()
@@ -70,16 +66,15 @@ def _copy_file_contents(src, dst, buffer_size=16*1024):
def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
link=None, verbose=1, dry_run=0):
- """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 the file exists, it will be
- ruthlessly clobbered.) If 'preserve_mode' is true (the default),
- the file's mode (type and permission bits, or whatever is analogous on
- the current platform) is copied. If 'preserve_times' is true (the
- default), the last-modified and last-access times are copied as well.
- If 'update' is true, 'src' will only be copied if 'dst' does not exist,
- or if 'dst' does exist but is older than 'src'.
+ """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
+ the file exists, it will be ruthlessly clobbered.) If 'preserve_mode'
+ is true (the default), the file's mode (type and permission bits, or
+ whatever is analogous on the current platform) is copied. If
+ 'preserve_times' is true (the default), the last-modified and
+ last-access times are copied as well. If 'update' is true, 'src' will
+ only be copied if 'dst' does not exist, or if 'dst' does exist but is
+ older than 'src'.
'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
@@ -117,7 +112,7 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
if update and not newer(src, dst):
if verbose >= 1:
log.debug("not copying %s (output up-to-date)", src)
- return dst, 0
+ return (dst, 0)
try:
action = _copy_action[link]
@@ -135,7 +130,7 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
# If linking (hard or symbolic), use the appropriate system call
# (Unix only, of course, but that's the caller's responsibility)
- if link == 'hard':
+ elif link == 'hard':
if not (os.path.exists(dst) and os.path.samefile(src, dst)):
os.link(src, dst)
elif link == 'sym':
@@ -158,13 +153,15 @@ def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
return (dst, 1)
+
# XXX I suspect this is Unix-specific -- need porting help!
-def move_file (src, dst, verbose=1, dry_run=0):
- """Move a file 'src' to 'dst'.
+def move_file (src, dst,
+ verbose=1,
+ dry_run=0):
- If 'dst' is a directory, the file will be moved into it with the same
- name; otherwise, 'src' is just renamed to 'dst'. Return the new
- full name of the file.
+ """Move a file 'src' to 'dst'. If 'dst' is a directory, the file will
+ be moved into it with the same name; otherwise, 'src' is just renamed
+ to 'dst'. Return the new full name of the file.
Handles cross-device moves on Unix using 'copy_file()'. What about
other systems???
@@ -190,15 +187,16 @@ def move_file (src, dst, verbose=1, dry_run=0):
if not isdir(dirname(dst)):
raise DistutilsFileError(
- "can't move '%s': destination '%s' not a valid path" % \
+ "can't move '%s': destination '%s' not a valid path" %
(src, dst))
- copy_it = 0
+ copy_it = False
try:
os.rename(src, dst)
- except os.error, (num, msg):
+ except os.error as e:
+ (num, msg) = e
if num == errno.EXDEV:
- copy_it = 1
+ copy_it = True
else:
raise DistutilsFileError(
"couldn't move '%s' to '%s': %s" % (src, dst, msg))
@@ -207,15 +205,16 @@ def move_file (src, dst, verbose=1, dry_run=0):
copy_file(src, dst, verbose=verbose)
try:
os.unlink(src)
- except os.error, (num, msg):
+ except os.error as e:
+ (num, msg) = e
try:
os.unlink(dst)
except os.error:
pass
raise DistutilsFileError(
- ("couldn't move '%s' to '%s' by copy/delete: " +
- "delete '%s' failed: %s") %
- (src, dst, src, msg))
+ "couldn't move '%s' to '%s' by copy/delete: "
+ "delete '%s' failed: %s"
+ % (src, dst, src, msg))
return dst
diff --git a/Lib/distutils/filelist.py b/Lib/distutils/filelist.py
index 2f1c457ea0b..db3f7a96802 100644
--- a/Lib/distutils/filelist.py
+++ b/Lib/distutils/filelist.py
@@ -4,8 +4,6 @@ Provides the FileList class, used for poking about the filesystem
and building lists of files.
"""
-__revision__ = "$Id$"
-
import os, re
import fnmatch
from distutils.util import convert_path
@@ -45,7 +43,7 @@ class FileList:
"""
from distutils.debug import DEBUG
if DEBUG:
- print msg
+ print(msg)
# -- List-like methods ---------------------------------------------
@@ -57,8 +55,7 @@ class FileList:
def sort(self):
# Not a strict lexical sort!
- sortable_files = map(os.path.split, self.files)
- sortable_files.sort()
+ sortable_files = sorted(map(os.path.split, self.files))
self.files = []
for sort_tuple in sortable_files:
self.files.append(os.path.join(*sort_tuple))
@@ -84,28 +81,22 @@ class FileList:
if action in ('include', 'exclude',
'global-include', 'global-exclude'):
if len(words) < 2:
- raise DistutilsTemplateError, \
- "'%s' expects <pattern1> <pattern2> ..." % action
-
- patterns = map(convert_path, words[1:])
-
+ raise DistutilsTemplateError(
+ "'%s' expects <pattern1> <pattern2> ..." % action)
+ patterns = [convert_path(w) for w in words[1:]]
elif action in ('recursive-include', 'recursive-exclude'):
if len(words) < 3:
- raise DistutilsTemplateError, \
- "'%s' expects <dir> <pattern1> <pattern2> ..." % action
-
+ raise DistutilsTemplateError(
+ "'%s' expects <dir> <pattern1> <pattern2> ..." % action)
dir = convert_path(words[1])
- patterns = map(convert_path, words[2:])
-
+ patterns = [convert_path(w) for w in words[2:]]
elif action in ('graft', 'prune'):
if len(words) != 2:
- raise DistutilsTemplateError, \
- "'%s' expects a single <dir_pattern>" % action
-
+ raise DistutilsTemplateError(
+ "'%s' expects a single <dir_pattern>" % action)
dir_pattern = convert_path(words[1])
-
else:
- raise DistutilsTemplateError, "unknown action '%s'" % action
+ raise DistutilsTemplateError("unknown action '%s'" % action)
return (action, patterns, dir, dir_pattern)
@@ -115,7 +106,7 @@ class FileList:
# defined: it's the first word of the line. Which of the other
# three are defined depends on the action; it'll be either
# 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
# right number of words on the line for that action -- so we
@@ -138,7 +129,7 @@ class FileList:
self.debug_print("global-include " + ' '.join(patterns))
for pattern in patterns:
if not self.include_pattern(pattern, anchor=0):
- log.warn(("warning: no files found matching '%s' " +
+ log.warn(("warning: no files found matching '%s' "
"anywhere in distribution"), pattern)
elif action == 'global-exclude':
@@ -154,7 +145,7 @@ class FileList:
(dir, ' '.join(patterns)))
for pattern in patterns:
if not self.include_pattern(pattern, prefix=dir):
- log.warn(("warning: no files found matching '%s' " +
+ log.warn(("warning: no files found matching '%s' "
"under directory '%s'"),
pattern, dir)
@@ -176,21 +167,21 @@ class FileList:
elif action == 'prune':
self.debug_print("prune " + dir_pattern)
if not self.exclude_pattern(None, prefix=dir_pattern):
- log.warn(("no previously-included directories found " +
+ log.warn(("no previously-included directories found "
"matching '%s'"), dir_pattern)
else:
- raise DistutilsInternalError, \
- "this cannot happen: invalid action '%s'" % action
+ raise DistutilsInternalError(
+ "this cannot happen: invalid action '%s'" % action)
+
# -- Filtering/selection methods -----------------------------------
def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
"""Select strings (presumably filenames) from 'self.files' that
- match 'pattern', a Unix-style wildcard (glob) pattern.
-
- Patterns are not quite the same as implemented by the 'fnmatch'
- module: '*' and '?' match non-special characters, where "special"
- is platform-dependent: slash on Unix; colon, slash, and backslash on
+ match 'pattern', a Unix-style wildcard (glob) pattern. Patterns
+ are not quite the same as implemented by the 'fnmatch' module: '*'
+ and '?' match non-special characters, where "special" is platform-
+ dependent: slash on Unix; colon, slash, and backslash on
DOS/Windows; and colon on Mac OS.
If 'anchor' is true (the default), then the pattern match is more
@@ -208,10 +199,10 @@ class FileList:
Selected strings will be added to self.files.
- Return 1 if files are found.
+ Return True if files are found, False otherwise.
"""
# XXX docstring lying about what the special chars are?
- files_found = 0
+ files_found = False
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
self.debug_print("include_pattern: applying regex r'%s'" %
pattern_re.pattern)
@@ -224,20 +215,19 @@ class FileList:
if pattern_re.search(name):
self.debug_print(" adding " + name)
self.files.append(name)
- files_found = 1
-
+ files_found = True
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
- 'pattern'.
-
- Other parameters are the same as for 'include_pattern()', above.
- The list 'self.files' is modified in place. Return 1 if files are
- found.
+ 'pattern'. Other parameters are the same as for
+ 'include_pattern()', above.
+ The list 'self.files' is modified in place.
+ Return True if files are found, False otherwise.
"""
- files_found = 0
+ files_found = False
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
self.debug_print("exclude_pattern: applying regex r'%s'" %
pattern_re.pattern)
@@ -245,15 +235,14 @@ class FileList:
if pattern_re.search(self.files[i]):
self.debug_print(" removing " + self.files[i])
del self.files[i]
- files_found = 1
-
+ files_found = True
return files_found
# ----------------------------------------------------------------------
# Utility functions
-def findall(dir = os.curdir):
+def findall(dir=os.curdir):
"""Find all files under 'dir' and return the list of full filenames
(relative to 'dir').
"""
@@ -281,16 +270,14 @@ def findall(dir = os.curdir):
list.append(fullname)
elif S_ISDIR(mode) and not S_ISLNK(mode):
push(fullname)
-
return list
def glob_to_re(pattern):
- """Translate a shell-like glob pattern to a regular expression.
-
- Return a string containing the regex. Differs from
- 'fnmatch.translate()' in that '*' does not match "special characters"
- (which are platform-specific).
+ """Translate a shell-like glob pattern to a regular expression; return
+ a string containing the regex. Differs from 'fnmatch.translate()' in
+ that '*' does not match "special characters" (which are
+ platform-specific).
"""
pattern_re = fnmatch.translate(pattern)
@@ -311,9 +298,7 @@ def glob_to_re(pattern):
def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
"""Translate a shell-like wildcard pattern to a compiled regular
- expression.
-
- Return the compiled regex. If 'is_regex' true,
+ expression. Return the compiled regex. If 'is_regex' true,
then 'pattern' is directly compiled to a regex (if it's a string)
or just returned as-is (assumes it's a regex object).
"""
diff --git a/Lib/distutils/log.py b/Lib/distutils/log.py
index 758857081c8..b301a8338c2 100644
--- a/Lib/distutils/log.py
+++ b/Lib/distutils/log.py
@@ -27,6 +27,10 @@ class Log:
stream = sys.stderr
else:
stream = sys.stdout
+ if stream.errors == 'strict':
+ # emulate backslashreplace error handler
+ encoding = stream.encoding
+ msg = msg.encode(encoding, "backslashreplace").decode(encoding)
stream.write('%s\n' % msg)
stream.flush()
diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py
index 7ec9b92a5dc..b3f6ce10a81 100644
--- a/Lib/distutils/msvc9compiler.py
+++ b/Lib/distutils/msvc9compiler.py
@@ -12,30 +12,29 @@ for older versions of VS in distutils.msvccompiler.
# finding DevStudio (through the registry)
# ported to VS2005 and VS 2008 by Christian Heimes
-__revision__ = "$Id$"
-
import os
import subprocess
import sys
import re
-from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
- CompileError, LibError, LinkError)
-from distutils.ccompiler import CCompiler, gen_lib_options
+from distutils.errors import DistutilsExecError, DistutilsPlatformError, \
+ CompileError, LibError, LinkError
+from distutils.ccompiler import CCompiler, gen_preprocess_options, \
+ gen_lib_options
from distutils import log
from distutils.util import get_platform
-import _winreg
+import winreg
-RegOpenKeyEx = _winreg.OpenKeyEx
-RegEnumKey = _winreg.EnumKey
-RegEnumValue = _winreg.EnumValue
-RegError = _winreg.error
+RegOpenKeyEx = winreg.OpenKeyEx
+RegEnumKey = winreg.EnumKey
+RegEnumValue = winreg.EnumValue
+RegError = winreg.error
-HKEYS = (_winreg.HKEY_USERS,
- _winreg.HKEY_CURRENT_USER,
- _winreg.HKEY_LOCAL_MACHINE,
- _winreg.HKEY_CLASSES_ROOT)
+HKEYS = (winreg.HKEY_USERS,
+ winreg.HKEY_CURRENT_USER,
+ winreg.HKEY_LOCAL_MACHINE,
+ winreg.HKEY_CLASSES_ROOT)
NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32)
if NATIVE_WIN64:
@@ -43,12 +42,10 @@ if NATIVE_WIN64:
# the corresponding registry branch, if we're running a
# 64-bit Python on Win64
VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
- VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f"
WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework"
else:
VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
- VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
NET_BASE = r"Software\Microsoft\.NETFramework"
@@ -227,18 +224,9 @@ def find_vcvarsall(version):
productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
"productdir")
except KeyError:
+ log.debug("Unable to find productdir in registry")
productdir = None
- # trying Express edition
- if productdir is None:
- vsbase = VSEXPRESS_BASE % version
- try:
- productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
- "productdir")
- except KeyError:
- productdir = None
- log.debug("Unable to find productdir in registry")
-
if not productdir or not os.path.isdir(productdir):
toolskey = "VS%0.f0COMNTOOLS" % version
toolsdir = os.environ.get(toolskey, None)
@@ -382,10 +370,9 @@ class MSVCCompiler(CCompiler) :
vc_env = query_vcvarsall(VERSION, plat_spec)
- # take care to only use strings in the environment.
- self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep)
- os.environ['lib'] = vc_env['lib'].encode('mbcs')
- os.environ['include'] = vc_env['include'].encode('mbcs')
+ self.__paths = vc_env['path'].split(os.pathsep)
+ os.environ['lib'] = vc_env['lib']
+ os.environ['include'] = vc_env['include']
if len(self.__paths) == 0:
raise DistutilsPlatformError("Python was built with %s, "
@@ -504,7 +491,7 @@ class MSVCCompiler(CCompiler) :
try:
self.spawn([self.rc] + pp_opts +
[output_opt] + [input_opt])
- except DistutilsExecError, msg:
+ except DistutilsExecError as msg:
raise CompileError(msg)
continue
elif ext in self._mc_extensions:
@@ -531,7 +518,7 @@ class MSVCCompiler(CCompiler) :
self.spawn([self.rc] +
["/fo" + obj] + [rc_file])
- except DistutilsExecError, msg:
+ except DistutilsExecError as msg:
raise CompileError(msg)
continue
else:
@@ -544,7 +531,7 @@ class MSVCCompiler(CCompiler) :
self.spawn([self.cc] + compile_opts + pp_opts +
[input_opt, output_opt] +
extra_postargs)
- except DistutilsExecError, msg:
+ except DistutilsExecError as msg:
raise CompileError(msg)
return objects
@@ -569,7 +556,7 @@ class MSVCCompiler(CCompiler) :
pass # XXX what goes here?
try:
self.spawn([self.lib] + lib_args)
- except DistutilsExecError, msg:
+ except DistutilsExecError as msg:
raise LibError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
@@ -650,7 +637,7 @@ class MSVCCompiler(CCompiler) :
self.mkpath(os.path.dirname(output_filename))
try:
self.spawn([self.linker] + ld_args)
- except DistutilsExecError, msg:
+ except DistutilsExecError as msg:
raise LinkError(msg)
# embed the manifest
@@ -665,7 +652,7 @@ class MSVCCompiler(CCompiler) :
try:
self.spawn(['mt.exe', '-nologo', '-manifest',
mffilename, out_arg])
- except DistutilsExecError, msg:
+ except DistutilsExecError as msg:
raise LinkError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
diff --git a/Lib/distutils/msvccompiler.py b/Lib/distutils/msvccompiler.py
index 0e69fd368ca..81166569619 100644
--- a/Lib/distutils/msvccompiler.py
+++ b/Lib/distutils/msvccompiler.py
@@ -8,45 +8,41 @@ for the Microsoft Visual Studio.
# hacked by Robin Becker and Thomas Heller to do a better job of
# finding DevStudio (through the registry)
-__revision__ = "$Id$"
-
-import sys
-import os
-import string
-
-from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
- CompileError, LibError, LinkError)
-from distutils.ccompiler import CCompiler, gen_lib_options
+import sys, os
+from distutils.errors import \
+ DistutilsExecError, DistutilsPlatformError, \
+ CompileError, LibError, LinkError
+from distutils.ccompiler import \
+ CCompiler, gen_preprocess_options, gen_lib_options
from distutils import log
-_can_read_reg = 0
+_can_read_reg = False
try:
- import _winreg
+ import winreg
- _can_read_reg = 1
- hkey_mod = _winreg
+ _can_read_reg = True
+ hkey_mod = winreg
- RegOpenKeyEx = _winreg.OpenKeyEx
- RegEnumKey = _winreg.EnumKey
- RegEnumValue = _winreg.EnumValue
- RegError = _winreg.error
+ RegOpenKeyEx = winreg.OpenKeyEx
+ RegEnumKey = winreg.EnumKey
+ RegEnumValue = winreg.EnumValue
+ RegError = winreg.error
except ImportError:
try:
import win32api
import win32con
- _can_read_reg = 1
+ _can_read_reg = True
hkey_mod = win32con
RegOpenKeyEx = win32api.RegOpenKeyEx
RegEnumKey = win32api.RegEnumKey
RegEnumValue = win32api.RegEnumValue
RegError = win32api.error
-
except ImportError:
log.info("Warning: Can't read registry to find the "
"necessary compiler setting\n"
- "Make sure that Python modules _winreg, "
+ "Make sure that Python modules winreg, "
"win32api or win32con are installed.")
pass
@@ -58,20 +54,19 @@ if _can_read_reg:
def read_keys(base, key):
"""Return list of registry keys."""
-
try:
handle = RegOpenKeyEx(base, key)
except RegError:
return None
L = []
i = 0
- while 1:
+ while True:
try:
k = RegEnumKey(handle, i)
except RegError:
break
L.append(k)
- i = i + 1
+ i += 1
return L
def read_values(base, key):
@@ -85,27 +80,26 @@ def read_values(base, key):
return None
d = {}
i = 0
- while 1:
+ while True:
try:
name, value, type = RegEnumValue(handle, i)
except RegError:
break
name = name.lower()
d[convert_mbcs(name)] = convert_mbcs(value)
- i = i + 1
+ i += 1
return d
def convert_mbcs(s):
- enc = getattr(s, "encode", None)
- if enc is not None:
+ dec = getattr(s, "decode", None)
+ if dec is not None:
try:
- s = enc("mbcs")
+ s = dec("mbcs")
except UnicodeError:
pass
return s
class MacroExpander:
-
def __init__(self, version):
self.macros = {}
self.load_macros(version)
@@ -128,9 +122,9 @@ class MacroExpander:
self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
else:
self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
- except KeyError:
- raise DistutilsPlatformError, \
- ("""Python was built with Visual Studio 2003;
+ except KeyError as exc: #
+ raise DistutilsPlatformError(
+ """Python was built with Visual Studio 2003;
extensions must be built with a compiler than can generate compatible binaries.
Visual Studio 2003 was not found on this system. If you have Cygwin installed,
you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
@@ -147,7 +141,7 @@ you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
def sub(self, s):
for k, v in self.macros.items():
- s = string.replace(s, k, v)
+ s = s.replace(k, v)
return s
def get_build_version():
@@ -156,9 +150,8 @@ def get_build_version():
For Python 2.3 and up, the version number is included in
sys.version. For earlier versions, assume the compiler is MSVC 6.
"""
-
prefix = "MSC v."
- i = string.find(sys.version, prefix)
+ i = sys.version.find(prefix)
if i == -1:
return 6
i = i + len(prefix)
@@ -180,10 +173,10 @@ def get_build_architecture():
"""
prefix = " bit ("
- i = string.find(sys.version, prefix)
+ i = sys.version.find(prefix)
if i == -1:
return "Intel"
- j = string.find(sys.version, ")", i)
+ j = sys.version.find(")", i)
return sys.version[i+len(prefix):j]
def normalize_and_reduce_paths(paths):
@@ -201,7 +194,7 @@ def normalize_and_reduce_paths(paths):
return reduced_paths
-class MSVCCompiler (CCompiler) :
+class MSVCCompiler(CCompiler) :
"""Concrete class that implements an interface to Microsoft Visual C++,
as defined by the CCompiler abstract class."""
@@ -231,7 +224,7 @@ class MSVCCompiler (CCompiler) :
static_lib_format = shared_lib_format = '%s%s'
exe_extension = '.exe'
- def __init__ (self, verbose=0, dry_run=0, force=0):
+ def __init__(self, verbose=0, dry_run=0, force=0):
CCompiler.__init__ (self, verbose, dry_run, force)
self.__version = get_build_version()
self.__arch = get_build_architecture()
@@ -262,11 +255,11 @@ class MSVCCompiler (CCompiler) :
else:
self.__paths = self.get_msvc_paths("path")
- if len (self.__paths) == 0:
- raise DistutilsPlatformError, \
- ("Python was built with %s, "
+ if len(self.__paths) == 0:
+ raise DistutilsPlatformError("Python was built with %s, "
"and extensions need to be built with the same "
- "version of the compiler, but it isn't installed." % self.__product)
+ "version of the compiler, but it isn't installed."
+ % self.__product)
self.cc = self.find_exe("cl.exe")
self.linker = self.find_exe("link.exe")
@@ -278,12 +271,12 @@ class MSVCCompiler (CCompiler) :
# extend the MSVC path with the current path
try:
- for p in string.split(os.environ['path'], ';'):
+ for p in os.environ['path'].split(';'):
self.__paths.append(p)
except KeyError:
pass
self.__paths = normalize_and_reduce_paths(self.__paths)
- os.environ['path'] = string.join(self.__paths, ';')
+ os.environ['path'] = ";".join(self.__paths)
self.preprocess_options = None
if self.__arch == "Intel":
@@ -313,10 +306,10 @@ class MSVCCompiler (CCompiler) :
# -- Worker methods ------------------------------------------------
- def object_filenames (self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
+ def object_filenames(self,
+ source_filenames,
+ strip_dir=0,
+ output_dir=''):
# Copied from ccompiler.py, extended to return .res as 'object'-file
# for .rc input file
if output_dir is None: output_dir = ''
@@ -343,17 +336,16 @@ class MSVCCompiler (CCompiler) :
base + self.obj_extension))
return obj_names
- # object_filenames ()
-
def compile(self, sources,
output_dir=None, macros=None, include_dirs=None, debug=0,
extra_preargs=None, extra_postargs=None, depends=None):
- if not self.initialized: self.initialize()
- macros, objects, extra_postargs, pp_opts, build = \
- self._setup_compile(output_dir, macros, include_dirs, sources,
- depends, extra_postargs)
+ if not self.initialized:
+ self.initialize()
+ compile_info = self._setup_compile(output_dir, macros, include_dirs,
+ sources, depends, extra_postargs)
+ macros, objects, extra_postargs, pp_opts, build = compile_info
compile_opts = extra_preargs or []
compile_opts.append ('/c')
@@ -382,13 +374,12 @@ class MSVCCompiler (CCompiler) :
input_opt = src
output_opt = "/fo" + obj
try:
- self.spawn ([self.rc] + pp_opts +
- [output_opt] + [input_opt])
- except DistutilsExecError, msg:
- raise CompileError, msg
+ self.spawn([self.rc] + pp_opts +
+ [output_opt] + [input_opt])
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
continue
elif ext in self._mc_extensions:
-
# Compile .MC to .RC file to .RES file.
# * '-h dir' specifies the directory for the
# generated include file
@@ -400,99 +391,95 @@ class MSVCCompiler (CCompiler) :
# we use the source-directory for the include file and
# the build directory for the RC file and message
# resources. This works at least for win32all.
-
- h_dir = os.path.dirname (src)
- rc_dir = os.path.dirname (obj)
+ h_dir = os.path.dirname(src)
+ rc_dir = os.path.dirname(obj)
try:
# first compile .MC to .RC and .H file
- self.spawn ([self.mc] +
- ['-h', h_dir, '-r', rc_dir] + [src])
+ self.spawn([self.mc] +
+ ['-h', h_dir, '-r', rc_dir] + [src])
base, _ = os.path.splitext (os.path.basename (src))
rc_file = os.path.join (rc_dir, base + '.rc')
# then compile .RC to .RES file
- self.spawn ([self.rc] +
- ["/fo" + obj] + [rc_file])
+ self.spawn([self.rc] +
+ ["/fo" + obj] + [rc_file])
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
continue
else:
# how to handle this file?
- raise CompileError (
- "Don't know how to compile %s to %s" % \
- (src, obj))
+ raise CompileError("Don't know how to compile %s to %s"
+ % (src, obj))
output_opt = "/Fo" + obj
try:
- self.spawn ([self.cc] + compile_opts + pp_opts +
- [input_opt, output_opt] +
- extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
+ self.spawn([self.cc] + compile_opts + pp_opts +
+ [input_opt, output_opt] +
+ extra_postargs)
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
return objects
- # compile ()
-
- def create_static_lib (self,
- objects,
- output_libname,
- output_dir=None,
- debug=0,
- target_lang=None):
+ def create_static_lib(self,
+ objects,
+ output_libname,
+ output_dir=None,
+ debug=0,
+ target_lang=None):
- if not self.initialized: self.initialize()
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- output_filename = \
- self.library_filename (output_libname, output_dir=output_dir)
+ if not self.initialized:
+ self.initialize()
+ (objects, output_dir) = self._fix_object_args(objects, output_dir)
+ output_filename = self.library_filename(output_libname,
+ output_dir=output_dir)
- if self._need_link (objects, output_filename):
+ if self._need_link(objects, output_filename):
lib_args = objects + ['/OUT:' + output_filename]
if debug:
- pass # XXX what goes here?
+ pass # XXX what goes here?
try:
- self.spawn ([self.lib] + lib_args)
- except DistutilsExecError, msg:
- raise LibError, msg
-
+ self.spawn([self.lib] + lib_args)
+ except DistutilsExecError as msg:
+ raise LibError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
- # create_static_lib ()
-
- def link (self,
- target_desc,
- objects,
- 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):
-
- if not self.initialized: self.initialize()
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- (libraries, library_dirs, runtime_library_dirs) = \
- self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
+
+ def link(self,
+ target_desc,
+ objects,
+ 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):
+
+ if not self.initialized:
+ self.initialize()
+ (objects, output_dir) = self._fix_object_args(objects, output_dir)
+ fixed_args = self._fix_lib_args(libraries, library_dirs,
+ runtime_library_dirs)
+ (libraries, library_dirs, runtime_library_dirs) = fixed_args
if runtime_library_dirs:
self.warn ("I don't know what to do with 'runtime_library_dirs': "
+ str (runtime_library_dirs))
- lib_opts = gen_lib_options (self,
- library_dirs, runtime_library_dirs,
- libraries)
+ lib_opts = gen_lib_options(self,
+ library_dirs, runtime_library_dirs,
+ libraries)
if output_dir is not None:
- output_filename = os.path.join (output_dir, output_filename)
-
- if self._need_link (objects, output_filename):
+ output_filename = os.path.join(output_dir, output_filename)
+ if self._need_link(objects, output_filename):
if target_desc == CCompiler.EXECUTABLE:
if debug:
ldflags = self.ldflags_shared_debug[1:]
@@ -529,34 +516,32 @@ class MSVCCompiler (CCompiler) :
if extra_postargs:
ld_args.extend(extra_postargs)
- self.mkpath (os.path.dirname (output_filename))
+ self.mkpath(os.path.dirname(output_filename))
try:
- self.spawn ([self.linker] + ld_args)
- except DistutilsExecError, msg:
- raise LinkError, msg
+ self.spawn([self.linker] + ld_args)
+ except DistutilsExecError as msg:
+ raise LinkError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
- # link ()
-
# -- Miscellaneous methods -----------------------------------------
# These are all used by the 'gen_lib_options() function, in
# ccompiler.py.
- def library_dir_option (self, dir):
+ def library_dir_option(self, dir):
return "/LIBPATH:" + dir
- def runtime_library_dir_option (self, dir):
- raise DistutilsPlatformError, \
- "don't know how to set runtime library search path for MSVC++"
+ def runtime_library_dir_option(self, dir):
+ raise DistutilsPlatformError(
+ "don't know how to set runtime library search path for MSVC++")
- def library_option (self, lib):
- return self.library_filename (lib)
+ def library_option(self, lib):
+ return self.library_filename(lib)
- def find_library_file (self, dirs, lib, debug=0):
+ def find_library_file(self, dirs, lib, debug=0):
# Prefer a debugging library if found (and requested), but deal
# with it if we don't have one.
if debug:
@@ -572,8 +557,6 @@ class MSVCCompiler (CCompiler) :
# Oops, didn't find it in *any* of 'dirs'
return None
- # find_library_file ()
-
# Helper methods for using the MSVC registry settings
def find_exe(self, exe):
@@ -585,14 +568,13 @@ class MSVCCompiler (CCompiler) :
absolute path that is known to exist. If none of them work, just
return the original program name, 'exe'.
"""
-
for p in self.__paths:
fn = os.path.join(os.path.abspath(p), exe)
if os.path.isfile(fn):
return fn
# didn't find it; try existing path
- for p in string.split(os.environ['Path'],';'):
+ for p in os.environ['Path'].split(';'):
fn = os.path.join(os.path.abspath(p),exe)
if os.path.isfile(fn):
return fn
@@ -605,7 +587,6 @@ class MSVCCompiler (CCompiler) :
Return a list of strings. The list will be empty if unable to
access the registry or appropriate registry keys not found.
"""
-
if not _can_read_reg:
return []
@@ -621,9 +602,9 @@ class MSVCCompiler (CCompiler) :
d = read_values(base, key)
if d:
if self.__version >= 7:
- return string.split(self.__macros.sub(d[path]), ";")
+ return self.__macros.sub(d[path]).split(";")
else:
- return string.split(d[path], ";")
+ return d[path].split(";")
# MSVC 6 seems to create the registry entries we need only when
# the GUI is run.
if self.__version == 6:
@@ -648,7 +629,7 @@ class MSVCCompiler (CCompiler) :
else:
p = self.get_msvc_paths(name)
if p:
- os.environ[name] = string.join(p, ';')
+ os.environ[name] = ';'.join(p)
if get_build_version() >= 8.0:
diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py
index 7306099f6b6..f58c55f9024 100644
--- a/Lib/distutils/spawn.py
+++ b/Lib/distutils/spawn.py
@@ -6,8 +6,6 @@ Also provides the 'find_executable()' to search the path for a given
executable name.
"""
-__revision__ = "$Id$"
-
import sys
import os
@@ -37,8 +35,8 @@ def spawn(cmd, search_path=1, verbose=0, dry_run=0):
elif os.name == 'os2':
_spawn_os2(cmd, search_path, dry_run=dry_run)
else:
- raise DistutilsPlatformError, \
- "don't know how to spawn programs on platform '%s'" % os.name
+ raise DistutilsPlatformError(
+ "don't know how to spawn programs on platform '%s'" % os.name)
def _nt_quote_args(args):
"""Quote command-line arguments for DOS/Windows conventions.
@@ -67,14 +65,14 @@ def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0):
# spawn for NT requires a full path to the .exe
try:
rc = os.spawnv(os.P_WAIT, executable, cmd)
- except OSError, exc:
+ except OSError as exc:
# this seems to happen when the command isn't found
- raise DistutilsExecError, \
- "command '%s' failed: %s" % (cmd[0], exc[-1])
+ raise DistutilsExecError(
+ "command '%s' failed: %s" % (cmd[0], exc.args[-1]))
if rc != 0:
# and this reflects the command running but failing
- raise DistutilsExecError, \
- "command '%s' failed with exit status %d" % (cmd[0], rc)
+ raise DistutilsExecError(
+ "command '%s' failed with exit status %d" % (cmd[0], rc))
def _spawn_os2(cmd, search_path=1, verbose=0, dry_run=0):
executable = cmd[0]
@@ -86,15 +84,15 @@ def _spawn_os2(cmd, search_path=1, verbose=0, dry_run=0):
# spawnv for OS/2 EMX requires a full path to the .exe
try:
rc = os.spawnv(os.P_WAIT, executable, cmd)
- except OSError, exc:
+ except OSError as exc:
# this seems to happen when the command isn't found
- raise DistutilsExecError, \
- "command '%s' failed: %s" % (cmd[0], exc[-1])
+ raise DistutilsExecError(
+ "command '%s' failed: %s" % (cmd[0], exc.args[-1]))
if rc != 0:
# and this reflects the command running but failing
log.debug("command '%s' failed with exit status %d" % (cmd[0], rc))
- raise DistutilsExecError, \
- "command '%s' failed with exit status %d" % (cmd[0], rc)
+ raise DistutilsExecError(
+ "command '%s' failed with exit status %d" % (cmd[0], rc))
if sys.platform == 'darwin':
from distutils import sysconfig
@@ -129,50 +127,46 @@ def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0):
exec_fn = search_path and os.execvpe or os.execve
exec_args.append(env)
pid = os.fork()
-
- if pid == 0: # in the child
+ if pid == 0: # in the child
try:
exec_fn(*exec_args)
- except OSError, e:
- sys.stderr.write("unable to execute %s: %s\n" %
- (cmd[0], e.strerror))
+ except OSError as e:
+ sys.stderr.write("unable to execute %s: %s\n"
+ % (cmd[0], e.strerror))
os._exit(1)
sys.stderr.write("unable to execute %s for unknown reasons" % cmd[0])
os._exit(1)
- else: # in the parent
+ else: # in the parent
# Loop until the child either exits or is terminated by a signal
# (ie. keep waiting if it's merely stopped)
- while 1:
+ while True:
try:
pid, status = os.waitpid(pid, 0)
- except OSError, exc:
+ except OSError as exc:
import errno
if exc.errno == errno.EINTR:
continue
- raise DistutilsExecError, \
- "command '%s' failed: %s" % (cmd[0], exc[-1])
+ raise DistutilsExecError(
+ "command '%s' failed: %s" % (cmd[0], exc.args[-1]))
if os.WIFSIGNALED(status):
- raise DistutilsExecError, \
- "command '%s' terminated by signal %d" % \
- (cmd[0], os.WTERMSIG(status))
-
+ raise DistutilsExecError(
+ "command '%s' terminated by signal %d"
+ % (cmd[0], os.WTERMSIG(status)))
elif os.WIFEXITED(status):
exit_status = os.WEXITSTATUS(status)
if exit_status == 0:
return # hey, it succeeded!
else:
- raise DistutilsExecError, \
- "command '%s' failed with exit status %d" % \
- (cmd[0], exit_status)
-
+ raise DistutilsExecError(
+ "command '%s' failed with exit status %d"
+ % (cmd[0], exit_status))
elif os.WIFSTOPPED(status):
continue
-
else:
- raise DistutilsExecError, \
- "unknown error executing '%s': termination status %d" % \
- (cmd[0], status)
+ raise DistutilsExecError(
+ "unknown error executing '%s': termination status %d"
+ % (cmd[0], status))
def find_executable(executable, path=None):
"""Tries to find 'executable' in the directories listed in 'path'.
@@ -182,6 +176,7 @@ def find_executable(executable, path=None):
"""
if path is None:
path = os.environ['PATH']
+
paths = path.split(os.pathsep)
base, ext = os.path.splitext(executable)
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 4b193b2703c..16902ca920a 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -9,14 +9,11 @@ Written by: Fred L. Drake, Jr.
Email: <fdrake@acm.org>
"""
-__revision__ = "$Id$"
-
import os
import re
-import string
import sys
-from distutils.errors import DistutilsPlatformError
+from .errors import DistutilsPlatformError
# These are needed in a couple of spots, so just compute them once.
PREFIX = os.path.normpath(sys.prefix)
@@ -49,6 +46,17 @@ def _python_build():
return False
python_build = _python_build()
+# Calculate the build qualifier flags if they are defined. Adding the flags
+# to the include and lib directories only makes sense for an installation, not
+# an in-source build.
+build_flags = ''
+try:
+ if not python_build:
+ build_flags = sys.abiflags
+except AttributeError:
+ # It's not a configure-based build, so the sys module doesn't have
+ # this attribute, which is fine.
+ pass
def get_python_version():
"""Return a string containing the major and minor Python version,
@@ -71,21 +79,21 @@ def get_python_inc(plat_specific=0, prefix=None):
"""
if prefix is None:
prefix = plat_specific and EXEC_PREFIX or PREFIX
-
if os.name == "posix":
if python_build:
- buildir = os.path.dirname(sys.executable)
+ # Assume the executable is in the build directory. The
+ # pyconfig.h file should be in the same directory. Since
+ # the build directory may not be the source directory, we
+ # must use "srcdir" from the makefile to find the "Include"
+ # directory.
+ base = os.path.dirname(os.path.abspath(sys.executable))
if plat_specific:
- # python.h is located in the buildir
- inc_dir = buildir
+ return base
else:
- # the source dir is relative to the buildir
- srcdir = os.path.abspath(os.path.join(buildir,
- get_config_var('srcdir')))
- # Include is located in the srcdir
- inc_dir = os.path.join(srcdir, "Include")
- return inc_dir
- return os.path.join(prefix, "include", "python" + get_python_version())
+ incdir = os.path.join(get_config_var('srcdir'), 'Include')
+ return os.path.normpath(incdir)
+ python_dir = 'python' + get_python_version() + build_flags
+ return os.path.join(prefix, "include", python_dir)
elif os.name == "nt":
return os.path.join(prefix, "include")
elif os.name == "os2":
@@ -120,7 +128,6 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
return libpython
else:
return os.path.join(libpython, "site-packages")
-
elif os.name == "nt":
if standard_lib:
return os.path.join(prefix, "Lib")
@@ -129,13 +136,11 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
return prefix
else:
return os.path.join(prefix, "Lib", "site-packages")
-
elif os.name == "os2":
if standard_lib:
return os.path.join(prefix, "Lib")
else:
return os.path.join(prefix, "Lib", "site-packages")
-
else:
raise DistutilsPlatformError(
"I don't know where Python installs its library "
@@ -152,8 +157,7 @@ def customize_compiler(compiler):
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')
+ 'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS')
newcc = None
if 'CC' in os.environ:
@@ -245,8 +249,9 @@ def get_makefile_filename():
"""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")
+ lib_dir = get_python_lib(plat_specific=0, standard_lib=1)
+ config_file = 'config-{}{}'.format(get_python_version(), build_flags)
+ return os.path.join(lib_dir, config_file, 'Makefile')
def parse_config_h(fp, g=None):
@@ -261,7 +266,7 @@ def parse_config_h(fp, g=None):
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 1:
+ while True:
line = fp.readline()
if not line:
break
@@ -292,16 +297,16 @@ def parse_makefile(fn, g=None):
used instead of a new dictionary.
"""
from distutils.text_file import TextFile
- fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
+ fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape")
if g is None:
g = {}
done = {}
notdone = {}
- while 1:
+ while True:
line = fp.readline()
- if line is None: # eof
+ if line is None: # eof
break
m = _variable_rx.match(line)
if m:
@@ -321,9 +326,15 @@ def parse_makefile(fn, g=None):
else:
done[n] = v
+ # Variables with a 'PY_' prefix in the makefile. These need to
+ # be made available without that prefix through sysconfig.
+ # Special care is needed to ensure that variable expansion works, even
+ # if the expansion uses the name without a prefix.
+ renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
+
# do variable interpolation here
while notdone:
- for name in notdone.keys():
+ for name in list(notdone):
value = notdone[name]
m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
if m:
@@ -337,6 +348,16 @@ def parse_makefile(fn, g=None):
elif n in os.environ:
# do it like make: fall back to environment
item = os.environ[n]
+
+ elif n in renamed_variables:
+ if name.startswith('PY_') and name[3:] in renamed_variables:
+ item = ""
+
+ elif 'PY_' + n in notdone:
+ found = False
+
+ else:
+ item = str(done['PY_' + n])
else:
done[n] = item = ""
if found:
@@ -351,6 +372,13 @@ def parse_makefile(fn, g=None):
else:
done[name] = value
del notdone[name]
+
+ if name.startswith('PY_') \
+ and name[3:] in renamed_variables:
+
+ name = name[3:]
+ if name not in done:
+ done[name] = value
else:
# bogus variable reference; just drop it since we can't deal
del notdone[name]
@@ -382,7 +410,7 @@ def expand_makefile_vars(s, vars):
# 'parse_makefile()', which takes care of such expansions eagerly,
# according to make's variable expansion semantics.
- while 1:
+ while True:
m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
if m:
(beg, end) = m.span()
@@ -401,7 +429,7 @@ def _init_posix():
try:
filename = get_makefile_filename()
parse_makefile(filename, g)
- except IOError, msg:
+ 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
@@ -411,8 +439,9 @@ def _init_posix():
# load the installed pyconfig.h:
try:
filename = get_config_h_filename()
- parse_config_h(file(filename), g)
- except IOError, msg:
+ with open(filename) as file:
+ parse_config_h(file, 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
@@ -436,24 +465,6 @@ def _init_posix():
g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp)
- elif sys.platform == 'beos':
- # Linker script is in the config directory. In the Makefile it is
- # relative to the srcdir, which after installation no longer makes
- # sense.
- python_lib = get_python_lib(standard_lib=1)
- linkerscript_path = string.split(g['LDSHARED'])[0]
- linkerscript_name = os.path.basename(linkerscript_path)
- linkerscript = os.path.join(python_lib, 'config',
- linkerscript_name)
-
- # XXX this isn't the right place to do this: adding the Python
- # library to the link, if needed, should be in the "build_ext"
- # command. (It's also needed for non-MS compilers on Windows, and
- # it's taken care of for them by the 'build_ext.get_libraries()'
- # method.)
- g['LDSHARED'] = ("%s -L%s/lib -lpython%s" %
- (linkerscript, PREFIX, get_python_version()))
-
global _config_vars
_config_vars = g
@@ -518,6 +529,20 @@ def get_config_vars(*args):
_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])
@@ -527,12 +552,12 @@ def get_config_vars(*args):
# 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', 'LDSHARED',
+ 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 = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII)
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
_config_vars[key] = flags
@@ -546,7 +571,7 @@ def get_config_vars(*args):
if 'ARCHFLAGS' in os.environ:
arch = os.environ['ARCHFLAGS']
- for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
+ for key in ('LDFLAGS', 'BASECFLAGS',
# a number of derived variables. These need to be
# patched up as well.
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
@@ -556,29 +581,6 @@ def get_config_vars(*args):
flags = flags + ' ' + arch
_config_vars[key] = flags
- # If we're on OSX 10.5 or later and the user tries to
- # compiles an extension using an SDK that is not present
- # on the current machine it is better to not use an SDK
- # than to fail.
- #
- # The major usecase for this is users using a Python.org
- # binary installer on OSX 10.6: that installer uses
- # the 10.4u SDK, but that SDK is not installed by default
- # when you install Xcode.
- #
- m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS'])
- if m is not None:
- sdk = m.group(1)
- if not os.path.exists(sdk):
- for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
- # a number of derived variables. These need to be
- # patched up as well.
- 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
-
- flags = _config_vars[key]
- flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
- _config_vars[key] = flags
-
if args:
vals = []
for name in args:
diff --git a/Lib/distutils/tests/__init__.py b/Lib/distutils/tests/__init__.py
index 697ff840456..1b939cbd5db 100644
--- a/Lib/distutils/tests/__init__.py
+++ b/Lib/distutils/tests/__init__.py
@@ -15,7 +15,7 @@ by import rather than matching pre-defined names.
import os
import sys
import unittest
-from test.test_support import run_unittest
+from test.support import run_unittest
here = os.path.dirname(__file__) or os.curdir
diff --git a/Lib/distutils/tests/setuptools_build_ext.py b/Lib/distutils/tests/setuptools_build_ext.py
deleted file mode 100644
index 21fa9e8f439..00000000000
--- a/Lib/distutils/tests/setuptools_build_ext.py
+++ /dev/null
@@ -1,287 +0,0 @@
-from distutils.command.build_ext import build_ext as _du_build_ext
-try:
- # Attempt to use Pyrex for building extensions, if available
- from Pyrex.Distutils.build_ext import build_ext as _build_ext
-except ImportError:
- _build_ext = _du_build_ext
-
-import os, sys
-from distutils.file_util import copy_file
-
-from distutils.tests.setuptools_extension import Library
-
-from distutils.ccompiler import new_compiler
-from distutils.sysconfig import customize_compiler, get_config_var
-get_config_var("LDSHARED") # make sure _config_vars is initialized
-from distutils.sysconfig import _config_vars
-from distutils import log
-from distutils.errors import *
-
-have_rtld = False
-use_stubs = False
-libtype = 'shared'
-
-if sys.platform == "darwin":
- use_stubs = True
-elif os.name != 'nt':
- try:
- from dl import RTLD_NOW
- have_rtld = True
- use_stubs = True
- except ImportError:
- pass
-
-def if_dl(s):
- if have_rtld:
- return s
- return ''
-
-
-
-
-
-
-class build_ext(_build_ext):
- def run(self):
- """Build extensions in build directory, then copy if --inplace"""
- old_inplace, self.inplace = self.inplace, 0
- _build_ext.run(self)
- self.inplace = old_inplace
- if old_inplace:
- self.copy_extensions_to_source()
-
- def copy_extensions_to_source(self):
- build_py = self.get_finalized_command('build_py')
- for ext in self.extensions:
- fullname = self.get_ext_fullname(ext.name)
- filename = self.get_ext_filename(fullname)
- modpath = fullname.split('.')
- package = '.'.join(modpath[:-1])
- package_dir = build_py.get_package_dir(package)
- dest_filename = os.path.join(package_dir,os.path.basename(filename))
- src_filename = os.path.join(self.build_lib,filename)
-
- # Always copy, even if source is older than destination, to ensure
- # that the right extensions for the current Python/platform are
- # used.
- copy_file(
- src_filename, dest_filename, verbose=self.verbose,
- dry_run=self.dry_run
- )
- if ext._needs_stub:
- self.write_stub(package_dir or os.curdir, ext, True)
-
-
- if _build_ext is not _du_build_ext and not hasattr(_build_ext,'pyrex_sources'):
- # Workaround for problems using some Pyrex versions w/SWIG and/or 2.4
- def swig_sources(self, sources, *otherargs):
- # first do any Pyrex processing
- sources = _build_ext.swig_sources(self, sources) or sources
- # Then do any actual SWIG stuff on the remainder
- return _du_build_ext.swig_sources(self, sources, *otherargs)
-
-
-
- def get_ext_filename(self, fullname):
- filename = _build_ext.get_ext_filename(self,fullname)
- ext = self.ext_map[fullname]
- if isinstance(ext,Library):
- fn, ext = os.path.splitext(filename)
- return self.shlib_compiler.library_filename(fn,libtype)
- elif use_stubs and ext._links_to_dynamic:
- d,fn = os.path.split(filename)
- return os.path.join(d,'dl-'+fn)
- else:
- return filename
-
- def initialize_options(self):
- _build_ext.initialize_options(self)
- self.shlib_compiler = None
- self.shlibs = []
- self.ext_map = {}
-
- def finalize_options(self):
- _build_ext.finalize_options(self)
- self.extensions = self.extensions or []
- self.check_extensions_list(self.extensions)
- self.shlibs = [ext for ext in self.extensions
- if isinstance(ext,Library)]
- if self.shlibs:
- self.setup_shlib_compiler()
- for ext in self.extensions:
- ext._full_name = self.get_ext_fullname(ext.name)
- for ext in self.extensions:
- fullname = ext._full_name
- self.ext_map[fullname] = ext
- ltd = ext._links_to_dynamic = \
- self.shlibs and self.links_to_dynamic(ext) or False
- ext._needs_stub = ltd and use_stubs and not isinstance(ext,Library)
- filename = ext._file_name = self.get_ext_filename(fullname)
- libdir = os.path.dirname(os.path.join(self.build_lib,filename))
- if ltd and libdir not in ext.library_dirs:
- ext.library_dirs.append(libdir)
- if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs:
- ext.runtime_library_dirs.append(os.curdir)
-
- def setup_shlib_compiler(self):
- compiler = self.shlib_compiler = new_compiler(
- compiler=self.compiler, dry_run=self.dry_run, force=self.force
- )
- if sys.platform == "darwin":
- tmp = _config_vars.copy()
- try:
- # XXX Help! I don't have any idea whether these are right...
- _config_vars['LDSHARED'] = "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup"
- _config_vars['CCSHARED'] = " -dynamiclib"
- _config_vars['SO'] = ".dylib"
- customize_compiler(compiler)
- finally:
- _config_vars.clear()
- _config_vars.update(tmp)
- else:
- customize_compiler(compiler)
-
- if self.include_dirs is not None:
- compiler.set_include_dirs(self.include_dirs)
- if self.define is not None:
- # 'define' option is a list of (name,value) tuples
- for (name,value) in self.define:
- compiler.define_macro(name, value)
- if self.undef is not None:
- for macro in self.undef:
- compiler.undefine_macro(macro)
- if self.libraries is not None:
- compiler.set_libraries(self.libraries)
- if self.library_dirs is not None:
- compiler.set_library_dirs(self.library_dirs)
- if self.rpath is not None:
- compiler.set_runtime_library_dirs(self.rpath)
- if self.link_objects is not None:
- compiler.set_link_objects(self.link_objects)
-
- # hack so distutils' build_extension() builds a library instead
- compiler.link_shared_object = link_shared_object.__get__(compiler)
-
-
-
- def get_export_symbols(self, ext):
- if isinstance(ext,Library):
- return ext.export_symbols
- return _build_ext.get_export_symbols(self,ext)
-
- def build_extension(self, ext):
- _compiler = self.compiler
- try:
- if isinstance(ext,Library):
- self.compiler = self.shlib_compiler
- _build_ext.build_extension(self,ext)
- if ext._needs_stub:
- self.write_stub(
- self.get_finalized_command('build_py').build_lib, ext
- )
- finally:
- self.compiler = _compiler
-
- def links_to_dynamic(self, ext):
- """Return true if 'ext' links to a dynamic lib in the same package"""
- # XXX this should check to ensure the lib is actually being built
- # XXX as dynamic, and not just using a locally-found version or a
- # XXX static-compiled version
- libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])
- pkg = '.'.join(ext._full_name.split('.')[:-1]+[''])
- for libname in ext.libraries:
- if pkg+libname in libnames: return True
- return False
-
- def get_outputs(self):
- outputs = _build_ext.get_outputs(self)
- optimize = self.get_finalized_command('build_py').optimize
- for ext in self.extensions:
- if ext._needs_stub:
- base = os.path.join(self.build_lib, *ext._full_name.split('.'))
- outputs.append(base+'.py')
- outputs.append(base+'.pyc')
- if optimize:
- outputs.append(base+'.pyo')
- return outputs
-
- def write_stub(self, output_dir, ext, compile=False):
- log.info("writing stub loader for %s to %s",ext._full_name, output_dir)
- stub_file = os.path.join(output_dir, *ext._full_name.split('.'))+'.py'
- if compile and os.path.exists(stub_file):
- raise DistutilsError(stub_file+" already exists! Please delete.")
- if not self.dry_run:
- f = open(stub_file,'w')
- f.write('\n'.join([
- "def __bootstrap__():",
- " global __bootstrap__, __file__, __loader__",
- " import sys, os, pkg_resources, imp"+if_dl(", dl"),
- " __file__ = pkg_resources.resource_filename(__name__,%r)"
- % os.path.basename(ext._file_name),
- " del __bootstrap__",
- " if '__loader__' in globals():",
- " del __loader__",
- if_dl(" old_flags = sys.getdlopenflags()"),
- " old_dir = os.getcwd()",
- " try:",
- " os.chdir(os.path.dirname(__file__))",
- if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"),
- " imp.load_dynamic(__name__,__file__)",
- " finally:",
- if_dl(" sys.setdlopenflags(old_flags)"),
- " os.chdir(old_dir)",
- "__bootstrap__()",
- "" # terminal \n
- ]))
- f.close()
- if compile:
- from distutils.util import byte_compile
- byte_compile([stub_file], optimize=0,
- force=True, dry_run=self.dry_run)
- optimize = self.get_finalized_command('install_lib').optimize
- if optimize > 0:
- byte_compile([stub_file], optimize=optimize,
- force=True, dry_run=self.dry_run)
- if os.path.exists(stub_file) and not self.dry_run:
- os.unlink(stub_file)
-
-
-if use_stubs or os.name=='nt':
- # Build shared libraries
- #
- def link_shared_object(self, objects, output_libname, 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
- ): self.link(
- self.SHARED_LIBRARY, objects, output_libname,
- output_dir, libraries, library_dirs, runtime_library_dirs,
- export_symbols, debug, extra_preargs, extra_postargs,
- build_temp, target_lang
- )
-else:
- # Build static libraries everywhere else
- libtype = 'static'
-
- def link_shared_object(self, objects, output_libname, 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
- ):
- # XXX we need to either disallow these attrs on Library instances,
- # or warn/abort here if set, or something...
- #libraries=None, library_dirs=None, runtime_library_dirs=None,
- #export_symbols=None, extra_preargs=None, extra_postargs=None,
- #build_temp=None
-
- assert output_dir is None # distutils build_ext doesn't pass this
- output_dir,filename = os.path.split(output_libname)
- basename, ext = os.path.splitext(filename)
- if self.library_filename("x").startswith('lib'):
- # strip 'lib' prefix; this is kludgy if some platform uses
- # a different prefix
- basename = basename[3:]
-
- self.create_static_lib(
- objects, basename, output_dir, debug, target_lang
- )
diff --git a/Lib/distutils/tests/setuptools_extension.py b/Lib/distutils/tests/setuptools_extension.py
deleted file mode 100644
index ec6b690cdb3..00000000000
--- a/Lib/distutils/tests/setuptools_extension.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from distutils.core import Extension as _Extension
-from distutils.core import Distribution as _Distribution
-
-def _get_unpatched(cls):
- """Protect against re-patching the distutils if reloaded
-
- Also ensures that no other distutils extension monkeypatched the distutils
- first.
- """
- while cls.__module__.startswith('setuptools'):
- cls, = cls.__bases__
- if not cls.__module__.startswith('distutils'):
- raise AssertionError(
- "distutils has already been patched by %r" % cls
- )
- return cls
-
-_Distribution = _get_unpatched(_Distribution)
-_Extension = _get_unpatched(_Extension)
-
-try:
- from Pyrex.Distutils.build_ext import build_ext
-except ImportError:
- have_pyrex = False
-else:
- have_pyrex = True
-
-
-class Extension(_Extension):
- """Extension that uses '.c' files in place of '.pyx' files"""
-
- if not have_pyrex:
- # convert .pyx extensions to .c
- def __init__(self,*args,**kw):
- _Extension.__init__(self,*args,**kw)
- sources = []
- for s in self.sources:
- if s.endswith('.pyx'):
- sources.append(s[:-3]+'c')
- else:
- sources.append(s)
- self.sources = sources
-
-class Library(Extension):
- """Just like a regular Extension, but built as a library instead"""
-
-import sys, distutils.core, distutils.extension
-distutils.core.Extension = Extension
-distutils.extension.Extension = Extension
-if 'distutils.command.build_ext' in sys.modules:
- sys.modules['distutils.command.build_ext'].Extension = Extension
diff --git a/Lib/distutils/tests/support.py b/Lib/distutils/tests/support.py
index 4e6058d0ec0..84d92323284 100644
--- a/Lib/distutils/tests/support.py
+++ b/Lib/distutils/tests/support.py
@@ -6,25 +6,16 @@ import tempfile
import unittest
import sysconfig
from copy import deepcopy
-import warnings
from distutils import log
from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
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):
def setUp(self):
- super(LoggingSilencer, self).setUp()
+ super().setUp()
self.threshold = log.set_threshold(log.FATAL)
# catching warnings
# when log will be replaced by logging
@@ -36,7 +27,7 @@ class LoggingSilencer(object):
def tearDown(self):
log.set_threshold(self.threshold)
log.Log._log = self._old_log
- super(LoggingSilencer, self).tearDown()
+ super().tearDown()
def _log(self, level, msg, args):
if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
@@ -62,7 +53,7 @@ class TempdirManager(object):
"""
def setUp(self):
- super(TempdirManager, self).setUp()
+ super().setUp()
self.old_cwd = os.getcwd()
self.tempdirs = []
@@ -70,7 +61,7 @@ class TempdirManager(object):
# Restore working dir, for Solaris and derivatives, where rmdir()
# on the current directory fails.
os.chdir(self.old_cwd)
- super(TempdirManager, self).tearDown()
+ super().tearDown()
while self.tempdirs:
d = self.tempdirs.pop()
shutil.rmtree(d, os.name in ('nt', 'cygwin'))
@@ -138,7 +129,7 @@ class EnvironGuard(object):
if os.environ.get(key) != value:
os.environ[key] = value
- for key in os.environ.keys():
+ for key in tuple(os.environ.keys()):
if key not in self.old_environ:
del os.environ[key]
@@ -165,8 +156,6 @@ def copy_xxmodule_c(directory):
def _get_xxmodule_path():
- # FIXME when run from regrtest, srcdir seems to be '.', which does not help
- # us find the xxmodule.c file
srcdir = sysconfig.get_config_var('srcdir')
candidates = [
# use installed copy if available
@@ -186,10 +175,9 @@ def _get_xxmodule_path():
def fixup_build_ext(cmd):
"""Function needed to make build_ext tests pass.
- When Python was build with --enable-shared on Unix, -L. is not good
- enough to find the libpython<blah>.so. This is because regrtest runs
- it under a tempdir, not in the top level where the .so lives. By the
- time we've gotten here, Python's already been chdir'd to the tempdir.
+ When Python was built with --enable-shared on Unix, -L. is not enough to
+ find libpython<blah>.so, because regrtest runs in a tempdir, not in the
+ source directory where the .so lives.
When Python was built with in debug mode on Windows, build_ext commands
need their debug attribute set, and it is not done automatically for
diff --git a/Lib/distutils/tests/test_archive_util.py b/Lib/distutils/tests/test_archive_util.py
index f01cec32632..8edfab49f87 100644
--- a/Lib/distutils/tests/test_archive_util.py
+++ b/Lib/distutils/tests/test_archive_util.py
@@ -1,27 +1,17 @@
-# -*- coding: utf-8 -*-
"""Tests for distutils.archive_util."""
-__revision__ = "$Id$"
-
import unittest
import os
-import sys
import tarfile
from os.path import splitdrive
import warnings
+from distutils import archive_util
from distutils.archive_util import (check_archive_formats, make_tarball,
make_zipfile, make_archive,
ARCHIVE_FORMATS)
from distutils.spawn import find_executable, spawn
from distutils.tests import support
-from test.test_support import check_warnings, run_unittest
-
-try:
- import grp
- import pwd
- UID_GID_SUPPORT = True
-except ImportError:
- UID_GID_SUPPORT = False
+from test.support import check_warnings, run_unittest, patch
try:
import zipfile
@@ -29,34 +19,19 @@ try:
except ImportError:
ZIP_SUPPORT = find_executable('zip')
-# some tests will fail if zlib is not available
try:
import zlib
+ ZLIB_SUPPORT = True
except ImportError:
- zlib = None
-
-def can_fs_encode(filename):
- """
- Return True if the filename can be saved in the file system.
- """
- if os.path.supports_unicode_filenames:
- return True
- try:
- filename.encode(sys.getfilesystemencoding())
- except UnicodeEncodeError:
- return False
- return True
+ ZLIB_SUPPORT = False
class ArchiveUtilTestCase(support.TempdirManager,
support.LoggingSilencer,
unittest.TestCase):
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_make_tarball(self):
- self._make_tarball('archive')
-
- def _make_tarball(self, target_name):
# creating something to tar
tmpdir = self.mkdtemp()
self.write_file([tmpdir, 'file1'], 'xxx')
@@ -66,9 +41,9 @@ class ArchiveUtilTestCase(support.TempdirManager,
tmpdir2 = self.mkdtemp()
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, target_name)
+ base_name = os.path.join(tmpdir2, 'archive')
# working with relative paths to avoid tar warnings
old_dir = os.getcwd()
@@ -83,7 +58,7 @@ class ArchiveUtilTestCase(support.TempdirManager,
self.assertTrue(os.path.exists(tarball))
# trying an uncompressed one
- base_name = os.path.join(tmpdir2, target_name)
+ base_name = os.path.join(tmpdir2, 'archive')
old_dir = os.getcwd()
os.chdir(tmpdir)
try:
@@ -116,9 +91,9 @@ class ArchiveUtilTestCase(support.TempdirManager,
base_name = os.path.join(tmpdir2, 'archive')
return tmpdir, tmpdir2, base_name
- @unittest.skipUnless(zlib, "Requires zlib")
- @unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
- 'Need the tar command to run')
+ @unittest.skipUnless(find_executable('tar') and find_executable('gzip')
+ and ZLIB_SUPPORT,
+ 'Need the tar, gzip and zlib command to run')
def test_tarfile_vs_tar(self):
tmpdir, tmpdir2, base_name = self._create_files()
old_dir = os.getcwd()
@@ -202,8 +177,8 @@ class ArchiveUtilTestCase(support.TempdirManager,
self.assertTrue(not os.path.exists(tarball))
self.assertEqual(len(w.warnings), 1)
- @unittest.skipUnless(zlib, "Requires zlib")
- @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
+ @unittest.skipUnless(ZIP_SUPPORT and ZLIB_SUPPORT,
+ 'Need zip and zlib support to run')
def test_make_zipfile(self):
# creating something to tar
tmpdir = self.mkdtemp()
@@ -216,6 +191,29 @@ class ArchiveUtilTestCase(support.TempdirManager,
# check if the compressed tarball was created
tarball = base_name + '.zip'
+ self.assertTrue(os.path.exists(tarball))
+
+ @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
+ def test_make_zipfile_no_zlib(self):
+ patch(self, archive_util.zipfile, 'zlib', None) # force zlib ImportError
+
+ called = []
+ zipfile_class = zipfile.ZipFile
+ def fake_zipfile(*a, **kw):
+ if kw.get('compression', None) == zipfile.ZIP_STORED:
+ called.append((a, kw))
+ return zipfile_class(*a, **kw)
+
+ patch(self, archive_util.zipfile, 'ZipFile', fake_zipfile)
+
+ # create something to tar and compress
+ tmpdir, tmpdir2, base_name = self._create_files()
+ make_zipfile(base_name, tmpdir)
+
+ tarball = base_name + '.zip'
+ self.assertEqual(called,
+ [((tarball, "w"), {'compression': zipfile.ZIP_STORED})])
+ self.assertTrue(os.path.exists(tarball))
def test_check_archive_formats(self):
self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']),
@@ -227,59 +225,6 @@ class ArchiveUtilTestCase(support.TempdirManager,
base_name = os.path.join(tmpdir, 'archive')
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.assertEqual(member.uid, 0)
- self.assertEqual(member.gid, 0)
- finally:
- archive.close()
-
def test_make_archive_cwd(self):
current_dir = os.getcwd()
def _breaks(*args, **kw):
@@ -294,33 +239,6 @@ class ArchiveUtilTestCase(support.TempdirManager,
finally:
del ARCHIVE_FORMATS['xxx']
- @unittest.skipUnless(zlib, "requires zlib")
- def test_make_tarball_unicode(self):
- """
- Mirror test_make_tarball, except filename is unicode.
- """
- self._make_tarball(u'archive')
-
- @unittest.skipUnless(zlib, "requires zlib")
- @unittest.skipUnless(can_fs_encode(u'Ã¥rchiv'),
- 'File system cannot handle this filename')
- def test_make_tarball_unicode_latin1(self):
- """
- Mirror test_make_tarball, except filename is unicode and contains
- latin characters.
- """
- self._make_tarball(u'Ã¥rchiv') # note this isn't a real word
-
- @unittest.skipUnless(zlib, "requires zlib")
- @unittest.skipUnless(can_fs_encode(u'ã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–'),
- 'File system cannot handle this filename')
- def test_make_tarball_unicode_extended(self):
- """
- Mirror test_make_tarball, except filename is unicode and contains
- characters outside the latin charset.
- """
- self._make_tarball(u'ã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–') # japanese for archive
-
def test_suite():
return unittest.makeSuite(ArchiveUtilTestCase)
diff --git a/Lib/distutils/tests/test_bdist.py b/Lib/distutils/tests/test_bdist.py
index 121d0992dba..503a6e857df 100644
--- a/Lib/distutils/tests/test_bdist.py
+++ b/Lib/distutils/tests/test_bdist.py
@@ -1,8 +1,7 @@
"""Tests for distutils.command.bdist."""
import os
import unittest
-
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.command.bdist import bdist
from distutils.tests import support
@@ -34,8 +33,7 @@ class BuildTestCase(support.TempdirManager,
cmd.ensure_finalized()
dist.command_obj['bdist'] = cmd
- names = ['bdist_dumb', 'bdist_wininst']
- # bdist_rpm does not support --skip-build
+ names = ['bdist_dumb', 'bdist_wininst'] # bdist_rpm does not support --skip-build
if os.name == 'nt':
names.append('bdist_msi')
diff --git a/Lib/distutils/tests/test_bdist_dumb.py b/Lib/distutils/tests/test_bdist_dumb.py
index 3378f49ea09..1037d8216ec 100644
--- a/Lib/distutils/tests/test_bdist_dumb.py
+++ b/Lib/distutils/tests/test_bdist_dumb.py
@@ -1,17 +1,11 @@
"""Tests for distutils.command.bdist_dumb."""
import os
+import imp
import sys
import zipfile
import unittest
-from test.test_support import run_unittest
-
-# 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.command.bdist_dumb import bdist_dumb
@@ -26,6 +20,13 @@ setup(name='foo', version='0.1', py_modules=['foo'],
"""
+try:
+ import zlib
+ ZLIB_SUPPORT = True
+except ImportError:
+ ZLIB_SUPPORT = False
+
+
class BuildDumbTestCase(support.TempdirManager,
support.LoggingSilencer,
support.EnvironGuard,
@@ -42,7 +43,7 @@ class BuildDumbTestCase(support.TempdirManager,
sys.argv[:] = self.old_sys_argv[1]
super(BuildDumbTestCase, self).tearDown()
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_simple_built(self):
# let's create a simple package
@@ -88,24 +89,10 @@ class BuildDumbTestCase(support.TempdirManager,
contents = sorted(os.path.basename(fn) for fn in contents)
wanted = ['foo-0.1-py%s.%s.egg-info' % sys.version_info[:2],
- 'foo.py', 'foo.pyc']
+ 'foo.%s.pyc' % imp.get_tag(),
+ 'foo.py']
self.assertEqual(contents, sorted(wanted))
- def test_finalize_options(self):
- pkg_dir, dist = self.create_dist()
- os.chdir(pkg_dir)
- cmd = bdist_dumb(dist)
- self.assertEqual(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.assertEqual(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.assertEqual(cmd.format, default)
-
def test_suite():
return unittest.makeSuite(BuildDumbTestCase)
diff --git a/Lib/distutils/tests/test_bdist_msi.py b/Lib/distutils/tests/test_bdist_msi.py
index f98b7a2199a..15d8bdff2b4 100644
--- a/Lib/distutils/tests/test_bdist_msi.py
+++ b/Lib/distutils/tests/test_bdist_msi.py
@@ -1,7 +1,7 @@
"""Tests for distutils.command.bdist_msi."""
import sys
import unittest
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.tests import support
diff --git a/Lib/distutils/tests/test_bdist_rpm.py b/Lib/distutils/tests/test_bdist_rpm.py
index 37d89155c7e..ab7a1bf24e7 100644
--- a/Lib/distutils/tests/test_bdist_rpm.py
+++ b/Lib/distutils/tests/test_bdist_rpm.py
@@ -5,8 +5,7 @@ import sys
import os
import tempfile
import shutil
-
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.core import Distribution
from distutils.command.bdist_rpm import bdist_rpm
diff --git a/Lib/distutils/tests/test_bdist_wininst.py b/Lib/distutils/tests/test_bdist_wininst.py
index c2b13b314dc..f9e8f89e21d 100644
--- a/Lib/distutils/tests/test_bdist_wininst.py
+++ b/Lib/distutils/tests/test_bdist_wininst.py
@@ -1,7 +1,6 @@
"""Tests for distutils.command.bdist_wininst."""
import unittest
-
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.command.bdist_wininst import bdist_wininst
from distutils.tests import support
diff --git a/Lib/distutils/tests/test_build.py b/Lib/distutils/tests/test_build.py
index eeb8d73e14d..3391f36d4bf 100644
--- a/Lib/distutils/tests/test_build.py
+++ b/Lib/distutils/tests/test_build.py
@@ -2,7 +2,7 @@
import unittest
import os
import sys
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.command.build import build
from distutils.tests import support
diff --git a/Lib/distutils/tests/test_build_clib.py b/Lib/distutils/tests/test_build_clib.py
index bef1bd99536..69bd2bf6241 100644
--- a/Lib/distutils/tests/test_build_clib.py
+++ b/Lib/distutils/tests/test_build_clib.py
@@ -3,7 +3,7 @@ import unittest
import os
import sys
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.command.build_clib import build_clib
from distutils.errors import DistutilsSetupError
diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
index b71cc983bee..090eacfb2c3 100644
--- a/Lib/distutils/tests/test_build_ext.py
+++ b/Lib/distutils/tests/test_build_ext.py
@@ -1,32 +1,36 @@
import sys
import os
-from StringIO import StringIO
+from io import StringIO
import textwrap
-from distutils.core import Extension, Distribution
+from distutils.core import Distribution
from distutils.command.build_ext import build_ext
from distutils import sysconfig
-from distutils.tests import support
-from distutils.errors import (DistutilsSetupError, CompileError,
- DistutilsPlatformError)
+from distutils.tests.support import (TempdirManager, LoggingSilencer,
+ copy_xxmodule_c, fixup_build_ext)
+from distutils.extension import Extension
+from distutils.errors import (
+ CompileError, DistutilsPlatformError, DistutilsSetupError,
+ UnknownFileError)
import unittest
-from test import test_support
+from test import support
# http://bugs.python.org/issue4373
# Don't load the xx module more than once.
ALREADY_TESTED = False
-class BuildExtTestCase(support.TempdirManager,
- support.LoggingSilencer,
+class BuildExtTestCase(TempdirManager,
+ LoggingSilencer,
unittest.TestCase):
def setUp(self):
+ # Create a simple test environment
+ # Note that we're making changes to sys.path
super(BuildExtTestCase, self).setUp()
self.tmp_dir = self.mkdtemp()
- self.xx_created = False
+ self.sys_path = sys.path, sys.path[:]
sys.path.append(self.tmp_dir)
- self.addCleanup(sys.path.remove, self.tmp_dir)
if sys.version > "2.6":
import site
self.old_user_base = site.USER_BASE
@@ -34,28 +38,20 @@ class BuildExtTestCase(support.TempdirManager,
from distutils.command import build_ext
build_ext.USER_BASE = site.USER_BASE
- def tearDown(self):
- if self.xx_created:
- test_support.unload('xx')
- # XXX on Windows the test leaves a directory
- # with xx module in TEMP
- super(BuildExtTestCase, self).tearDown()
-
def test_build_ext(self):
global ALREADY_TESTED
- support.copy_xxmodule_c(self.tmp_dir)
- self.xx_created = True
+ copy_xxmodule_c(self.tmp_dir)
xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
xx_ext = Extension('xx', [xx_c])
dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
dist.package_dir = self.tmp_dir
cmd = build_ext(dist)
- support.fixup_build_ext(cmd)
+ fixup_build_ext(cmd)
cmd.build_lib = self.tmp_dir
cmd.build_temp = self.tmp_dir
old_stdout = sys.stdout
- if not test_support.verbose:
+ if not support.verbose:
# silence compiler output
sys.stdout = StringIO()
try:
@@ -82,6 +78,18 @@ class BuildExtTestCase(support.TempdirManager,
self.assertTrue(isinstance(xx.Null(), xx.Null))
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):
dist = Distribution({'name': 'xx'})
cmd = build_ext(dist)
@@ -113,9 +121,9 @@ class BuildExtTestCase(support.TempdirManager,
cmd = build_ext(dist)
# making sure the user option is there
- options = [name for name, short, label in
+ options = [name for name, short, lable in
cmd.user_options]
- self.assertIn('user', options)
+ self.assertTrue('user' in options)
# setting a value
cmd.user = 1
@@ -126,21 +134,41 @@ class BuildExtTestCase(support.TempdirManager,
os.mkdir(lib)
os.mkdir(incl)
+ # let's run finalize
cmd.ensure_finalized()
- # see if include_dirs and library_dirs were set
+ # see if include_dirs and library_dirs
+ # were set
self.assertIn(lib, cmd.library_dirs)
self.assertIn(lib, cmd.rpath)
self.assertIn(incl, cmd.include_dirs)
+ def test_optional_extension(self):
+
+ # this extension will fail, but let's ignore this failure
+ # with the optional argument.
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = build_ext(dist)
+ cmd.ensure_finalized()
+ self.assertRaises((UnknownFileError, CompileError),
+ cmd.run) # should raise an error
+
+ modules = [Extension('foo', ['xxx'], optional=True)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = build_ext(dist)
+ cmd.ensure_finalized()
+ cmd.run() # should pass
+
def test_finalize_options(self):
# Make sure Python's include directories (for Python.h, pyconfig.h,
# etc.) are in the include search path.
- modules = [Extension('foo', ['xxx'])]
+ modules = [Extension('foo', ['xxx'], optional=False)]
dist = Distribution({'name': 'xx', 'ext_modules': modules})
cmd = build_ext(dist)
cmd.finalize_options()
+ from distutils import sysconfig
py_include = sysconfig.get_python_inc()
self.assertTrue(py_include in cmd.include_dirs)
@@ -202,7 +230,8 @@ class BuildExtTestCase(support.TempdirManager,
cmd.finalize_options()
#'extensions' option must be a list of Extension instances
- self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, 'foo')
+ self.assertRaises(DistutilsSetupError,
+ cmd.check_extensions_list, 'foo')
# each element of 'ext_modules' option must be an
# Extension instance or 2-tuple
@@ -244,7 +273,7 @@ class BuildExtTestCase(support.TempdirManager,
self.assertEqual(exts[0].define_macros, [('1', '2')])
def test_get_source_files(self):
- modules = [Extension('foo', ['xxx'])]
+ modules = [Extension('foo', ['xxx'], optional=False)]
dist = Distribution({'name': 'xx', 'ext_modules': modules})
cmd = build_ext(dist)
cmd.ensure_finalized()
@@ -264,12 +293,12 @@ class BuildExtTestCase(support.TempdirManager,
def test_get_outputs(self):
tmp_dir = self.mkdtemp()
c_file = os.path.join(tmp_dir, 'foo.c')
- self.write_file(c_file, 'void initfoo(void) {};\n')
- ext = Extension('foo', [c_file])
+ self.write_file(c_file, 'void PyInit_foo(void) {}\n')
+ ext = Extension('foo', [c_file], optional=False)
dist = Distribution({'name': 'xx',
'ext_modules': [ext]})
cmd = build_ext(dist)
- support.fixup_build_ext(cmd)
+ fixup_build_ext(cmd)
cmd.ensure_finalized()
self.assertEqual(len(cmd.get_outputs()), 1)
@@ -288,17 +317,17 @@ class BuildExtTestCase(support.TempdirManager,
finally:
os.chdir(old_wd)
self.assertTrue(os.path.exists(so_file))
- self.assertEqual(os.path.splitext(so_file)[-1],
- sysconfig.get_config_var('SO'))
+ so_ext = sysconfig.get_config_var('SO')
+ self.assertTrue(so_file.endswith(so_ext))
so_dir = os.path.dirname(so_file)
self.assertEqual(so_dir, other_tmp_dir)
- cmd.compiler = None
+
cmd.inplace = 0
+ cmd.compiler = None
cmd.run()
so_file = cmd.get_outputs()[0]
self.assertTrue(os.path.exists(so_file))
- self.assertEqual(os.path.splitext(so_file)[-1],
- sysconfig.get_config_var('SO'))
+ self.assertTrue(so_file.endswith(so_ext))
so_dir = os.path.dirname(so_file)
self.assertEqual(so_dir, cmd.build_lib)
@@ -326,6 +355,10 @@ class BuildExtTestCase(support.TempdirManager,
def test_ext_fullpath(self):
ext = sysconfig.get_config_vars()['SO']
+ # building lxml.etree inplace
+ #etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
+ #etree_ext = Extension('lxml.etree', [etree_c])
+ #dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
dist = Distribution()
cmd = build_ext(dist)
cmd.inplace = 1
@@ -358,73 +391,6 @@ class BuildExtTestCase(support.TempdirManager,
wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
self.assertEqual(wanted, path)
- def test_build_ext_inplace(self):
- etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
- etree_ext = Extension('lxml.etree', [etree_c])
- dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- cmd.inplace = 1
- cmd.distribution.package_dir = {'': 'src'}
- cmd.distribution.packages = ['lxml', 'lxml.html']
- curdir = os.getcwd()
- ext = sysconfig.get_config_var("SO")
- wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
- path = cmd.get_ext_fullpath('lxml.etree')
- self.assertEqual(wanted, path)
-
- def test_setuptools_compat(self):
- import distutils.core, distutils.extension, distutils.command.build_ext
- saved_ext = distutils.extension.Extension
- try:
- # on some platforms, it loads the deprecated "dl" module
- test_support.import_module('setuptools_build_ext', deprecated=True)
-
- # theses import patch Distutils' Extension class
- from setuptools_build_ext import build_ext as setuptools_build_ext
- from setuptools_extension import Extension
-
- etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
- etree_ext = Extension('lxml.etree', [etree_c])
- dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
- cmd = setuptools_build_ext(dist)
- cmd.ensure_finalized()
- cmd.inplace = 1
- cmd.distribution.package_dir = {'': 'src'}
- cmd.distribution.packages = ['lxml', 'lxml.html']
- curdir = os.getcwd()
- ext = sysconfig.get_config_var("SO")
- wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
- path = cmd.get_ext_fullpath('lxml.etree')
- self.assertEqual(wanted, path)
- finally:
- # restoring Distutils' Extension class otherwise its broken
- distutils.extension.Extension = saved_ext
- distutils.core.Extension = saved_ext
- distutils.command.build_ext.Extension = saved_ext
-
- def test_build_ext_path_with_os_sep(self):
- dist = Distribution({'name': 'UpdateManager'})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- ext = sysconfig.get_config_var("SO")
- ext_name = os.path.join('UpdateManager', 'fdsend')
- ext_path = cmd.get_ext_fullpath(ext_name)
- wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
- self.assertEqual(ext_path, wanted)
-
- def test_build_ext_path_cross_platform(self):
- if sys.platform != 'win32':
- return
- dist = Distribution({'name': 'UpdateManager'})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- ext = sysconfig.get_config_var("SO")
- # this needs to work even under win32
- ext_name = 'UpdateManager/fdsend'
- ext_path = cmd.get_ext_fullpath(ext_name)
- wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
- self.assertEqual(ext_path, wanted)
@unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
def test_deployment_target_default(self):
@@ -498,13 +464,22 @@ class BuildExtTestCase(support.TempdirManager,
cmd.build_temp = self.tmp_dir
try:
- cmd.ensure_finalized()
- cmd.run()
+ old_stdout = sys.stdout
+ if not support.verbose:
+ # silence compiler output
+ sys.stdout = StringIO()
+ try:
+ cmd.ensure_finalized()
+ cmd.run()
+ finally:
+ sys.stdout = old_stdout
+
except CompileError:
self.fail("Wrong deployment target during compilation")
+
def test_suite():
return unittest.makeSuite(BuildExtTestCase)
if __name__ == '__main__':
- test_support.run_unittest(test_suite())
+ support.run_unittest(test_suite())
diff --git a/Lib/distutils/tests/test_build_py.py b/Lib/distutils/tests/test_build_py.py
index 6c6ec208aaa..e416edd4a1e 100644
--- a/Lib/distutils/tests/test_build_py.py
+++ b/Lib/distutils/tests/test_build_py.py
@@ -2,7 +2,7 @@
import os
import sys
-import StringIO
+import imp
import unittest
from distutils.command.build_py import build_py
@@ -10,7 +10,7 @@ from distutils.core import Distribution
from distutils.errors import DistutilsFileError
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class BuildPyTestCase(support.TempdirManager,
@@ -53,23 +53,20 @@ class BuildPyTestCase(support.TempdirManager,
# This makes sure the list of outputs includes byte-compiled
# files for Python modules but not for package data files
# (there shouldn't *be* byte-code files for those!).
- #
self.assertEqual(len(cmd.get_outputs()), 3)
pkgdest = os.path.join(destination, "pkg")
files = os.listdir(pkgdest)
+ pycache_dir = os.path.join(pkgdest, "__pycache__")
self.assertIn("__init__.py", files)
self.assertIn("README.txt", files)
- # XXX even with -O, distutils writes pyc, not pyo; bug?
if sys.dont_write_bytecode:
- self.assertNotIn("__init__.pyc", files)
+ self.assertFalse(os.path.exists(pycache_dir))
else:
- self.assertIn("__init__.pyc", files)
+ pyc_files = os.listdir(pycache_dir)
+ self.assertIn("__init__.%s.pyc" % imp.get_tag(), pyc_files)
def test_empty_package_dir(self):
- # See SF 1668596/1720897.
- cwd = os.getcwd()
-
- # create the distribution files.
+ # See bugs #1668596/#1720897
sources = self.mkdtemp()
open(os.path.join(sources, "__init__.py"), "w").close()
@@ -78,30 +75,55 @@ class BuildPyTestCase(support.TempdirManager,
open(os.path.join(testdir, "testfile"), "w").close()
os.chdir(sources)
- old_stdout = sys.stdout
- sys.stdout = StringIO.StringIO()
+ dist = Distribution({"packages": ["pkg"],
+ "package_dir": {"pkg": ""},
+ "package_data": {"pkg": ["doc/*"]}})
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(sources, "setup.py")
+ dist.script_args = ["build"]
+ dist.parse_command_line()
try:
- dist = Distribution({"packages": ["pkg"],
- "package_dir": {"pkg": ""},
- "package_data": {"pkg": ["doc/*"]}})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
- dist.script_args = ["build"]
- dist.parse_command_line()
-
- try:
- dist.run_commands()
- except DistutilsFileError:
- self.fail("failed package_data test when package_dir is ''")
- finally:
- # Restore state.
- os.chdir(cwd)
- sys.stdout = old_stdout
+ dist.run_commands()
+ except DistutilsFileError:
+ self.fail("failed package_data test when package_dir is ''")
+
+ @unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
+ def test_byte_compile(self):
+ project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
+ os.chdir(project_dir)
+ self.write_file('boiledeggs.py', 'import antigravity')
+ cmd = build_py(dist)
+ cmd.compile = 1
+ cmd.build_lib = 'here'
+ cmd.finalize_options()
+ cmd.run()
+
+ found = os.listdir(cmd.build_lib)
+ self.assertEqual(sorted(found), ['__pycache__', 'boiledeggs.py'])
+ found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
+ self.assertEqual(found, ['boiledeggs.%s.pyc' % imp.get_tag()])
+
+ @unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
+ def test_byte_compile_optimized(self):
+ project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
+ os.chdir(project_dir)
+ self.write_file('boiledeggs.py', 'import antigravity')
+ cmd = build_py(dist)
+ cmd.compile = 0
+ cmd.optimize = 1
+ cmd.build_lib = 'here'
+ cmd.finalize_options()
+ cmd.run()
+
+ found = os.listdir(cmd.build_lib)
+ self.assertEqual(sorted(found), ['__pycache__', 'boiledeggs.py'])
+ found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
+ self.assertEqual(sorted(found), ['boiledeggs.%s.pyo' % imp.get_tag()])
def test_dont_write_bytecode(self):
# makes sure byte_compile is not used
- pkg_dir, dist = self.create_dist()
+ dist = self.create_dist()[1]
cmd = build_py(dist)
cmd.compile = 1
cmd.optimize = 1
@@ -115,6 +137,7 @@ class BuildPyTestCase(support.TempdirManager,
self.assertIn('byte-compiling is disabled', self.logs[0][1])
+
def test_suite():
return unittest.makeSuite(BuildPyTestCase)
diff --git a/Lib/distutils/tests/test_build_scripts.py b/Lib/distutils/tests/test_build_scripts.py
index 4da93cc1405..e3326b85176 100644
--- a/Lib/distutils/tests/test_build_scripts.py
+++ b/Lib/distutils/tests/test_build_scripts.py
@@ -5,10 +5,10 @@ import unittest
from distutils.command.build_scripts import build_scripts
from distutils.core import Distribution
-import sysconfig
+from distutils import sysconfig
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class BuildScriptsTestCase(support.TempdirManager,
@@ -94,12 +94,12 @@ class BuildScriptsTestCase(support.TempdirManager,
# --with-suffix=3`, python is compiled okay but the build scripts
# failed when writing the name of the executable
old = sysconfig.get_config_vars().get('VERSION')
- sysconfig._CONFIG_VARS['VERSION'] = 4
+ sysconfig._config_vars['VERSION'] = 4
try:
cmd.run()
finally:
if old is not None:
- sysconfig._CONFIG_VARS['VERSION'] = old
+ sysconfig._config_vars['VERSION'] = old
built = os.listdir(target)
for name in expected:
diff --git a/Lib/distutils/tests/test_ccompiler.py b/Lib/distutils/tests/test_ccompiler.py
deleted file mode 100644
index 45e477a429e..00000000000
--- a/Lib/distutils/tests/test_ccompiler.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""Tests for distutils.ccompiler."""
-import os
-import unittest
-from test.test_support import captured_stdout
-
-from distutils.ccompiler import (gen_lib_options, CCompiler,
- get_default_compiler)
-from distutils.sysconfig import 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.assertEqual(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.assertEqual(stdout.read(), '')
-
- debug.DEBUG = True
- try:
- with captured_stdout() as stdout:
- compiler.debug_print('xxx')
- stdout.seek(0)
- self.assertEqual(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.assertEqual(comp.exes['archiver'], 'my_ar -arflags')
-
-def test_suite():
- return unittest.makeSuite(CCompilerTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/Lib/distutils/tests/test_check.py b/Lib/distutils/tests/test_check.py
index f73342ade85..4de64734c4c 100644
--- a/Lib/distutils/tests/test_check.py
+++ b/Lib/distutils/tests/test_check.py
@@ -1,7 +1,6 @@
-# -*- encoding: utf8 -*-
"""Tests for distutils.command.check."""
import unittest
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.command.check import check, HAS_DOCUTILS
from distutils.tests import support
@@ -47,12 +46,12 @@ class CheckTestCase(support.LoggingSilencer,
cmd = self._run(metadata, strict=1)
self.assertEqual(cmd._warnings, 0)
- # now a test with Unicode entries
- metadata = {'url': u'xxx', 'author': u'\u00c9ric',
- 'author_email': u'xxx', u'name': 'xxx',
- 'version': u'xxx',
- 'description': u'Something about esszet \u00df',
- 'long_description': u'More things about esszet \u00df'}
+ # now a test with non-ASCII characters
+ metadata = {'url': 'xxx', 'author': '\u00c9ric',
+ 'author_email': 'xxx', 'name': 'xxx',
+ 'version': 'xxx',
+ 'description': 'Something about esszet \u00df',
+ 'long_description': 'More things about esszet \u00df'}
cmd = self._run(metadata)
self.assertEqual(cmd._warnings, 0)
@@ -91,7 +90,7 @@ class CheckTestCase(support.LoggingSilencer,
**{'strict': 1, 'restructuredtext': 1})
# and non-broken rest, including a non-ASCII character to test #12114
- metadata['long_description'] = u'title\n=====\n\ntest \u00df'
+ metadata['long_description'] = 'title\n=====\n\ntest \u00df'
cmd = self._run(metadata, strict=1, restructuredtext=1)
self.assertEqual(cmd._warnings, 0)
diff --git a/Lib/distutils/tests/test_clean.py b/Lib/distutils/tests/test_clean.py
index 7b988f7f325..eb8958bff5a 100644
--- a/Lib/distutils/tests/test_clean.py
+++ b/Lib/distutils/tests/test_clean.py
@@ -6,7 +6,7 @@ import getpass
from distutils.command.clean import clean
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class cleanTestCase(support.TempdirManager,
support.LoggingSilencer,
diff --git a/Lib/distutils/tests/test_cmd.py b/Lib/distutils/tests/test_cmd.py
index e074099609a..195045cc7b8 100644
--- a/Lib/distutils/tests/test_cmd.py
+++ b/Lib/distutils/tests/test_cmd.py
@@ -1,7 +1,7 @@
"""Tests for distutils.cmd."""
import unittest
import os
-from test.test_support import captured_stdout, run_unittest
+from test.support import captured_stdout, run_unittest
from distutils.cmd import Command
from distutils.dist import Distribution
diff --git a/Lib/distutils/tests/test_config.py b/Lib/distutils/tests/test_config.py
index cfd096ebc23..525bee9416a 100644
--- a/Lib/distutils/tests/test_config.py
+++ b/Lib/distutils/tests/test_config.py
@@ -3,7 +3,6 @@ import sys
import os
import unittest
import tempfile
-import shutil
from distutils.core import PyPIRCCommand
from distutils.core import Distribution
@@ -11,7 +10,7 @@ from distutils.log import set_threshold
from distutils.log import WARN
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
PYPIRC = """\
[distutils]
@@ -86,8 +85,7 @@ class PyPIRCCommandTestCase(support.TempdirManager,
cmd = self._cmd(self.dist)
config = cmd._read_pypirc()
- config = config.items()
- config.sort()
+ config = list(sorted(config.items()))
waited = [('password', 'secret'), ('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi'),
('server', 'server1'), ('username', 'me')]
@@ -96,8 +94,7 @@ class PyPIRCCommandTestCase(support.TempdirManager,
# old format
self.write_file(self.rc, PYPIRC_OLD)
config = cmd._read_pypirc()
- config = config.items()
- config.sort()
+ config = list(sorted(config.items()))
waited = [('password', 'secret'), ('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi'),
('server', 'server-login'), ('username', 'tarek')]
diff --git a/Lib/distutils/tests/test_config_cmd.py b/Lib/distutils/tests/test_config_cmd.py
index 2cf3886cb5b..e2e6e4ebaa2 100644
--- a/Lib/distutils/tests/test_config_cmd.py
+++ b/Lib/distutils/tests/test_config_cmd.py
@@ -2,7 +2,7 @@
import unittest
import os
import sys
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils.command.config import dump_file, config
from distutils.tests import support
diff --git a/Lib/distutils/tests/test_core.py b/Lib/distutils/tests/test_core.py
index 0d979bcde9e..41321f7db4e 100644
--- a/Lib/distutils/tests/test_core.py
+++ b/Lib/distutils/tests/test_core.py
@@ -1,12 +1,12 @@
"""Tests for distutils.core."""
-import StringIO
+import io
import distutils.core
import os
import shutil
import sys
-import test.test_support
-from test.test_support import captured_stdout, run_unittest
+import test.support
+from test.support import captured_stdout, run_unittest
import unittest
from distutils.tests import support
@@ -22,7 +22,7 @@ setup()
setup_prints_cwd = """\
import os
-print os.getcwd()
+print(os.getcwd())
from distutils.core import setup
setup()
@@ -45,13 +45,13 @@ class CoreTestCase(support.EnvironGuard, unittest.TestCase):
super(CoreTestCase, self).tearDown()
def cleanup_testfn(self):
- path = test.test_support.TESTFN
+ path = test.support.TESTFN
if os.path.isfile(path):
os.remove(path)
elif os.path.isdir(path):
shutil.rmtree(path)
- def write_setup(self, text, path=test.test_support.TESTFN):
+ def write_setup(self, text, path=test.support.TESTFN):
f = open(path, "w")
try:
f.write(text)
@@ -69,12 +69,12 @@ class CoreTestCase(support.EnvironGuard, unittest.TestCase):
# This tests that the setup script is run with the current directory
# as its own current directory; this was temporarily broken by a
# previous patch when TESTFN did not use the current directory.
- sys.stdout = StringIO.StringIO()
+ sys.stdout = io.StringIO()
cwd = os.getcwd()
# Create a directory and write the setup.py file there:
- os.mkdir(test.test_support.TESTFN)
- setup_py = os.path.join(test.test_support.TESTFN, "setup.py")
+ os.mkdir(test.support.TESTFN)
+ setup_py = os.path.join(test.support.TESTFN, "setup.py")
distutils.core.run_setup(
self.write_setup(setup_prints_cwd, path=setup_py))
diff --git a/Lib/distutils/tests/test_cygwinccompiler.py b/Lib/distutils/tests/test_cygwinccompiler.py
new file mode 100644
index 00000000000..856921679d6
--- /dev/null
+++ b/Lib/distutils/tests/test_cygwinccompiler.py
@@ -0,0 +1,155 @@
+"""Tests for distutils.cygwinccompiler."""
+import unittest
+import sys
+import os
+from io import BytesIO
+import subprocess
+from test.support import run_unittest
+
+from distutils import cygwinccompiler
+from distutils.cygwinccompiler import (CygwinCCompiler, check_config_h,
+ CONFIG_H_OK, CONFIG_H_NOTOK,
+ CONFIG_H_UNCERTAIN, get_versions,
+ get_msvcr)
+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,
+ unittest.TestCase):
+
+ def setUp(self):
+ super(CygwinCCompilerTestCase, self).setUp()
+ self.version = sys.version
+ 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
+ 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):
+ sys.version = self.version
+ from distutils import sysconfig
+ 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()
+
+ def _get_config_h_filename(self):
+ return self.python_h
+
+ def _find_executable(self, name):
+ if name in self._exes:
+ return name
+ return None
+
+ def test_check_config_h(self):
+
+ # check_config_h looks for "GCC" in sys.version first
+ # returns CONFIG_H_OK if found
+ sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) \n[GCC '
+ '4.0.1 (Apple Computer, Inc. build 5370)]')
+
+ self.assertEqual(check_config_h()[0], CONFIG_H_OK)
+
+ # then it tries to see if it can find "__GNUC__" in pyconfig.h
+ sys.version = 'something without the *CC word'
+
+ # if the file doesn't exist it returns CONFIG_H_UNCERTAIN
+ self.assertEqual(check_config_h()[0], CONFIG_H_UNCERTAIN)
+
+ # if it exists but does not contain __GNUC__, it returns CONFIG_H_NOTOK
+ self.write_file(self.python_h, 'xxx')
+ self.assertEqual(check_config_h()[0], CONFIG_H_NOTOK)
+
+ # and CONFIG_H_OK if __GNUC__ is found
+ self.write_file(self.python_h, 'xxx __GNUC__ xxx')
+ self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(res[0], None)
+
+ # same thing for ld
+ self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
+ res = get_versions()
+ self.assertEqual(str(res[1]), '2.17.50')
+ self._exes['ld'] = b'@(#)PROGRAM:ld PROJECT:ld64-77'
+ res = get_versions()
+ self.assertEqual(res[1], None)
+
+ # and dllwrap
+ self._exes['dllwrap'] = b'GNU dllwrap 2.17.50 20060824\nFSF'
+ res = get_versions()
+ self.assertEqual(str(res[2]), '2.17.50')
+ self._exes['dllwrap'] = b'Cheese Wrap'
+ res = get_versions()
+ self.assertEqual(res[2], None)
+
+ def test_get_msvcr(self):
+
+ # none
+ sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) '
+ '\n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]')
+ self.assertEqual(get_msvcr(), None)
+
+ # MSVC 7.0
+ sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
+ '[MSC v.1300 32 bits (Intel)]')
+ self.assertEqual(get_msvcr(), ['msvcr70'])
+
+ # MSVC 7.1
+ sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
+ '[MSC v.1310 32 bits (Intel)]')
+ self.assertEqual(get_msvcr(), ['msvcr71'])
+
+ # VS2005 / MSVC 8.0
+ sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
+ '[MSC v.1400 32 bits (Intel)]')
+ self.assertEqual(get_msvcr(), ['msvcr80'])
+
+ # VS2008 / MSVC 9.0
+ sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
+ '[MSC v.1500 32 bits (Intel)]')
+ self.assertEqual(get_msvcr(), ['msvcr90'])
+
+ # unknown
+ sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
+ '[MSC v.1999 32 bits (Intel)]')
+ self.assertRaises(ValueError, get_msvcr)
+
+def test_suite():
+ return unittest.makeSuite(CygwinCCompilerTestCase)
+
+if __name__ == '__main__':
+ run_unittest(test_suite())
diff --git a/Lib/distutils/tests/test_dep_util.py b/Lib/distutils/tests/test_dep_util.py
index 751043432ed..3e1c366892d 100644
--- a/Lib/distutils/tests/test_dep_util.py
+++ b/Lib/distutils/tests/test_dep_util.py
@@ -6,7 +6,7 @@ import time
from distutils.dep_util import newer, newer_pairwise, newer_group
from distutils.errors import DistutilsFileError
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class DepUtilTestCase(support.TempdirManager, unittest.TestCase):
diff --git a/Lib/distutils/tests/test_dir_util.py b/Lib/distutils/tests/test_dir_util.py
index d82d9133d04..1589f1297db 100644
--- a/Lib/distutils/tests/test_dir_util.py
+++ b/Lib/distutils/tests/test_dir_util.py
@@ -10,7 +10,7 @@ from distutils.dir_util import (mkpath, remove_tree, create_tree, copy_tree,
from distutils import log
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class DirUtilTestCase(support.TempdirManager, unittest.TestCase):
@@ -76,7 +76,6 @@ class DirUtilTestCase(support.TempdirManager, unittest.TestCase):
remove_tree(self.root_target, verbose=0)
-
def test_copy_tree_verbosity(self):
mkpath(self.target, verbose=0)
@@ -88,11 +87,8 @@ class DirUtilTestCase(support.TempdirManager, unittest.TestCase):
mkpath(self.target, verbose=0)
a_file = os.path.join(self.target, 'ok.txt')
- f = open(a_file, 'w')
- try:
+ with open(a_file, 'w') as f:
f.write('some content')
- finally:
- f.close()
wanted = ['copying %s -> %s' % (a_file, self.target2)]
copy_tree(self.target, self.target2, verbose=1)
@@ -107,11 +103,8 @@ class DirUtilTestCase(support.TempdirManager, unittest.TestCase):
a_file = os.path.join(self.target, 'ok.txt')
nfs_file = os.path.join(self.target, '.nfs123abc')
for f in a_file, nfs_file:
- fh = open(f, 'w')
- try:
+ with open(f, 'w') as fh:
fh.write('some content')
- finally:
- fh.close()
copy_tree(self.target, self.target2)
self.assertEqual(os.listdir(self.target2), ['ok.txt'])
diff --git a/Lib/distutils/tests/test_dist.py b/Lib/distutils/tests/test_dist.py
index 4b7bbeb33ec..8aaae88cae5 100644
--- a/Lib/distutils/tests/test_dist.py
+++ b/Lib/distutils/tests/test_dist.py
@@ -1,8 +1,6 @@
-# -*- coding: utf8 -*-
-
"""Tests for distutils.dist."""
import os
-import StringIO
+import io
import sys
import unittest
import warnings
@@ -10,8 +8,8 @@ import textwrap
from distutils.dist import Distribution, fix_help_options
from distutils.cmd import Command
-import distutils.dist
-from test.test_support import TESTFN, captured_stdout, run_unittest
+
+from test.support import TESTFN, captured_stdout, run_unittest
from distutils.tests import support
@@ -38,8 +36,7 @@ class TestDistribution(Distribution):
return self._config_files
-class DistributionTestCase(support.TempdirManager,
- support.LoggingSilencer,
+class DistributionTestCase(support.LoggingSilencer,
support.EnvironGuard,
unittest.TestCase):
@@ -60,27 +57,6 @@ class DistributionTestCase(support.TempdirManager,
d.parse_command_line()
return d
- def test_debug_mode(self):
- with open(TESTFN, "w") as f:
- f.write("[global]\n")
- 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.assertEqual(stdout.read(), '')
- distutils.dist.DEBUG = True
- try:
- with captured_stdout() as stdout:
- self.create_distribution(files)
- stdout.seek(0)
- self.assertEqual(stdout.read(), '')
- finally:
- distutils.dist.DEBUG = False
-
def test_command_packages_unspecified(self):
sys.argv.append("build")
d = self.create_distribution()
@@ -106,8 +82,8 @@ class DistributionTestCase(support.TempdirManager,
self.addCleanup(os.unlink, TESTFN)
f = open(TESTFN, "w")
try:
- print >> f, "[global]"
- print >> f, "command_packages = foo.bar, splat"
+ print("[global]", file=f)
+ print("command_packages = foo.bar, splat", file=f)
finally:
f.close()
@@ -127,33 +103,6 @@ class DistributionTestCase(support.TempdirManager,
d = self.create_distribution([TESTFN])
self.assertEqual(d.get_command_packages(), ["distutils.command"])
- def test_write_pkg_file(self):
- # Check DistributionMetadata handling of Unicode fields
- tmp_dir = self.mkdtemp()
- my_file = os.path.join(tmp_dir, 'f')
- klass = Distribution
-
- dist = klass(attrs={'author': u'Mister Café',
- 'name': 'my.package',
- 'maintainer': u'Café Junior',
- 'description': u'Café torréfié',
- 'long_description': u'Héhéhé'})
-
- # let's make sure the file can be written
- # with Unicode fields. they are encoded with
- # PKG_INFO_ENCODING
- dist.metadata.write_pkg_file(open(my_file, 'w'))
-
- # regular ascii is of course always usable
- dist = klass(attrs={'author': 'Mister Cafe',
- 'name': 'my.package',
- 'maintainer': 'Cafe Junior',
- 'description': 'Cafe torrefie',
- 'long_description': 'Hehehe'})
-
- my_file2 = os.path.join(tmp_dir, 'f2')
- dist.metadata.write_pkg_file(open(my_file2, 'w'))
-
def test_empty_options(self):
# an empty options dictionary should not stay in the
# list of attributes
@@ -203,35 +152,6 @@ class DistributionTestCase(support.TempdirManager,
kwargs = {'level': 'ok2'}
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.assertEqual(len(all_files)-1, len(files))
-
class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
unittest.TestCase):
@@ -245,34 +165,10 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
sys.argv[:] = self.argv[1]
super(MetadataTestCase, self).tearDown()
- def test_classifier(self):
- attrs = {'name': 'Boa', 'version': '3.0',
- 'classifiers': ['Programming Language :: Python :: 3']}
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- self.assertIn('Metadata-Version: 1.1', meta)
-
- def test_download_url(self):
- attrs = {'name': 'Boa', 'version': '3.0',
- 'download_url': 'http://example.org/boa'}
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- self.assertIn('Metadata-Version: 1.1', meta)
-
- def test_long_description(self):
- long_desc = textwrap.dedent("""\
- example::
- We start here
- and continue here
- and end here.""")
- attrs = {"name": "package",
- "version": "1.0",
- "long_description": long_desc}
-
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- meta = meta.replace('\n' + 8 * ' ', '\n')
- self.assertIn(long_desc, meta)
+ def format_metadata(self, dist):
+ sio = io.StringIO()
+ dist.metadata.write_pkg_file(sio)
+ return sio.getvalue()
def test_simple_metadata(self):
attrs = {"name": "package",
@@ -348,10 +244,34 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
"version": "1.0",
"obsoletes": ["my.pkg (splat)"]})
- def format_metadata(self, dist):
- sio = StringIO.StringIO()
- dist.metadata.write_pkg_file(sio)
- return sio.getvalue()
+ def test_classifier(self):
+ attrs = {'name': 'Boa', 'version': '3.0',
+ 'classifiers': ['Programming Language :: Python :: 3']}
+ dist = Distribution(attrs)
+ meta = self.format_metadata(dist)
+ self.assertIn('Metadata-Version: 1.1', meta)
+
+ def test_download_url(self):
+ attrs = {'name': 'Boa', 'version': '3.0',
+ 'download_url': 'http://example.org/boa'}
+ dist = Distribution(attrs)
+ meta = self.format_metadata(dist)
+ self.assertIn('Metadata-Version: 1.1', meta)
+
+ def test_long_description(self):
+ long_desc = textwrap.dedent("""\
+ example::
+ We start here
+ and continue here
+ and end here.""")
+ attrs = {"name": "package",
+ "version": "1.0",
+ "long_description": long_desc}
+
+ dist = Distribution(attrs)
+ meta = self.format_metadata(dist)
+ meta = meta.replace('\n' + 8 * ' ', '\n')
+ self.assertIn(long_desc, meta)
def test_custom_pydistutils(self):
# fixes #2166
@@ -407,33 +327,6 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
if line.strip() != '']
self.assertTrue(output)
- 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 = StringIO.StringIO()
- metadata.write_pkg_file(PKG_INFO)
- PKG_INFO.seek(0)
- metadata.read_pkg_file(PKG_INFO)
-
- self.assertEqual(metadata.name, "package")
- self.assertEqual(metadata.version, "1.0")
- self.assertEqual(metadata.description, "xxx")
- self.assertEqual(metadata.download_url, 'http://example.com')
- self.assertEqual(metadata.keywords, ['one', 'two'])
- self.assertEqual(metadata.platforms, ['UNKNOWN'])
- self.assertEqual(metadata.obsoletes, None)
- self.assertEqual(metadata.requires, ['foo'])
-
def test_suite():
suite = unittest.TestSuite()
diff --git a/Lib/distutils/tests/test_extension.py b/Lib/distutils/tests/test_extension.py
new file mode 100644
index 00000000000..e35f2738b6a
--- /dev/null
+++ b/Lib/distutils/tests/test_extension.py
@@ -0,0 +1,69 @@
+"""Tests for distutils.extension."""
+import unittest
+import os
+import warnings
+
+from test.support import check_warnings, run_unittest
+from distutils.extension import read_setup_file, Extension
+
+class ExtensionTestCase(unittest.TestCase):
+
+ def test_read_setup_file(self):
+ # trying to read a Setup file
+ # (sample extracted from the PyGame project)
+ setup = os.path.join(os.path.dirname(__file__), 'Setup.sample')
+
+ exts = read_setup_file(setup)
+ names = [ext.name for ext in exts]
+ names.sort()
+
+ # here are the extensions read_setup_file should have created
+ # out of the file
+ wanted = ['_arraysurfarray', '_camera', '_numericsndarray',
+ '_numericsurfarray', 'base', 'bufferproxy', 'cdrom',
+ 'color', 'constants', 'display', 'draw', 'event',
+ 'fastevent', 'font', 'gfxdraw', 'image', 'imageext',
+ 'joystick', 'key', 'mask', 'mixer', 'mixer_music',
+ 'mouse', 'movie', 'overlay', 'pixelarray', 'pypm',
+ 'rect', 'rwobject', 'scrap', 'surface', 'surflock',
+ 'time', 'transform']
+
+ self.assertEqual(names, wanted)
+
+ def test_extension_init(self):
+ # the first argument, which is the name, must be a string
+ self.assertRaises(AssertionError, Extension, 1, [])
+ ext = Extension('name', [])
+ self.assertEqual(ext.name, 'name')
+
+ # the second argument, which is the list of files, must
+ # be a list of strings
+ self.assertRaises(AssertionError, Extension, 'name', 'file')
+ self.assertRaises(AssertionError, Extension, 'name', ['file', 1])
+ ext = Extension('name', ['file1', 'file2'])
+ self.assertEqual(ext.sources, ['file1', 'file2'])
+
+ # others arguments have defaults
+ for attr in ('include_dirs', 'define_macros', 'undef_macros',
+ 'library_dirs', 'libraries', 'runtime_library_dirs',
+ 'extra_objects', 'extra_compile_args', 'extra_link_args',
+ 'export_symbols', 'swig_opts', 'depends'):
+ self.assertEqual(getattr(ext, attr), [])
+
+ self.assertEqual(ext.language, None)
+ self.assertEqual(ext.optional, None)
+
+ # if there are unknown keyword options, warn about them
+ with check_warnings() as w:
+ warnings.simplefilter('always')
+ ext = Extension('name', ['file1', 'file2'], chic=True)
+
+ self.assertEqual(len(w.warnings), 1)
+ self.assertEqual(str(w.warnings[0].message),
+ "Unknown Extension options: 'chic'")
+
+def test_suite():
+ return unittest.makeSuite(ExtensionTestCase)
+
+if __name__ == "__main__":
+ run_unittest(test_suite())
diff --git a/Lib/distutils/tests/test_file_util.py b/Lib/distutils/tests/test_file_util.py
index 7dbcf52c68c..3c3e3dcb3bf 100644
--- a/Lib/distutils/tests/test_file_util.py
+++ b/Lib/distutils/tests/test_file_util.py
@@ -3,10 +3,10 @@ import unittest
import os
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.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class FileUtilTestCase(support.TempdirManager, unittest.TestCase):
@@ -58,21 +58,6 @@ class FileUtilTestCase(support.TempdirManager, unittest.TestCase):
wanted = ['moving %s -> %s' % (self.source, self.target_dir)]
self.assertEqual(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.assertEqual(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():
return unittest.makeSuite(FileUtilTestCase)
diff --git a/Lib/distutils/tests/test_filelist.py b/Lib/distutils/tests/test_filelist.py
index 69b88f2df2a..e82bc3d2ed7 100644
--- a/Lib/distutils/tests/test_filelist.py
+++ b/Lib/distutils/tests/test_filelist.py
@@ -7,7 +7,7 @@ from distutils.log import WARN
from distutils.errors import DistutilsTemplateError
from distutils.filelist import glob_to_re, translate_pattern, FileList
-from test.test_support import captured_stdout, run_unittest
+from test.support import captured_stdout, run_unittest
from distutils.tests import support
MANIFEST_IN = """\
diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py
index f17baa1e50d..cb2e1f28799 100644
--- a/Lib/distutils/tests/test_install.py
+++ b/Lib/distutils/tests/test_install.py
@@ -1,11 +1,12 @@
"""Tests for distutils.command.install."""
import os
+import imp
import sys
import unittest
import site
-from test.test_support import captured_stdout, run_unittest
+from test.support import captured_stdout, run_unittest
from distutils import sysconfig
from distutils.command.install import install
@@ -26,6 +27,7 @@ def _make_ext_name(modname):
class InstallTestCase(support.TempdirManager,
+ support.EnvironGuard,
support.LoggingSilencer,
unittest.TestCase):
@@ -66,10 +68,7 @@ class InstallTestCase(support.TempdirManager,
check_path(cmd.install_data, destination)
def test_user_site(self):
- # site.USER_SITE was introduced in 2.6
- if sys.version < '2.6':
- return
-
+ # test install with --user
# preparing the environment for the test
self.old_user_base = site.USER_BASE
self.old_user_site = site.USER_SITE
@@ -177,7 +176,7 @@ class InstallTestCase(support.TempdirManager,
project_dir, dist = self.create_dist(py_modules=['hello'],
scripts=['sayhi'])
os.chdir(project_dir)
- self.write_file('hello.py', "def main(): print 'o hai'")
+ self.write_file('hello.py', "def main(): print('o hai')")
self.write_file('sayhi', 'from hello import main; main()')
cmd = install(dist)
@@ -194,7 +193,7 @@ class InstallTestCase(support.TempdirManager,
f.close()
found = [os.path.basename(line) for line in content.splitlines()]
- expected = ['hello.py', 'hello.pyc', 'sayhi',
+ expected = ['hello.py', 'hello.%s.pyc' % imp.get_tag(), 'sayhi',
'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
self.assertEqual(found, expected)
diff --git a/Lib/distutils/tests/test_install_data.py b/Lib/distutils/tests/test_install_data.py
index 477569444fb..4d8c00acb99 100644
--- a/Lib/distutils/tests/test_install_data.py
+++ b/Lib/distutils/tests/test_install_data.py
@@ -6,7 +6,7 @@ import getpass
from distutils.command.install_data import install_data
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class InstallDataTestCase(support.TempdirManager,
support.LoggingSilencer,
diff --git a/Lib/distutils/tests/test_install_headers.py b/Lib/distutils/tests/test_install_headers.py
index b37224b93d2..d953157bb7e 100644
--- a/Lib/distutils/tests/test_install_headers.py
+++ b/Lib/distutils/tests/test_install_headers.py
@@ -6,7 +6,7 @@ import getpass
from distutils.command.install_headers import install_headers
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class InstallHeadersTestCase(support.TempdirManager,
support.LoggingSilencer,
diff --git a/Lib/distutils/tests/test_install_lib.py b/Lib/distutils/tests/test_install_lib.py
index 4d863089c08..2bd4dc6e963 100644
--- a/Lib/distutils/tests/test_install_lib.py
+++ b/Lib/distutils/tests/test_install_lib.py
@@ -1,13 +1,15 @@
"""Tests for distutils.command.install_data."""
-import os
import sys
+import os
+import imp
import unittest
from distutils.command.install_lib import install_lib
from distutils.extension import Extension
from distutils.tests import support
from distutils.errors import DistutilsOptionError
-from test.test_support import run_unittest
+from test.support import run_unittest
+
class InstallLibTestCase(support.TempdirManager,
support.LoggingSilencer,
@@ -15,7 +17,7 @@ class InstallLibTestCase(support.TempdirManager,
unittest.TestCase):
def test_finalize_options(self):
- pkg_dir, dist = self.create_dist()
+ dist = self.create_dist()[1]
cmd = install_lib(dist)
cmd.finalize_options()
@@ -32,61 +34,64 @@ class InstallLibTestCase(support.TempdirManager,
cmd.finalize_options()
self.assertEqual(cmd.optimize, 2)
- def _setup_byte_compile(self):
- pkg_dir, dist = self.create_dist()
+ @unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
+ def test_byte_compile(self):
+ project_dir, dist = self.create_dist()
+ os.chdir(project_dir)
cmd = install_lib(dist)
cmd.compile = cmd.optimize = 1
- f = os.path.join(pkg_dir, 'foo.py')
+ f = os.path.join(project_dir, 'foo.py')
self.write_file(f, '# python file')
cmd.byte_compile([f])
- return pkg_dir
-
- @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')))
+ pyc_file = imp.cache_from_source('foo.py', debug_override=True)
+ pyo_file = imp.cache_from_source('foo.py', debug_override=False)
+ self.assertTrue(os.path.exists(pyc_file))
+ self.assertTrue(os.path.exists(pyo_file))
def test_get_outputs(self):
- pkg_dir, dist = self.create_dist()
+ project_dir, dist = self.create_dist()
+ os.chdir(project_dir)
+ os.mkdir('spam')
cmd = install_lib(dist)
# setting up a dist environment
cmd.compile = cmd.optimize = 1
- cmd.install_dir = pkg_dir
- f = os.path.join(pkg_dir, 'foo.py')
- self.write_file(f, '# python file')
- cmd.distribution.py_modules = [pkg_dir]
+ cmd.install_dir = self.mkdtemp()
+ f = os.path.join(project_dir, 'spam', '__init__.py')
+ self.write_file(f, '# python package')
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
- cmd.distribution.packages = [pkg_dir]
+ cmd.distribution.packages = ['spam']
cmd.distribution.script_name = 'setup.py'
- # get_output should return 4 elements
- self.assertTrue(len(cmd.get_outputs()) >= 2)
+ # get_outputs should return 4 elements: spam/__init__.py, .pyc and
+ # .pyo, foo.import-tag-abiflags.so / foo.pyd
+ outputs = cmd.get_outputs()
+ self.assertEqual(len(outputs), 4, outputs)
def test_get_inputs(self):
- pkg_dir, dist = self.create_dist()
+ project_dir, dist = self.create_dist()
+ os.chdir(project_dir)
+ os.mkdir('spam')
cmd = install_lib(dist)
# setting up a dist environment
cmd.compile = cmd.optimize = 1
- cmd.install_dir = pkg_dir
- f = os.path.join(pkg_dir, 'foo.py')
- self.write_file(f, '# python file')
- cmd.distribution.py_modules = [pkg_dir]
+ cmd.install_dir = self.mkdtemp()
+ f = os.path.join(project_dir, 'spam', '__init__.py')
+ self.write_file(f, '# python package')
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
- cmd.distribution.packages = [pkg_dir]
+ cmd.distribution.packages = ['spam']
cmd.distribution.script_name = 'setup.py'
- # get_input should return 2 elements
- self.assertEqual(len(cmd.get_inputs()), 2)
+ # get_inputs should return 2 elements: spam/__init__.py and
+ # foo.import-tag-abiflags.so / foo.pyd
+ inputs = cmd.get_inputs()
+ self.assertEqual(len(inputs), 2, inputs)
def test_dont_write_bytecode(self):
# makes sure byte_compile is not used
- pkg_dir, dist = self.create_dist()
+ dist = self.create_dist()[1]
cmd = install_lib(dist)
cmd.compile = 1
cmd.optimize = 1
@@ -100,6 +105,7 @@ class InstallLibTestCase(support.TempdirManager,
self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
+
def test_suite():
return unittest.makeSuite(InstallLibTestCase)
diff --git a/Lib/distutils/tests/test_install_scripts.py b/Lib/distutils/tests/test_install_scripts.py
index 46085458bf1..8952e744e5d 100644
--- a/Lib/distutils/tests/test_install_scripts.py
+++ b/Lib/distutils/tests/test_install_scripts.py
@@ -7,7 +7,7 @@ from distutils.command.install_scripts import install_scripts
from distutils.core import Distribution
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
class InstallScriptsTestCase(support.TempdirManager,
diff --git a/Lib/distutils/tests/test_log.py b/Lib/distutils/tests/test_log.py
new file mode 100644
index 00000000000..ce66ee51e7c
--- /dev/null
+++ b/Lib/distutils/tests/test_log.py
@@ -0,0 +1,37 @@
+"""Tests for distutils.log"""
+
+import sys
+import unittest
+from tempfile import NamedTemporaryFile
+from test.support import run_unittest
+
+from distutils import log
+
+class TestLog(unittest.TestCase):
+ def test_non_ascii(self):
+ # Issue #8663: test that non-ASCII text is escaped with
+ # backslashreplace error handler (stream use ASCII encoding and strict
+ # error handler)
+ old_stdout = sys.stdout
+ old_stderr = sys.stderr
+ try:
+ log.set_threshold(log.DEBUG)
+ with NamedTemporaryFile(mode="w+", encoding='ascii') as stdout, \
+ NamedTemporaryFile(mode="w+", encoding='ascii') as stderr:
+ sys.stdout = stdout
+ sys.stderr = stderr
+ log.debug("debug:\xe9")
+ log.fatal("fatal:\xe9")
+ stdout.seek(0)
+ self.assertEqual(stdout.read().rstrip(), "debug:\\xe9")
+ stderr.seek(0)
+ self.assertEqual(stderr.read().rstrip(), "fatal:\\xe9")
+ finally:
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+
+def test_suite():
+ return unittest.makeSuite(TestLog)
+
+if __name__ == "__main__":
+ run_unittest(test_suite())
diff --git a/Lib/distutils/tests/test_msvc9compiler.py b/Lib/distutils/tests/test_msvc9compiler.py
index 2d94a1117e4..301d43d20c0 100644
--- a/Lib/distutils/tests/test_msvc9compiler.py
+++ b/Lib/distutils/tests/test_msvc9compiler.py
@@ -5,7 +5,7 @@ import os
from distutils.errors import DistutilsPlatformError
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
# A manifest with the only assembly reference being the msvcrt assembly, so
# should have the assembly completely stripped. Note that although the
@@ -127,11 +127,11 @@ class msvc9compilerTestCase(support.TempdirManager,
# looking for values that should exist on all
# windows registeries versions.
path = r'Control Panel\Desktop'
- v = Reg.get_value(path, u'dragfullwindows')
- self.assertTrue(v in (u'0', u'1', u'2'))
+ v = Reg.get_value(path, 'dragfullwindows')
+ self.assertTrue(v in ('0', '1', '2'))
- import _winreg
- HKCU = _winreg.HKEY_CURRENT_USER
+ import winreg
+ HKCU = winreg.HKEY_CURRENT_USER
keys = Reg.read_keys(HKCU, 'xxxx')
self.assertEqual(keys, None)
diff --git a/Lib/distutils/tests/test_register.py b/Lib/distutils/tests/test_register.py
index 4f34b18bd8f..a86b8606e4e 100644
--- a/Lib/distutils/tests/test_register.py
+++ b/Lib/distutils/tests/test_register.py
@@ -1,12 +1,11 @@
-# -*- encoding: utf8 -*-
"""Tests for distutils.command.register."""
import os
import unittest
import getpass
-import urllib2
+import urllib
import warnings
-from test.test_support import check_warnings, run_unittest
+from test.support import check_warnings, run_unittest
from distutils.command import register as register_module
from distutils.command.register import register
@@ -39,7 +38,7 @@ username:tarek
password:password
"""
-class RawInputs(object):
+class Inputs(object):
"""Fakes user inputs."""
def __init__(self, *answers):
self.answers = answers
@@ -75,12 +74,12 @@ class RegisterTestCase(PyPIRCCommandTestCase):
def _getpass(prompt):
return 'password'
getpass.getpass = _getpass
- self.old_opener = urllib2.build_opener
- self.conn = urllib2.build_opener = FakeOpener()
+ self.old_opener = urllib.request.build_opener
+ self.conn = urllib.request.build_opener = FakeOpener()
def tearDown(self):
getpass.getpass = self._old_getpass
- urllib2.build_opener = self.old_opener
+ urllib.request.build_opener = self.old_opener
super(RegisterTestCase, self).tearDown()
def _get_cmd(self, metadata=None):
@@ -101,7 +100,7 @@ class RegisterTestCase(PyPIRCCommandTestCase):
# we shouldn't have a .pypirc file yet
self.assertTrue(not os.path.exists(self.rc))
- # patching raw_input and getpass.getpass
+ # patching input and getpass.getpass
# so register gets happy
#
# Here's what we are faking :
@@ -109,13 +108,13 @@ class RegisterTestCase(PyPIRCCommandTestCase):
# Username : 'tarek'
# Password : 'password'
# Save your login (y/N)? : 'y'
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
+ inputs = Inputs('1', 'tarek', 'y')
+ register_module.input = inputs.__call__
# let's run the command
try:
cmd.run()
finally:
- del register_module.raw_input
+ del register_module.input
# we should have a brand new .pypirc file
self.assertTrue(os.path.exists(self.rc))
@@ -133,7 +132,7 @@ class RegisterTestCase(PyPIRCCommandTestCase):
# if we run the command again
def _no_way(prompt=''):
raise AssertionError(prompt)
- register_module.raw_input = _no_way
+ register_module.input = _no_way
cmd.show_response = 1
cmd.run()
@@ -143,8 +142,10 @@ class RegisterTestCase(PyPIRCCommandTestCase):
self.assertEqual(len(self.conn.reqs), 2)
req1 = dict(self.conn.reqs[0].headers)
req2 = dict(self.conn.reqs[1].headers)
- self.assertEqual(req2['Content-length'], req1['Content-length'])
- self.assertTrue('xxx' in self.conn.reqs[1].data)
+
+ self.assertEqual(req1['Content-length'], '1374')
+ self.assertEqual(req2['Content-length'], '1374')
+ self.assertTrue((b'xxx') in self.conn.reqs[1].data)
def test_password_not_in_file(self):
@@ -161,38 +162,38 @@ class RegisterTestCase(PyPIRCCommandTestCase):
def test_registering(self):
# this test runs choice 2
cmd = self._get_cmd()
- inputs = RawInputs('2', 'tarek', 'tarek@ziade.org')
- register_module.raw_input = inputs.__call__
+ inputs = Inputs('2', 'tarek', 'tarek@ziade.org')
+ register_module.input = inputs.__call__
try:
# let's run the command
cmd.run()
finally:
- del register_module.raw_input
+ del register_module.input
# we should have send a request
self.assertEqual(len(self.conn.reqs), 1)
req = self.conn.reqs[0]
headers = dict(req.headers)
self.assertEqual(headers['Content-length'], '608')
- self.assertTrue('tarek' in req.data)
+ self.assertTrue((b'tarek') in req.data)
def test_password_reset(self):
# this test runs choice 3
cmd = self._get_cmd()
- inputs = RawInputs('3', 'tarek@ziade.org')
- register_module.raw_input = inputs.__call__
+ inputs = Inputs('3', 'tarek@ziade.org')
+ register_module.input = inputs.__call__
try:
# let's run the command
cmd.run()
finally:
- del register_module.raw_input
+ del register_module.input
# we should have send a request
self.assertEqual(len(self.conn.reqs), 1)
req = self.conn.reqs[0]
headers = dict(req.headers)
self.assertEqual(headers['Content-length'], '290')
- self.assertTrue('tarek' in req.data)
+ self.assertTrue((b'tarek') in req.data)
@unittest.skipUnless(docutils is not None, 'needs docutils')
def test_strict(self):
@@ -209,7 +210,7 @@ class RegisterTestCase(PyPIRCCommandTestCase):
# metadata are OK but long_description is broken
metadata = {'url': 'xxx', 'author': 'xxx',
- 'author_email': u'éxéxé',
+ 'author_email': 'éxéxé',
'name': 'xxx', 'version': 'xxx',
'long_description': 'title\n==\n\ntext'}
@@ -223,42 +224,42 @@ class RegisterTestCase(PyPIRCCommandTestCase):
cmd = self._get_cmd(metadata)
cmd.ensure_finalized()
cmd.strict = 1
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
+ inputs = Inputs('1', 'tarek', 'y')
+ register_module.input = inputs.__call__
# let's run the command
try:
cmd.run()
finally:
- del register_module.raw_input
+ del register_module.input
# strict is not by default
cmd = self._get_cmd()
cmd.ensure_finalized()
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
+ inputs = Inputs('1', 'tarek', 'y')
+ register_module.input = inputs.__call__
# let's run the command
try:
cmd.run()
finally:
- del register_module.raw_input
+ del register_module.input
# and finally a Unicode test (bug #12114)
- metadata = {'url': u'xxx', 'author': u'\u00c9ric',
- 'author_email': u'xxx', u'name': 'xxx',
- 'version': u'xxx',
- 'description': u'Something about esszet \u00df',
- 'long_description': u'More things about esszet \u00df'}
+ metadata = {'url': 'xxx', 'author': '\u00c9ric',
+ 'author_email': 'xxx', 'name': 'xxx',
+ 'version': 'xxx',
+ 'description': 'Something about esszet \u00df',
+ 'long_description': 'More things about esszet \u00df'}
cmd = self._get_cmd(metadata)
cmd.ensure_finalized()
cmd.strict = 1
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
+ inputs = Inputs('1', 'tarek', 'y')
+ register_module.input = inputs.__call__
# let's run the command
try:
cmd.run()
finally:
- del register_module.raw_input
+ del register_module.input
@unittest.skipUnless(docutils is not None, 'needs docutils')
def test_register_invalid_long_description(self):
@@ -270,9 +271,10 @@ class RegisterTestCase(PyPIRCCommandTestCase):
cmd = self._get_cmd(metadata)
cmd.ensure_finalized()
cmd.strict = True
- inputs = RawInputs('2', 'tarek', 'tarek@ziade.org')
- register_module.raw_input = inputs
- self.addCleanup(delattr, register_module, 'raw_input')
+ inputs = Inputs('2', 'tarek', 'tarek@ziade.org')
+ register_module.input = inputs
+ self.addCleanup(delattr, register_module, 'input')
+
self.assertRaises(DistutilsSetupError, cmd.run)
def test_check_metadata_deprecated(self):
diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py
index 7e7d98d096c..e6359d6a8af 100644
--- a/Lib/distutils/tests/test_sdist.py
+++ b/Lib/distutils/tests/test_sdist.py
@@ -6,21 +6,13 @@ import warnings
import zipfile
from os.path import join
from textwrap import dedent
-from test.test_support import captured_stdout, check_warnings, run_unittest
+from test.support import captured_stdout, check_warnings, run_unittest
-# zlib is not used here, but if it's not available
-# the tests that use zipfile may fail
try:
import zlib
+ ZLIB_SUPPORT = True
except ImportError:
- zlib = None
-
-try:
- import grp
- import pwd
- UID_GID_SUPPORT = True
-except ImportError:
- UID_GID_SUPPORT = False
+ ZLIB_SUPPORT = False
from distutils.command.sdist import sdist, show_formats
@@ -89,7 +81,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.dist_dir = 'dist'
return dist, cmd
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_prune_file_list(self):
# this test creates a project with some VCS dirs and an NFS rename
# file, then launches sdist to check they get pruned on all systems
@@ -132,7 +124,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
# making sure everything has been pruned correctly
self.assertEqual(len(content), 4)
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_make_distribution(self):
# check if tar and gzip are installed
@@ -167,29 +159,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
result.sort()
self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz'])
- @unittest.skipUnless(zlib, "requires zlib")
- def test_unicode_metadata_tgz(self):
- """
- Unicode name or version should not break building to tar.gz format.
- Reference issue #11638.
- """
-
- # create the sdist command with unicode parameters
- dist, cmd = self.get_cmd({'name': u'fake', 'version': u'1.0'})
-
- # create the sdist as gztar and run the command
- cmd.formats = ['gztar']
- cmd.ensure_finalized()
- cmd.run()
-
- # The command should have created the .tar.gz file
- dist_folder = join(self.tmp_dir, 'dist')
- result = os.listdir(dist_folder)
- self.assertEqual(result, ['fake-1.0.tar.gz'])
-
- os.remove(join(dist_folder, 'fake-1.0.tar.gz'))
-
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_add_defaults(self):
# http://bugs.python.org/issue2279
@@ -262,7 +232,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
f.close()
self.assertEqual(manifest, MANIFEST % {'sep': os.sep})
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_metadata_check_option(self):
# testing the `medata-check` option
dist, cmd = self.get_cmd(metadata={})
@@ -323,56 +293,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.formats = 'supazipa'
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.assertEqual(member.uid, 0)
- self.assertEqual(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.assertEqual(member.uid, os.getuid())
- finally:
- archive.close()
-
# the following tests make sure there is a nice error message instead
# of a traceback when parsing an invalid manifest template
@@ -399,7 +319,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
# this used to crash instead of raising a warning: #8286
self._check_template('include examples/')
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_get_file_list(self):
# make sure MANIFEST is recalculated
dist, cmd = self.get_cmd()
@@ -441,7 +361,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
self.assertEqual(len(manifest2), 6)
self.assertIn('doc2.txt', manifest2[-1])
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_manifest_marker(self):
# check that autogenerated MANIFESTs have a marker
dist, cmd = self.get_cmd()
@@ -458,7 +378,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
self.assertEqual(manifest[0],
'# file GENERATED by distutils, do NOT edit')
- @unittest.skipUnless(zlib, 'requires zlib')
+ @unittest.skipUnless(ZLIB_SUPPORT, "Need zlib support to run")
def test_manifest_comments(self):
# make sure comments don't cause exceptions or wrong includes
contents = dedent("""\
@@ -475,7 +395,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.run()
self.assertEqual(cmd.filelist.files, ['good.py'])
- @unittest.skipUnless(zlib, "requires zlib")
+ @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_manual_manifest(self):
# check that a MANIFEST without a marker is left alone
dist, cmd = self.get_cmd()
diff --git a/Lib/distutils/tests/test_spawn.py b/Lib/distutils/tests/test_spawn.py
index defa54d87f1..6c7eb20c471 100644
--- a/Lib/distutils/tests/test_spawn.py
+++ b/Lib/distutils/tests/test_spawn.py
@@ -2,7 +2,7 @@
import unittest
import os
import time
-from test.test_support import captured_stdout, run_unittest
+from test.support import captured_stdout, run_unittest
from distutils.spawn import _nt_quote_args
from distutils.spawn import spawn, find_executable
@@ -33,24 +33,22 @@ class SpawnTestCase(support.TempdirManager,
if os.name == 'posix':
exe = os.path.join(tmpdir, 'foo.sh')
self.write_file(exe, '#!/bin/sh\nexit 1')
- os.chmod(exe, 0777)
else:
exe = os.path.join(tmpdir, 'foo.bat')
self.write_file(exe, 'exit 1')
- os.chmod(exe, 0777)
+ os.chmod(exe, 0o777)
self.assertRaises(DistutilsExecError, spawn, [exe])
# now something that works
if os.name == 'posix':
exe = os.path.join(tmpdir, 'foo.sh')
self.write_file(exe, '#!/bin/sh\nexit 0')
- os.chmod(exe, 0777)
else:
exe = os.path.join(tmpdir, 'foo.bat')
self.write_file(exe, 'exit 0')
- os.chmod(exe, 0777)
+ os.chmod(exe, 0o777)
spawn([exe]) # should work without any error
def test_suite():
diff --git a/Lib/distutils/tests/test_sysconfig.py b/Lib/distutils/tests/test_sysconfig.py
index 49570c4ce50..fbe26bf65d6 100644
--- a/Lib/distutils/tests/test_sysconfig.py
+++ b/Lib/distutils/tests/test_sysconfig.py
@@ -1,12 +1,13 @@
"""Tests for distutils.sysconfig."""
import os
+import shutil
import test
import unittest
-import shutil
from distutils import sysconfig
+from distutils.ccompiler import get_default_compiler
from distutils.tests import support
-from test.test_support import TESTFN
+from test.support import TESTFN, run_unittest
class SysconfigTestCase(support.EnvironGuard,
unittest.TestCase):
@@ -21,11 +22,14 @@ class SysconfigTestCase(support.EnvironGuard,
super(SysconfigTestCase, self).tearDown()
def cleanup_testfn(self):
- path = test.test_support.TESTFN
- if os.path.isfile(path):
- os.remove(path)
- elif os.path.isdir(path):
- shutil.rmtree(path)
+ if os.path.isfile(TESTFN):
+ os.remove(TESTFN)
+ elif os.path.isdir(TESTFN):
+ shutil.rmtree(TESTFN)
+
+ 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):
lib_dir = sysconfig.get_python_lib()
@@ -34,9 +38,6 @@ class SysconfigTestCase(support.EnvironGuard,
# test for pythonxx.lib?
self.assertNotEqual(sysconfig.get_python_lib(),
sysconfig.get_python_lib(prefix=TESTFN))
- _sysconfig = __import__('sysconfig')
- res = sysconfig.get_python_lib(True, True)
- self.assertEqual(_sysconfig.get_path('platstdlib'), res)
def test_get_python_inc(self):
inc_dir = sysconfig.get_python_inc()
@@ -47,8 +48,33 @@ class SysconfigTestCase(support.EnvironGuard,
python_h = os.path.join(inc_dir, "Python.h")
self.assertTrue(os.path.isfile(python_h), python_h)
+ 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.assertEqual(comp.exes['archiver'], 'my_ar -arflags')
+
def test_parse_makefile_base(self):
- self.makefile = test.test_support.TESTFN
+ self.makefile = TESTFN
fd = open(self.makefile, 'w')
try:
fd.write(r"CONFIG_ARGS= '--arg1=optarg1' 'ENV=LIB'" '\n')
@@ -60,7 +86,7 @@ class SysconfigTestCase(support.EnvironGuard,
'OTHER': 'foo'})
def test_parse_makefile_literal_dollar(self):
- self.makefile = test.test_support.TESTFN
+ self.makefile = TESTFN
fd = open(self.makefile, 'w')
try:
fd.write(r"CONFIG_ARGS= '--arg1=optarg1' 'ENV=\$$LIB'" '\n')
@@ -72,6 +98,15 @@ class SysconfigTestCase(support.EnvironGuard,
'OTHER': 'foo'})
+ def test_sysconfig_module(self):
+ import sysconfig as global_sysconfig
+ self.assertEqual(global_sysconfig.get_config_var('CFLAGS'), sysconfig.get_config_var('CFLAGS'))
+ self.assertEqual(global_sysconfig.get_config_var('LDFLAGS'), sysconfig.get_config_var('LDFLAGS'))
+ self.assertEqual(global_sysconfig.get_config_var('LDSHARED'),sysconfig.get_config_var('LDSHARED'))
+ self.assertEqual(global_sysconfig.get_config_var('CC'), sysconfig.get_config_var('CC'))
+
+
+
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(SysconfigTestCase))
@@ -79,4 +114,4 @@ def test_suite():
if __name__ == '__main__':
- test.test_support.run_unittest(test_suite())
+ run_unittest(test_suite())
diff --git a/Lib/distutils/tests/test_text_file.py b/Lib/distutils/tests/test_text_file.py
index ce19cd4dcde..7e76240a9a3 100644
--- a/Lib/distutils/tests/test_text_file.py
+++ b/Lib/distutils/tests/test_text_file.py
@@ -3,7 +3,7 @@ import os
import unittest
from distutils.text_file import TextFile
from distutils.tests import support
-from test.test_support import run_unittest
+from test.support import run_unittest
TEST_DATA = """# test file
diff --git a/Lib/distutils/tests/test_unixccompiler.py b/Lib/distutils/tests/test_unixccompiler.py
index 40c908a24d0..1bff38e9eef 100644
--- a/Lib/distutils/tests/test_unixccompiler.py
+++ b/Lib/distutils/tests/test_unixccompiler.py
@@ -1,7 +1,7 @@
"""Tests for distutils.unixccompiler."""
import sys
import unittest
-from test.test_support import run_unittest
+from test.support import run_unittest
from distutils import sysconfig
from distutils.unixccompiler import UnixCCompiler
@@ -71,7 +71,7 @@ class UnixCCompilerTestCase(unittest.TestCase):
elif v == 'GNULD':
return 'yes'
sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-Wl,-R/foo')
+ self.assertEqual(self.cc.rpath_foo(), '-Wl,--enable-new-dtags,-R/foo')
# GCC non-GNULD
sys.platform = 'bar'
@@ -92,7 +92,7 @@ class UnixCCompilerTestCase(unittest.TestCase):
elif v == 'GNULD':
return 'yes'
sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-Wl,-R/foo')
+ self.assertEqual(self.cc.rpath_foo(), '-Wl,--enable-new-dtags,-R/foo')
# non-GCC GNULD
@@ -115,14 +115,6 @@ class UnixCCompilerTestCase(unittest.TestCase):
sysconfig.get_config_var = gcv
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(), '-R/foo')
-
-
def test_suite():
return unittest.makeSuite(UnixCCompilerTestCase)
diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py
index 99111999d87..4c6464a32e8 100644
--- a/Lib/distutils/tests/test_upload.py
+++ b/Lib/distutils/tests/test_upload.py
@@ -1,10 +1,9 @@
-# -*- encoding: utf8 -*-
"""Tests for distutils.command.upload."""
import os
import unittest
-from test.test_support import run_unittest
+import http.client as httpclient
+from test.support import run_unittest
-from distutils.command import upload as upload_mod
from distutils.command.upload import upload
from distutils.core import Distribution
@@ -38,37 +37,48 @@ index-servers =
[server1]
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):
- self.url = url
- if not isinstance(url, str):
- self.req = url
- else:
- self.req = None
- self.msg = 'OK'
+ def __init__(self):
+ self.requests = []
+ self.headers = []
+ self.body = ''
- def getcode(self):
- return 200
+ def __call__(self, netloc):
+ 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):
def setUp(self):
super(uploadTestCase, self).setUp()
- self.old_open = upload_mod.urlopen
- upload_mod.urlopen = self._urlopen
- self.last_open = None
+ self.old_class = httpclient.HTTPConnection
+ self.conn = httpclient.HTTPConnection = FakeConnection()
def tearDown(self):
- upload_mod.urlopen = self.old_open
+ httpclient.HTTPConnection = self.old_class
super(uploadTestCase, self).tearDown()
- def _urlopen(self, url):
- self.last_open = FakeOpen(url)
- return self.last_open
-
def test_finalize_options(self):
# new format
@@ -107,22 +117,19 @@ class uploadTestCase(PyPIRCCommandTestCase):
self.write_file(self.rc, PYPIRC_LONG_PASSWORD)
# lets run it
- pkg_dir, dist = self.create_dist(dist_files=dist_files, author=u'dédé')
+ pkg_dir, dist = self.create_dist(dist_files=dist_files)
cmd = upload(dist)
cmd.ensure_finalized()
cmd.run()
# what did we send ?
- self.assertIn('dédé', self.last_open.req.data)
- headers = dict(self.last_open.req.headers)
- self.assertEqual(headers['Content-length'], '2085')
+ headers = dict(self.conn.headers)
+ self.assertEqual(headers['Content-length'], '2087')
self.assertTrue(headers['Content-type'].startswith('multipart/form-data'))
- self.assertEqual(self.last_open.req.get_method(), 'POST')
- self.assertEqual(self.last_open.req.get_full_url(),
- 'http://pypi.python.org/pypi')
- self.assertTrue('xxx' in self.last_open.req.data)
- auth = self.last_open.req.headers['Authorization']
- self.assertFalse('\n' in auth)
+ self.assertFalse('\n' in headers['Authorization'])
+
+ self.assertEqual(self.conn.requests, [('POST', '/pypi')])
+ self.assertTrue((b'xxx') in self.conn.body)
def test_suite():
return unittest.makeSuite(uploadTestCase)
diff --git a/Lib/distutils/tests/test_util.py b/Lib/distutils/tests/test_util.py
index 67cd4cc7e61..1a06d4c4a14 100644
--- a/Lib/distutils/tests/test_util.py
+++ b/Lib/distutils/tests/test_util.py
@@ -1,12 +1,270 @@
"""Tests for distutils.util."""
+import os
import sys
import unittest
-from test.test_support import run_unittest
+from copy import copy
+from test.support import run_unittest
from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
-from distutils.util import byte_compile
+from distutils.util import (get_platform, convert_path, change_root,
+ check_environ, split_quoted, strtobool,
+ rfc822_escape, byte_compile)
+from distutils import util # used to patch _environ_checked
+from distutils.sysconfig import get_config_vars
+from distutils import sysconfig
+from distutils.tests import support
-class UtilTestCase(unittest.TestCase):
+class UtilTestCase(support.EnvironGuard, unittest.TestCase):
+
+ def setUp(self):
+ super(UtilTestCase, self).setUp()
+ # saving the environment
+ self.name = os.name
+ self.platform = sys.platform
+ self.version = sys.version
+ self.sep = os.sep
+ self.join = os.path.join
+ self.isabs = os.path.isabs
+ self.splitdrive = os.path.splitdrive
+ self._config_vars = copy(sysconfig._config_vars)
+
+ # patching os.uname
+ if hasattr(os, 'uname'):
+ self.uname = os.uname
+ self._uname = os.uname()
+ else:
+ self.uname = None
+ self._uname = None
+
+ os.uname = self._get_uname
+
+ def tearDown(self):
+ # getting back the environment
+ os.name = self.name
+ sys.platform = self.platform
+ sys.version = self.version
+ os.sep = self.sep
+ os.path.join = self.join
+ os.path.isabs = self.isabs
+ os.path.splitdrive = self.splitdrive
+ if self.uname is not None:
+ os.uname = self.uname
+ else:
+ del os.uname
+ sysconfig._config_vars = copy(self._config_vars)
+ super(UtilTestCase, self).tearDown()
+
+ def _set_uname(self, uname):
+ self._uname = uname
+
+ def _get_uname(self):
+ return self._uname
+
+ def test_get_platform(self):
+
+ # windows XP, 32bits
+ os.name = 'nt'
+ sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
+ '[MSC v.1310 32 bit (Intel)]')
+ sys.platform = 'win32'
+ self.assertEqual(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.assertEqual(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.assertEqual(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'))
+ get_config_vars()['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.assertEqual(get_platform(), 'macosx-10.3-i386')
+ finally:
+ sys.maxsize = cursize
+
+ # macbook with fat binaries (fat, universal or fat64)
+ get_config_vars()['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.assertEqual(get_platform(), 'macosx-10.4-fat')
+
+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.1'
+ self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(get_platform(), 'linux-i686')
+
+ # XXX more platforms to tests here
+
+ def test_convert_path(self):
+ # linux/mac
+ os.sep = '/'
+ def _join(path):
+ return '/'.join(path)
+ os.path.join = _join
+
+ self.assertEqual(convert_path('/home/to/my/stuff'),
+ '/home/to/my/stuff')
+
+ # win
+ os.sep = '\\'
+ def _join(*path):
+ return '\\'.join(path)
+ os.path.join = _join
+
+ self.assertRaises(ValueError, convert_path, '/home/to/my/stuff')
+ self.assertRaises(ValueError, convert_path, 'home/to/my/stuff/')
+
+ self.assertEqual(convert_path('home/to/my/stuff'),
+ 'home\\to\\my\\stuff')
+ self.assertEqual(convert_path('.'),
+ os.curdir)
+
+ def test_change_root(self):
+ # linux/mac
+ os.name = 'posix'
+ def _isabs(path):
+ return path[0] == '/'
+ os.path.isabs = _isabs
+ def _join(*path):
+ return '/'.join(path)
+ os.path.join = _join
+
+ self.assertEqual(change_root('/root', '/old/its/here'),
+ '/root/old/its/here')
+ self.assertEqual(change_root('/root', 'its/here'),
+ '/root/its/here')
+
+ # windows
+ os.name = 'nt'
+ def _isabs(path):
+ return path.startswith('c:\\')
+ os.path.isabs = _isabs
+ def _splitdrive(path):
+ if path.startswith('c:'):
+ return ('', path.replace('c:', ''))
+ return ('', path)
+ os.path.splitdrive = _splitdrive
+ def _join(*path):
+ return '\\'.join(path)
+ os.path.join = _join
+
+ self.assertEqual(change_root('c:\\root', 'c:\\old\\its\\here'),
+ 'c:\\root\\old\\its\\here')
+ self.assertEqual(change_root('c:\\root', 'its\\here'),
+ 'c:\\root\\its\\here')
+
+ # BugsBunny os (it's a great os)
+ os.name = 'BugsBunny'
+ self.assertRaises(DistutilsPlatformError,
+ change_root, 'c:\\root', 'its\\here')
+
+ # XXX platforms to be covered: os2, mac
+
+ def test_check_environ(self):
+ util._environ_checked = 0
+ if 'HOME' in os.environ:
+ del os.environ['HOME']
+
+ # posix without HOME
+ if os.name == 'posix': # this test won't run on windows
+ check_environ()
+ import pwd
+ self.assertEqual(os.environ['HOME'], pwd.getpwuid(os.getuid())[5])
+ else:
+ check_environ()
+
+ self.assertEqual(os.environ['PLAT'], get_platform())
+ self.assertEqual(util._environ_checked, 1)
+
+ def test_split_quoted(self):
+ self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
+ ['one', 'two', 'three', 'four'])
+
+ def test_strtobool(self):
+ yes = ('y', 'Y', 'yes', 'True', 't', 'true', 'True', 'On', 'on', '1')
+ no = ('n', 'no', 'f', 'false', 'off', '0', 'Off', 'No', 'N')
+
+ for y in yes:
+ self.assertTrue(strtobool(y))
+
+ for n in no:
+ self.assertTrue(not strtobool(n))
+
+ def test_rfc822_escape(self):
+ header = 'I am a\npoor\nlonesome\nheader\n'
+ res = rfc822_escape(header)
+ wanted = ('I am a%(8s)spoor%(8s)slonesome%(8s)s'
+ 'header%(8s)s') % {'8s': '\n'+8*' '}
+ self.assertEqual(res, wanted)
def test_dont_write_bytecode(self):
# makes sure byte_compile raise a DistutilsError
diff --git a/Lib/distutils/tests/test_version.py b/Lib/distutils/tests/test_version.py
index 2189956429f..15f14c7de3f 100644
--- a/Lib/distutils/tests/test_version.py
+++ b/Lib/distutils/tests/test_version.py
@@ -2,7 +2,7 @@
import unittest
from distutils.version import LooseVersion
from distutils.version import StrictVersion
-from test.test_support import run_unittest
+from test.support import run_unittest
class VersionTestCase(unittest.TestCase):
@@ -34,7 +34,7 @@ class VersionTestCase(unittest.TestCase):
for v1, v2, wanted in versions:
try:
- res = StrictVersion(v1).__cmp__(StrictVersion(v2))
+ res = StrictVersion(v1)._cmp(StrictVersion(v2))
except ValueError:
if wanted is ValueError:
continue
@@ -59,7 +59,7 @@ class VersionTestCase(unittest.TestCase):
for v1, v2, wanted in versions:
- res = LooseVersion(v1).__cmp__(LooseVersion(v2))
+ res = LooseVersion(v1)._cmp(LooseVersion(v2))
self.assertEqual(res, wanted,
'cmp(%s, %s) should be %s, got %s' %
(v1, v2, wanted, res))
diff --git a/Lib/distutils/tests/test_versionpredicate.py b/Lib/distutils/tests/test_versionpredicate.py
index 1d6c8d5a98d..28ae09dc205 100644
--- a/Lib/distutils/tests/test_versionpredicate.py
+++ b/Lib/distutils/tests/test_versionpredicate.py
@@ -4,7 +4,7 @@
import distutils.versionpredicate
import doctest
-from test.test_support import run_unittest
+from test.support import run_unittest
def test_suite():
return doctest.DocTestSuite(distutils.versionpredicate)
diff --git a/Lib/distutils/text_file.py b/Lib/distutils/text_file.py
index 09a798b1902..40b8484a685 100644
--- a/Lib/distutils/text_file.py
+++ b/Lib/distutils/text_file.py
@@ -4,13 +4,10 @@ provides the TextFile class, which gives an interface to text files
that (optionally) takes care of stripping comments, ignoring blank
lines, and joining lines with backslashes."""
-__revision__ = "$Id$"
-
-import sys
+import sys, os, io
class TextFile:
-
"""Provides a file-like object that takes care of all the things you
commonly want to do when processing a text file that has some
line-by-line syntax: strip comments (as long as "#" is your
@@ -33,7 +30,7 @@ class TextFile:
something that provides 'readline()' and 'close()' methods). It is
recommended that you supply at least 'filename', so that TextFile
can include it in warning messages. If 'file' is not supplied,
- TextFile creates its own using the 'open()' builtin.
+ TextFile creates its own using 'io.open()'.
The options are all boolean, and affect the value returned by
'readline()':
@@ -59,6 +56,8 @@ class TextFile:
collapse_join [default: false]
strip leading whitespace from lines that are joined to their
predecessor; only matters if (join_lines and not lstrip_ws)
+ errors [default: 'strict']
+ error handler used to decode the file content
Note that since 'rstrip_ws' can strip the trailing newline, the
semantics of 'readline()' must differ from those of the builtin file
@@ -73,34 +72,32 @@ class TextFile:
'rstrip_ws': 1,
'join_lines': 0,
'collapse_join': 0,
+ 'errors': 'strict',
}
- def __init__ (self, filename=None, file=None, **options):
+ def __init__(self, filename=None, file=None, **options):
"""Construct a new TextFile object. At least one of 'filename'
(a string) and 'file' (a file-like object) must be supplied.
They keyword argument options are described above and affect
the values returned by 'readline()'."""
-
if filename is None and file is None:
- raise RuntimeError, \
- "you must supply either or both of 'filename' and 'file'"
+ raise RuntimeError("you must supply either or both of 'filename' and 'file'")
# set values for all options -- either from client option hash
# or fallback to default_options
for opt in self.default_options.keys():
if opt in options:
- setattr (self, opt, options[opt])
-
+ setattr(self, opt, options[opt])
else:
- setattr (self, opt, self.default_options[opt])
+ setattr(self, opt, self.default_options[opt])
# sanity check client option hash
for opt in options.keys():
if opt not in self.default_options:
- raise KeyError, "invalid TextFile option '%s'" % opt
+ raise KeyError("invalid TextFile option '%s'" % opt)
if file is None:
- self.open (filename)
+ self.open(filename)
else:
self.filename = filename
self.file = file
@@ -111,43 +108,37 @@ class TextFile:
# 'unreadline()' operation
self.linebuf = []
-
- def open (self, filename):
+ def open(self, filename):
"""Open a new file named 'filename'. This overrides both the
'filename' and 'file' arguments to the constructor."""
-
self.filename = filename
- self.file = open (self.filename, 'r')
+ self.file = io.open(self.filename, 'r', errors=self.errors)
self.current_line = 0
-
- def close (self):
+ def close(self):
"""Close the current file and forget everything we know about it
(filename, current line number)."""
-
- self.file.close ()
+ self.file.close()
self.file = None
self.filename = None
self.current_line = None
-
- def gen_error (self, msg, line=None):
+ def gen_error(self, msg, line=None):
outmsg = []
if line is None:
line = self.current_line
outmsg.append(self.filename + ", ")
if isinstance(line, (list, tuple)):
- outmsg.append("lines %d-%d: " % tuple (line))
+ outmsg.append("lines %d-%d: " % tuple(line))
else:
outmsg.append("line %d: " % line)
outmsg.append(str(msg))
- return ''.join(outmsg)
-
+ return "".join(outmsg)
- def error (self, msg, line=None):
- raise ValueError, "error: " + self.gen_error(msg, line)
+ def error(self, msg, line=None):
+ raise ValueError("error: " + self.gen_error(msg, line))
- def warn (self, msg, line=None):
+ def warn(self, msg, line=None):
"""Print (to stderr) a warning message tied to the current logical
line in the current file. If the current logical line in the
file spans multiple physical lines, the warning refers to the
@@ -157,8 +148,7 @@ class TextFile:
line."""
sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n")
-
- def readline (self):
+ def readline(self):
"""Read and return a single logical line from the current file (or
from an internal buffer if lines have previously been "unread"
with 'unreadline()'). If the 'join_lines' option is true, this
@@ -168,7 +158,6 @@ class TextFile:
line(s) just read. Returns None on end-of-file, since the empty
string can occur if 'rstrip_ws' is true but 'strip_blanks' is
not."""
-
# If any "unread" lines waiting in 'linebuf', return the top
# one. (We don't actually buffer read-ahead data -- lines only
# get put in 'linebuf' if the client explicitly does an
@@ -180,10 +169,11 @@ class TextFile:
buildup_line = ''
- while 1:
+ while True:
# read the line, make it None if EOF
line = self.file.readline()
- if line == '': line = None
+ if line == '':
+ line = None
if self.strip_comments and line:
@@ -196,7 +186,7 @@ class TextFile:
# lurking in there) and otherwise leave the line alone.
pos = line.find("#")
- if pos == -1: # no "#" -- no comments
+ if pos == -1: # no "#" -- no comments
pass
# It's definitely a comment -- either "#" is the first
@@ -220,17 +210,15 @@ class TextFile:
# result in "hello there".
if line.strip() == "":
continue
-
- else: # it's an escaped "#"
+ else: # it's an escaped "#"
line = line.replace("\\#", "#")
-
# did previous line end with a backslash? then accumulate
if self.join_lines and buildup_line:
# oops: end of file
if line is None:
- self.warn ("continuation line immediately precedes "
- "end-of-file")
+ self.warn("continuation line immediately precedes "
+ "end-of-file")
return buildup_line
if self.collapse_join:
@@ -242,10 +230,10 @@ class TextFile:
self.current_line[1] = self.current_line[1] + 1
else:
self.current_line = [self.current_line,
- self.current_line+1]
+ self.current_line + 1]
# just an ordinary line, read it as usual
else:
- if line is None: # eof
+ if line is None: # eof
return None
# still have to be careful about incrementing the line number!
@@ -254,7 +242,6 @@ class TextFile:
else:
self.current_line = self.current_line + 1
-
# strip whitespace however the client wants (leading and
# trailing, or one or the other, or neither)
if self.lstrip_ws and self.rstrip_ws:
@@ -281,24 +268,18 @@ class TextFile:
# well, I guess there's some actual content there: return it
return line
- # readline ()
-
-
- def readlines (self):
+ def readlines(self):
"""Read and return the list of all logical lines remaining in the
current file."""
-
lines = []
- while 1:
+ while True:
line = self.readline()
if line is None:
return lines
- lines.append (line)
+ lines.append(line)
-
- def unreadline (self, line):
+ def unreadline(self, line):
"""Push 'line' (a string) onto an internal buffer that will be
checked by future 'readline()' calls. Handy for implementing
a parser with line-at-a-time lookahead."""
-
- self.linebuf.append (line)
+ self.linebuf.append(line)
diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py
index c49ac9ba918..c70a3cc555c 100644
--- a/Lib/distutils/unixccompiler.py
+++ b/Lib/distutils/unixccompiler.py
@@ -13,10 +13,7 @@ the "typical" Unix-style command-line C compiler:
* link shared library handled by 'cc -shared'
"""
-__revision__ = "$Id$"
-
import os, sys, re
-from types import StringType, NoneType
from distutils import sysconfig
from distutils.dep_util import newer
@@ -50,7 +47,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args):
build, without a way to remove an architecture. Furthermore GCC will
barf if multiple '-isysroot' arguments are present.
"""
- stripArch = stripSysroot = 0
+ stripArch = stripSysroot = False
compiler_so = list(compiler_so)
kernel_version = os.uname()[2] # 8.4.3
@@ -65,7 +62,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args):
stripSysroot = '-isysroot' in cc_args
if stripArch or 'ARCHFLAGS' in os.environ:
- while 1:
+ while True:
try:
index = compiler_so.index('-arch')
# Strip this argument and the next one:
@@ -142,11 +139,10 @@ class UnixCCompiler(CCompiler):
if sys.platform == "cygwin":
exe_extension = ".exe"
- def preprocess(self, source,
- output_file=None, macros=None, include_dirs=None,
- extra_preargs=None, extra_postargs=None):
- ignore, macros, include_dirs = \
- self._fix_compile_args(None, macros, include_dirs)
+ def preprocess(self, source, output_file=None, macros=None,
+ include_dirs=None, extra_preargs=None, extra_postargs=None):
+ fixed_args = self._fix_compile_args(None, macros, include_dirs)
+ ignore, macros, include_dirs = fixed_args
pp_opts = gen_preprocess_options(macros, include_dirs)
pp_args = self.preprocessor + pp_opts
if output_file:
@@ -166,8 +162,8 @@ class UnixCCompiler(CCompiler):
self.mkpath(os.path.dirname(output_file))
try:
self.spawn(pp_args)
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
compiler_so = self.compiler_so
@@ -176,8 +172,8 @@ class UnixCCompiler(CCompiler):
try:
self.spawn(compiler_so + cc_args + [src, '-o', obj] +
extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
def create_static_lib(self, objects, output_libname,
output_dir=None, debug=0, target_lang=None):
@@ -200,8 +196,8 @@ class UnixCCompiler(CCompiler):
if self.ranlib:
try:
self.spawn(self.ranlib + [output_filename])
- except DistutilsExecError, msg:
- raise LibError, msg
+ except DistutilsExecError as msg:
+ raise LibError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
@@ -211,13 +207,14 @@ class UnixCCompiler(CCompiler):
export_symbols=None, debug=0, extra_preargs=None,
extra_postargs=None, build_temp=None, target_lang=None):
objects, output_dir = self._fix_object_args(objects, output_dir)
- libraries, library_dirs, runtime_library_dirs = \
- self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
+ fixed_args = self._fix_lib_args(libraries, library_dirs,
+ runtime_library_dirs)
+ libraries, library_dirs, runtime_library_dirs = fixed_args
lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
libraries)
- if type(output_dir) not in (StringType, NoneType):
- raise TypeError, "'output_dir' must be a string or None"
+ if not isinstance(output_dir, (str, type(None))):
+ raise TypeError("'output_dir' must be a string or None")
if output_dir is not None:
output_filename = os.path.join(output_dir, output_filename)
@@ -246,16 +243,15 @@ class UnixCCompiler(CCompiler):
if os.path.basename(linker[0]) == "env":
i = 1
while '=' in linker[i]:
- i = i + 1
-
+ i += 1
linker[i] = self.compiler_cxx[i]
if sys.platform == 'darwin':
linker = _darwin_compiler_fixup(linker, ld_args)
self.spawn(linker + ld_args)
- except DistutilsExecError, msg:
- raise LinkError, msg
+ except DistutilsExecError as msg:
+ raise LinkError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
@@ -276,8 +272,9 @@ class UnixCCompiler(CCompiler):
# Linkers on different platforms need different options to
# specify that directories need to be added to the list of
# directories searched for dependencies when a dynamic library
- # is sought. GCC has to be told to pass the -R option through
- # to the linker, whereas other compilers just know this.
+ # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
+ # be told to pass the -R option through to the linker, whereas
+ # other compilers and gcc on other systems just know this.
# Other compilers may need something slightly different. At
# this time, there's no way to determine this information from
# the configuration data stored in the Python installation, so
@@ -292,10 +289,23 @@ class UnixCCompiler(CCompiler):
return ["+s", "-L" + dir]
elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
return ["-rpath", dir]
- elif self._is_gcc(compiler):
- return "-Wl,-R" + dir
else:
- return "-R" + dir
+ if 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
+ 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):
return "-l" + lib
diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py
index 0c24e8ca3e1..bce840274dc 100644
--- a/Lib/distutils/util.py
+++ b/Lib/distutils/util.py
@@ -4,9 +4,11 @@ Miscellaneous utility functions -- anything that doesn't fit into
one of the other *util.py modules.
"""
-__revision__ = "$Id$"
-
-import sys, os, string, re
+import os
+import re
+import imp
+import sys
+import string
from distutils.errors import DistutilsPlatformError
from distutils.dep_util import newer
from distutils.spawn import spawn
@@ -40,14 +42,14 @@ def get_platform ():
if os.name == 'nt':
# sniff sys.version for architecture.
prefix = " bit ("
- i = string.find(sys.version, prefix)
+ i = sys.version.find(prefix)
if i == -1:
return sys.platform
- j = string.find(sys.version, ")", i)
+ j = sys.version.find(")", i)
look = sys.version[i+len(prefix):j].lower()
- if look=='amd64':
+ if look == 'amd64':
return 'win-amd64'
- if look=='itanium':
+ if look == 'itanium':
return 'win-ia64'
return sys.platform
@@ -62,10 +64,9 @@ def get_platform ():
# Convert the OS name to lowercase, remove '/' characters
# (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
- osname = string.lower(osname)
- osname = string.replace(osname, '/', '')
- machine = string.replace(machine, ' ', '_')
- machine = string.replace(machine, '/', '-')
+ osname = osname.lower().replace('/', '')
+ machine = machine.replace(' ', '_')
+ machine = machine.replace('/', '-')
if osname[:5] == "linux":
# At least on Linux/Intel, 'machine' is the processor --
@@ -80,7 +81,7 @@ def get_platform ():
# bootstrap problem. We use a dict to get an error
# if some suspicious happens.
bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
- machine += ".%s" % bitness[sys.maxint]
+ machine += ".%s" % bitness[sys.maxsize]
# fall through to standard osname-release-machine representation
elif osname[:4] == "irix": # could be "irix64"!
return "%s-%s" % (osname, release)
@@ -88,7 +89,7 @@ def get_platform ():
return "%s-%s.%s" % (osname, version, release)
elif osname[:6] == "cygwin":
osname = "cygwin"
- rel_re = re.compile (r'[\d.]+')
+ rel_re = re.compile (r'[\d.]+', re.ASCII)
m = rel_re.match(release)
if m:
release = m.group()
@@ -171,7 +172,7 @@ def get_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.maxint >= 2**32:
+ if sys.maxsize >= 2**32:
machine = 'x86_64'
elif machine in ('PowerPC', 'Power_Macintosh'):
@@ -179,7 +180,7 @@ def get_platform ():
machine = 'ppc'
# See 'i386' case
- if sys.maxint >= 2**32:
+ if sys.maxsize >= 2**32:
machine = 'ppc64'
return "%s-%s-%s" % (osname, release, machine)
@@ -201,11 +202,11 @@ def convert_path (pathname):
if not pathname:
return pathname
if pathname[0] == '/':
- raise ValueError, "path '%s' cannot be absolute" % pathname
+ raise ValueError("path '%s' cannot be absolute" % pathname)
if pathname[-1] == '/':
- raise ValueError, "path '%s' cannot end with '/'" % pathname
+ raise ValueError("path '%s' cannot end with '/'" % pathname)
- paths = string.split(pathname, '/')
+ paths = pathname.split('/')
while '.' in paths:
paths.remove('.')
if not paths:
@@ -240,8 +241,7 @@ def change_root (new_root, pathname):
return os.path.join(new_root, path)
else:
- raise DistutilsPlatformError, \
- "nothing known about platform '%s'" % os.name
+ raise DistutilsPlatformError("nothing known about platform '%s'" % os.name)
_environ_checked = 0
@@ -286,8 +286,8 @@ def subst_vars (s, local_vars):
try:
return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
- except KeyError, var:
- raise ValueError, "invalid variable '$%s'" % var
+ except KeyError as var:
+ raise ValueError("invalid variable '$%s'" % var)
# subst_vars ()
@@ -309,7 +309,7 @@ def grok_environment_error (exc, prefix="error: "):
# include the filename in the exception object!
error = prefix + "%s" % exc.strerror
else:
- error = prefix + str(exc[-1])
+ error = prefix + str(exc.args[-1])
return error
@@ -338,7 +338,7 @@ def split_quoted (s):
# bit of a brain-bender to get it working right, though...
if _wordchars_re is None: _init_regex()
- s = string.strip(s)
+ s = s.strip()
words = []
pos = 0
@@ -351,7 +351,7 @@ def split_quoted (s):
if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
words.append(s[:end]) # we definitely have a word delimiter
- s = string.lstrip(s[end:])
+ s = s[end:].lstrip()
pos = 0
elif s[end] == '\\': # preserve whatever is being escaped;
@@ -365,12 +365,10 @@ def split_quoted (s):
elif s[end] == '"': # slurp doubly-quoted string
m = _dquote_re.match(s, end)
else:
- raise RuntimeError, \
- "this can't happen (bad char '%c')" % s[end]
+ raise RuntimeError("this can't happen (bad char '%c')" % s[end])
if m is None:
- raise ValueError, \
- "bad string (mismatched %s quotes?)" % s[end]
+ raise ValueError("bad string (mismatched %s quotes?)" % s[end])
(beg, end) = m.span()
s = s[:beg] + s[beg+1:end-1] + s[end:]
@@ -411,13 +409,13 @@ def strtobool (val):
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
'val' is anything else.
"""
- val = string.lower(val)
+ val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
return 1
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return 0
else:
- raise ValueError, "invalid truth value %r" % (val,)
+ raise ValueError("invalid truth value %r" % (val,))
def byte_compile (py_files,
@@ -426,9 +424,9 @@ def byte_compile (py_files,
verbose=1, dry_run=0,
direct=None):
"""Byte-compile a collection of Python source files to either .pyc
- 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.
- 'optimize' must be one of the following:
+ or .pyo files in a __pycache__ subdirectory. 'py_files' is a list
+ of files to compile; any files that don't end in ".py" are silently
+ skipped. 'optimize' must be one of the following:
0 - don't optimize (generate .pyc)
1 - normal optimization (like "python -O")
2 - extra optimization (like "python -OO")
@@ -505,7 +503,7 @@ files = [
#if prefix:
# prefix = os.path.abspath(prefix)
- script.write(string.join(map(repr, py_files), ",\n") + "]\n")
+ script.write(",\n".join(map(repr, py_files)) + "]\n")
script.write("""
byte_compile(files, optimize=%r, force=%r,
prefix=%r, base_dir=%r,
@@ -540,12 +538,14 @@ byte_compile(files, optimize=%r, force=%r,
# Terminology from the py_compile module:
# cfile - byte-compiled file
# dfile - purported source filename (same as 'file' by default)
- cfile = file + (__debug__ and "c" or "o")
+ if optimize >= 0:
+ cfile = imp.cache_from_source(file, debug_override=not optimize)
+ else:
+ cfile = imp.cache_from_source(file)
dfile = file
if prefix:
if file[:len(prefix)] != prefix:
- raise ValueError, \
- ("invalid prefix: filename %r doesn't start with %r"
+ raise ValueError("invalid prefix: filename %r doesn't start with %r"
% (file, prefix))
dfile = dfile[len(prefix):]
if base_dir:
@@ -567,6 +567,87 @@ def rfc822_escape (header):
"""Return a version of the string escaped for inclusion in an
RFC-822 header, by ensuring there are 8 spaces space after each newline.
"""
- lines = string.split(header, '\n')
- header = string.join(lines, '\n' + 8*' ')
- return header
+ lines = header.split('\n')
+ sep = '\n' + 8 * ' '
+ return sep.join(lines)
+
+# 2to3 support
+
+def run_2to3(files, fixer_names=None, options=None, explicit=None):
+ """Invoke 2to3 on a list of Python files.
+ The files should all come from the build area, as the
+ modification is done in-place. To reduce the build time,
+ only files modified since the last invocation of this
+ function should be passed in the files argument."""
+
+ if not files:
+ return
+
+ # Make this class local, to delay import of 2to3
+ from lib2to3.refactor import RefactoringTool, get_fixers_from_package
+ class DistutilsRefactoringTool(RefactoringTool):
+ def log_error(self, msg, *args, **kw):
+ log.error(msg, *args)
+
+ def log_message(self, msg, *args):
+ log.info(msg, *args)
+
+ def log_debug(self, msg, *args):
+ log.debug(msg, *args)
+
+ if fixer_names is None:
+ fixer_names = get_fixers_from_package('lib2to3.fixes')
+ r = DistutilsRefactoringTool(fixer_names, options=options)
+ r.refactor(files, write=True)
+
+def copydir_run_2to3(src, dest, template=None, fixer_names=None,
+ options=None, explicit=None):
+ """Recursively copy a directory, only copying new and changed files,
+ running run_2to3 over all newly copied Python modules afterward.
+
+ If you give a template string, it's parsed like a MANIFEST.in.
+ """
+ from distutils.dir_util import mkpath
+ from distutils.file_util import copy_file
+ from distutils.filelist import FileList
+ filelist = FileList()
+ curdir = os.getcwd()
+ os.chdir(src)
+ try:
+ filelist.findall()
+ finally:
+ os.chdir(curdir)
+ filelist.files[:] = filelist.allfiles
+ if template:
+ for line in template.splitlines():
+ line = line.strip()
+ if not line: continue
+ filelist.process_template_line(line)
+ copied = []
+ for filename in filelist.files:
+ outname = os.path.join(dest, filename)
+ mkpath(os.path.dirname(outname))
+ res = copy_file(os.path.join(src, filename), outname, update=1)
+ if res[1]: copied.append(outname)
+ run_2to3([fn for fn in copied if fn.lower().endswith('.py')],
+ fixer_names=fixer_names, options=options, explicit=explicit)
+ return copied
+
+class Mixin2to3:
+ '''Mixin class for commands that run 2to3.
+ To configure 2to3, setup scripts may either change
+ the class variables, or inherit from individual commands
+ to override how 2to3 is invoked.'''
+
+ # provide list of fixers to run;
+ # defaults to all from lib2to3.fixers
+ fixer_names = None
+
+ # options dictionary
+ options = None
+
+ # list of fixers to invoke even though they are marked as explicit
+ explicit = None
+
+ def run_2to3(self, files):
+ return run_2to3(files, self.fixer_names, self.options, self.explicit)
diff --git a/Lib/distutils/version.py b/Lib/distutils/version.py
index 0fb5b6e2041..ebcab84e4e2 100644
--- a/Lib/distutils/version.py
+++ b/Lib/distutils/version.py
@@ -21,18 +21,18 @@ Every version number class implements the following interface:
an equivalent string -- ie. one that will generate an equivalent
version number instance)
* __repr__ generates Python code to recreate the version number instance
- * __cmp__ compares the current instance with either another instance
+ * _cmp compares the current instance with either another instance
of the same class or a string (which will be parsed to an instance
of the same class, thus must follow the same rules)
"""
-import string, re
-from types import StringType
+import re
class Version:
"""Abstract base class for version numbering classes. Just provides
constructor (__init__) and reproducer (__repr__), because those
- seem to be the same for all version numbering classes.
+ seem to be the same for all version numbering classes; and route
+ rich comparisons to _cmp.
"""
def __init__ (self, vstring=None):
@@ -42,6 +42,42 @@ class Version:
def __repr__ (self):
return "%s ('%s')" % (self.__class__.__name__, str(self))
+ def __eq__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c == 0
+
+ def __ne__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c != 0
+
+ def __lt__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c < 0
+
+ def __le__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c <= 0
+
+ def __gt__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c > 0
+
+ def __ge__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c >= 0
+
# Interface for version-number classes -- must be implemented
# by the following classes (the concrete ones -- Version should
@@ -55,7 +91,7 @@ class Version:
# (if not identical to) the string supplied to parse
# __repr__ (self) - generate Python code to recreate
# the instance
-# __cmp__ (self, other) - compare two version numbers ('other' may
+# _cmp (self, other) - compare two version numbers ('other' may
# be an unparsed version string, or another
# instance of your version class)
@@ -98,24 +134,24 @@ class StrictVersion (Version):
"""
version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$',
- re.VERBOSE)
+ re.VERBOSE | re.ASCII)
def parse (self, vstring):
match = self.version_re.match(vstring)
if not match:
- raise ValueError, "invalid version number '%s'" % vstring
+ raise ValueError("invalid version number '%s'" % vstring)
(major, minor, patch, prerelease, prerelease_num) = \
match.group(1, 2, 4, 5, 6)
if patch:
- self.version = tuple(map(string.atoi, [major, minor, patch]))
+ self.version = tuple(map(int, [major, minor, patch]))
else:
- self.version = tuple(map(string.atoi, [major, minor]) + [0])
+ self.version = tuple(map(int, [major, minor])) + (0,)
if prerelease:
- self.prerelease = (prerelease[0], string.atoi(prerelease_num))
+ self.prerelease = (prerelease[0], int(prerelease_num))
else:
self.prerelease = None
@@ -123,9 +159,9 @@ class StrictVersion (Version):
def __str__ (self):
if self.version[2] == 0:
- vstring = string.join(map(str, self.version[0:2]), '.')
+ vstring = '.'.join(map(str, self.version[0:2]))
else:
- vstring = string.join(map(str, self.version), '.')
+ vstring = '.'.join(map(str, self.version))
if self.prerelease:
vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
@@ -133,30 +169,39 @@ class StrictVersion (Version):
return vstring
- def __cmp__ (self, other):
- if isinstance(other, StringType):
+ def _cmp (self, other):
+ if isinstance(other, str):
other = StrictVersion(other)
- compare = cmp(self.version, other.version)
- if (compare == 0): # have to compare prerelease
-
- # case 1: neither has prerelease; they're equal
- # case 2: self has prerelease, other doesn't; other is greater
- # case 3: self doesn't have prerelease, other does: self is greater
- # case 4: both have prerelease: must compare them!
+ if self.version != other.version:
+ # numeric versions don't match
+ # prerelease stuff doesn't matter
+ if self.version < other.version:
+ return -1
+ else:
+ return 1
- if (not self.prerelease and not other.prerelease):
+ # have to compare prerelease
+ # case 1: neither has prerelease; they're equal
+ # case 2: self has prerelease, other doesn't; other is greater
+ # case 3: self doesn't have prerelease, other does: self is greater
+ # case 4: both have prerelease: must compare them!
+
+ if (not self.prerelease and not other.prerelease):
+ return 0
+ elif (self.prerelease and not other.prerelease):
+ return -1
+ elif (not self.prerelease and other.prerelease):
+ return 1
+ elif (self.prerelease and other.prerelease):
+ if self.prerelease == other.prerelease:
return 0
- elif (self.prerelease and not other.prerelease):
+ elif self.prerelease < other.prerelease:
return -1
- elif (not self.prerelease and other.prerelease):
+ else:
return 1
- elif (self.prerelease and other.prerelease):
- return cmp(self.prerelease, other.prerelease)
-
- else: # numeric versions don't match --
- return compare # prerelease stuff doesn't matter
-
+ else:
+ assert False, "never get here"
# end class StrictVersion
@@ -270,11 +315,11 @@ class LooseVersion (Version):
# from the parsed tuple -- so I just store the string here for
# use by __str__
self.vstring = vstring
- components = filter(lambda x: x and x != '.',
- self.component_re.split(vstring))
- for i in range(len(components)):
+ components = [x for x in self.component_re.split(vstring)
+ if x and x != '.']
+ for i, obj in enumerate(components):
try:
- components[i] = int(components[i])
+ components[i] = int(obj)
except ValueError:
pass
@@ -289,11 +334,16 @@ class LooseVersion (Version):
return "LooseVersion ('%s')" % str(self)
- def __cmp__ (self, other):
- if isinstance(other, StringType):
+ def _cmp (self, other):
+ if isinstance(other, str):
other = LooseVersion(other)
- return cmp(self.version, other.version)
+ if self.version == other.version:
+ return 0
+ if self.version < other.version:
+ return -1
+ if self.version > other.version:
+ return 1
# end class LooseVersion
diff --git a/Lib/distutils/versionpredicate.py b/Lib/distutils/versionpredicate.py
index ba8b6c021b2..b0dd9f45bff 100644
--- a/Lib/distutils/versionpredicate.py
+++ b/Lib/distutils/versionpredicate.py
@@ -5,7 +5,8 @@ import distutils.version
import operator
-re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)")
+re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)",
+ re.ASCII)
# (package) (rest)
re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses
@@ -40,7 +41,7 @@ class VersionPredicate:
The str() of a `VersionPredicate` provides a normalized
human-readable version of the expression::
- >>> print v
+ >>> print(v)
pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3)
The `satisfied_by()` method can be used to determine with a given
@@ -153,7 +154,8 @@ def split_provision(value):
global _provision_rx
if _provision_rx is None:
_provision_rx = re.compile(
- "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$")
+ "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$",
+ re.ASCII)
value = value.strip()
m = _provision_rx.match(value)
if not m: