summaryrefslogtreecommitdiff
path: root/distutils2
diff options
context:
space:
mode:
authorAlexis Metaireau <alexis@notmyidea.org>2011-02-13 23:07:59 +0000
committerAlexis Metaireau <alexis@notmyidea.org>2011-02-13 23:07:59 +0000
commitd08c2859eb32dc4278306cb93a25af68467299fc (patch)
tree507755fc1f3d2ac8ef9de311203bd861945a7f9a /distutils2
parent0ec26e45aed308dc6ea92361fe6ad7b6aa287e27 (diff)
parentdc5bb384d38de36ad539fe62343f117cfca74df3 (diff)
downloaddisutils2-d08c2859eb32dc4278306cb93a25af68467299fc.tar.gz
Merging the resource branch !
Diffstat (limited to 'distutils2')
-rw-r--r--distutils2/_backport/shutil.py2
-rw-r--r--distutils2/command/bdist_dumb.py13
-rw-r--r--distutils2/command/bdist_wininst.py2
-rw-r--r--distutils2/command/clean.py4
-rw-r--r--distutils2/command/cmd.py4
-rw-r--r--distutils2/command/config.py2
-rw-r--r--distutils2/command/install_data.py2
-rw-r--r--distutils2/command/install_dist.py2
-rw-r--r--distutils2/command/register.py17
-rw-r--r--distutils2/command/sdist.py12
-rw-r--r--distutils2/command/upload.py4
-rw-r--r--distutils2/compiler/bcppcompiler.py5
-rw-r--r--distutils2/compiler/ccompiler.py2
-rw-r--r--distutils2/compiler/msvc9compiler.py10
-rw-r--r--distutils2/compiler/msvccompiler.py11
-rw-r--r--distutils2/compiler/unixccompiler.py6
-rw-r--r--distutils2/config.py8
-rw-r--r--distutils2/dist.py24
-rw-r--r--distutils2/errors.py9
-rw-r--r--distutils2/index/__init__.py2
-rw-r--r--distutils2/index/dist.py5
-rw-r--r--distutils2/index/mirrors.py14
-rw-r--r--distutils2/index/simple.py7
-rw-r--r--distutils2/index/wrapper.py5
-rw-r--r--distutils2/index/xmlrpc.py3
-rw-r--r--distutils2/install.py47
-rw-r--r--distutils2/manifest.py53
-rw-r--r--distutils2/metadata.py138
-rw-r--r--distutils2/run.py8
-rw-r--r--distutils2/tests/support.py3
-rw-r--r--distutils2/tests/test_command_build_py.py2
-rw-r--r--distutils2/tests/test_command_install_lib.py2
-rw-r--r--distutils2/tests/test_command_sdist.py8
-rw-r--r--distutils2/tests/test_index_dist.py22
-rw-r--r--distutils2/tests/test_manifest.py11
-rw-r--r--distutils2/tests/test_metadata.py19
-rw-r--r--distutils2/tests/test_mkcfg.py7
-rw-r--r--distutils2/util.py58
38 files changed, 281 insertions, 272 deletions
diff --git a/distutils2/_backport/shutil.py b/distutils2/_backport/shutil.py
index 21f94fb..ef34e43 100644
--- a/distutils2/_backport/shutil.py
+++ b/distutils2/_backport/shutil.py
@@ -408,7 +408,7 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
from distutils2._backport import tarfile
if logger is not None:
- logger.info('Creating tar archive')
+ logger.info('creating tar archive')
uid = _get_uid(owner)
gid = _get_gid(group)
diff --git a/distutils2/command/bdist_dumb.py b/distutils2/command/bdist_dumb.py
index 8aed45c..0ca232f 100644
--- a/distutils2/command/bdist_dumb.py
+++ b/distutils2/command/bdist_dumb.py
@@ -87,7 +87,7 @@ class bdist_dumb (Command):
install.skip_build = self.skip_build
install.warn_dir = 0
- logger.info("installing to %s" % self.bdist_dir)
+ logger.info("installing to %s", self.bdist_dir)
self.run_command('install_dist')
# And make an archive relative to the root of the
@@ -106,11 +106,10 @@ 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 "
- "base and platbase are different (%s, %s)"
- % (repr(install.install_base),
- repr(install.install_platbase)))
+ raise DistutilsPlatformError(
+ "can't make a dumb built distribution where base and "
+ "platbase are different (%r, %r)" %
+ (install.install_base, install.install_platbase))
else:
archive_root = os.path.join(
self.bdist_dir,
@@ -129,7 +128,7 @@ class bdist_dumb (Command):
if not self.keep_temp:
if self.dry_run:
- logger.info('Removing %s' % self.bdist_dir)
+ logger.info('removing %s', self.bdist_dir)
else:
rmtree(self.bdist_dir)
diff --git a/distutils2/command/bdist_wininst.py b/distutils2/command/bdist_wininst.py
index 40f151f..5932d50 100644
--- a/distutils2/command/bdist_wininst.py
+++ b/distutils2/command/bdist_wininst.py
@@ -192,7 +192,7 @@ class bdist_wininst (Command):
if not self.keep_temp:
if self.dry_run:
- logger.info('Removing %s' % self.bdist_dir)
+ logger.info('removing %s', self.bdist_dir)
else:
rmtree(self.bdist_dir)
diff --git a/distutils2/command/clean.py b/distutils2/command/clean.py
index 295cfac..3904085 100644
--- a/distutils2/command/clean.py
+++ b/distutils2/command/clean.py
@@ -48,7 +48,7 @@ class clean(Command):
# gone)
if os.path.exists(self.build_temp):
if self.dry_run:
- logger.info('Removing %s' % self.build_temp)
+ logger.info('removing %s', self.build_temp)
else:
rmtree(self.build_temp)
else:
@@ -62,7 +62,7 @@ class clean(Command):
self.build_scripts):
if os.path.exists(directory):
if self.dry_run:
- logger.info('Removing %s' % directory)
+ logger.info('removing %s', directory)
else:
rmtree(directory)
else:
diff --git a/distutils2/command/cmd.py b/distutils2/command/cmd.py
index 0e4d99e..9cfc5d9 100644
--- a/distutils2/command/cmd.py
+++ b/distutils2/command/cmd.py
@@ -182,6 +182,7 @@ class Command(object):
raise RuntimeError(
"abstract method -- subclass %s must override" % self.__class__)
+ # TODO remove this method, just use logging.info
def announce(self, msg, level=logging.INFO):
"""If the current verbosity level is of greater than or equal to
'level' print 'msg' to stdout.
@@ -363,8 +364,9 @@ class Command(object):
# -- External world manipulation -----------------------------------
+ # TODO remove this method, just use logging.warn
def warn(self, msg):
- logger.warning("warning: %s: %s\n" % (self.get_command_name(), msg))
+ logger.warning("warning: %s: %s\n", self.get_command_name(), msg)
def execute(self, func, args, msg=None, level=1):
util.execute(func, args, msg, dry_run=self.dry_run)
diff --git a/distutils2/command/config.py b/distutils2/command/config.py
index 0f4ae9f..411ad26 100644
--- a/distutils2/command/config.py
+++ b/distutils2/command/config.py
@@ -345,7 +345,7 @@ def dump_file(filename, head=None):
If head is not None, will be dumped before the file content.
"""
if head is None:
- logger.info('%s' % filename)
+ logger.info(filename)
else:
logger.info(head)
file = open(filename)
diff --git a/distutils2/command/install_data.py b/distutils2/command/install_data.py
index d4f8143..1440753 100644
--- a/distutils2/command/install_data.py
+++ b/distutils2/command/install_data.py
@@ -77,4 +77,4 @@ class install_data(Command):
return self.outfiles
def get_resources_out(self):
- return self.data_files_out \ No newline at end of file
+ return self.data_files_out
diff --git a/distutils2/command/install_dist.py b/distutils2/command/install_dist.py
index fb3fd2a..baa5991 100644
--- a/distutils2/command/install_dist.py
+++ b/distutils2/command/install_dist.py
@@ -422,7 +422,7 @@ class install_dist(Command):
else:
opt_name = opt_name.replace('-', '_')
val = getattr(self, opt_name)
- logger.debug(" %s: %s" % (opt_name, val))
+ logger.debug(" %s: %s", opt_name, val)
def select_scheme(self, name):
"""Set the install directories by applying the install schemes."""
diff --git a/distutils2/command/register.py b/distutils2/command/register.py
index 74f708c..f051622 100644
--- a/distutils2/command/register.py
+++ b/distutils2/command/register.py
@@ -14,9 +14,9 @@ import logging
from distutils2.command.cmd import Command
from distutils2 import logger
-from distutils2.util import (metadata_to_dict, read_pypirc, generate_pypirc,
- DEFAULT_REPOSITORY, DEFAULT_REALM,
- get_pypirc_path)
+from distutils2.metadata import metadata_to_dict
+from distutils2.util import (read_pypirc, generate_pypirc, DEFAULT_REPOSITORY,
+ DEFAULT_REALM, get_pypirc_path)
class register(Command):
@@ -92,7 +92,7 @@ class register(Command):
'''
# send the info to the server and report the result
code, result = self.post_to_server(self.build_post_data('verify'))
- logger.info('Server response (%s): %s' % (code, result))
+ logger.info('server response (%s): %s', code, result)
def send_metadata(self):
@@ -206,18 +206,17 @@ Your selection [default 1]: ''', logging.INFO)
data['email'] = raw_input(' EMail: ')
code, result = self.post_to_server(data)
if code != 200:
- logger.info('Server response (%s): %s' % (code, result))
+ logger.info('server response (%s): %s', code, result)
else:
- logger.info('You will receive an email shortly.')
- logger.info(('Follow the instructions in it to '
- 'complete registration.'))
+ logger.info('you will receive an email shortly; follow the '
+ 'instructions in it to complete registration.')
elif choice == '3':
data = {':action': 'password_reset'}
data['email'] = ''
while not data['email']:
data['email'] = raw_input('Your email address: ')
code, result = self.post_to_server(data)
- logger.info('Server response (%s): %s' % (code, result))
+ logger.info('server response (%s): %s', code, result)
def build_post_data(self, action):
# figure the data to send - the metadata plus some additional
diff --git a/distutils2/command/sdist.py b/distutils2/command/sdist.py
index 5aff9bd..babf5ba 100644
--- a/distutils2/command/sdist.py
+++ b/distutils2/command/sdist.py
@@ -2,10 +2,7 @@
Implements the Distutils 'sdist' command (create a source distribution)."""
import os
-import string
import sys
-from glob import glob
-from warnings import warn
from shutil import rmtree
import re
from StringIO import StringIO
@@ -18,11 +15,10 @@ except ImportError:
from distutils2.command import get_command_names
from distutils2.command.cmd import Command
from distutils2.errors import (DistutilsPlatformError, DistutilsOptionError,
- DistutilsTemplateError, DistutilsModuleError,
- DistutilsFileError)
+ DistutilsModuleError, DistutilsFileError)
from distutils2.manifest import Manifest
from distutils2 import logger
-from distutils2.util import convert_path, resolve_name
+from distutils2.util import resolve_name
def show_formats():
"""Print all possible values for the 'formats' option (used by
@@ -300,7 +296,7 @@ class sdist(Command):
for file in files:
if not os.path.isfile(file):
- logger.warn("'%s' not a regular file -- skipping" % file)
+ logger.warn("'%s' not a regular file -- skipping", file)
else:
dest = os.path.join(base_dir, file)
self.copy_file(file, dest, link=link)
@@ -336,7 +332,7 @@ class sdist(Command):
if not self.keep_temp:
if self.dry_run:
- logger.info('Removing %s' % base_dir)
+ logger.info('removing %s', base_dir)
else:
rmtree(base_dir)
diff --git a/distutils2/command/upload.py b/distutils2/command/upload.py
index a9e7fe0..3bba7ae 100644
--- a/distutils2/command/upload.py
+++ b/distutils2/command/upload.py
@@ -20,8 +20,8 @@ except ImportError:
from distutils2.errors import DistutilsOptionError
from distutils2.util import spawn
from distutils2.command.cmd import Command
-from distutils2.util import (metadata_to_dict, read_pypirc,
- DEFAULT_REPOSITORY, DEFAULT_REALM)
+from distutils2.metadata import metadata_to_dict
+from distutils2.util import read_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM
class upload(Command):
diff --git a/distutils2/compiler/bcppcompiler.py b/distutils2/compiler/bcppcompiler.py
index dbf287e..f156cb2 100644
--- a/distutils2/compiler/bcppcompiler.py
+++ b/distutils2/compiler/bcppcompiler.py
@@ -191,9 +191,8 @@ class BCPPCompiler(CCompiler) :
self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
if runtime_library_dirs:
- logger.warning(("I don't know what to do with "
- "'runtime_library_dirs': %s"),
- str(runtime_library_dirs))
+ logger.warning("don't know what to do with "
+ "'runtime_library_dirs': %r", runtime_library_dirs)
if output_dir is not None:
output_filename = os.path.join (output_dir, output_filename)
diff --git a/distutils2/compiler/ccompiler.py b/distutils2/compiler/ccompiler.py
index 4067518..10702f7 100644
--- a/distutils2/compiler/ccompiler.py
+++ b/distutils2/compiler/ccompiler.py
@@ -850,6 +850,7 @@ main (int argc, char **argv) {
# -- Utility methods -----------------------------------------------
+ # TODO use logging.info
def announce(self, msg, level=None):
logger.debug(msg)
@@ -858,6 +859,7 @@ main (int argc, char **argv) {
if DEBUG:
print msg
+ # TODO use logging.warn
def warn(self, msg):
sys.stderr.write("warning: %s\n" % msg)
diff --git a/distutils2/compiler/msvc9compiler.py b/distutils2/compiler/msvc9compiler.py
index 25e832c..2d247da 100644
--- a/distutils2/compiler/msvc9compiler.py
+++ b/distutils2/compiler/msvc9compiler.py
@@ -226,17 +226,17 @@ def find_vcvarsall(version):
productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
productdir = os.path.abspath(productdir)
if not os.path.isdir(productdir):
- logger.debug("%s is not a valid directory" % productdir)
+ logger.debug("%s is not a valid directory", productdir)
return None
else:
- logger.debug("Env var %s is not set or invalid" % toolskey)
+ logger.debug("env var %s is not set or invalid", toolskey)
if not productdir:
- logger.debug("No productdir found")
+ logger.debug("no productdir found")
return None
vcvarsall = os.path.join(productdir, "vcvarsall.bat")
if os.path.isfile(vcvarsall):
return vcvarsall
- logger.debug("Unable to find vcvarsall.bat")
+ logger.debug("unable to find vcvarsall.bat")
return None
def query_vcvarsall(version, arch="x86"):
@@ -248,7 +248,7 @@ def query_vcvarsall(version, arch="x86"):
if vcvarsall is None:
raise DistutilsPlatformError("Unable to find vcvarsall.bat")
- logger.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
+ logger.debug("calling 'vcvarsall.bat %s' (version=%s)", arch, version)
popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
diff --git a/distutils2/compiler/msvccompiler.py b/distutils2/compiler/msvccompiler.py
index df1efd5..9bc2b63 100644
--- a/distutils2/compiler/msvccompiler.py
+++ b/distutils2/compiler/msvccompiler.py
@@ -44,11 +44,10 @@ except ImportError:
RegError = win32api.error
except ImportError:
- logger.info("Warning: Can't read registry to find the "
- "necessary compiler setting\n"
- "Make sure that Python modules _winreg, "
- "win32api or win32con are installed.")
- pass
+ logger.warning(
+ "can't read registry to find the necessary compiler setting;\n"
+ "make sure that Python modules _winreg, win32api or win32con "
+ "are installed.")
if _can_read_reg:
HKEYS = (hkey_mod.HKEY_USERS,
@@ -653,7 +652,7 @@ class MSVCCompiler (CCompiler) :
if get_build_version() >= 8.0:
- logger.debug("Importing new compiler from distutils.msvc9compiler")
+ logger.debug("importing new compiler from distutils.msvc9compiler")
OldMSVCCompiler = MSVCCompiler
from distutils2.compiler.msvc9compiler import MSVCCompiler
# get_build_architecture not really relevant now we support cross-compile
diff --git a/distutils2/compiler/unixccompiler.py b/distutils2/compiler/unixccompiler.py
index 555b77b..c19f4be 100644
--- a/distutils2/compiler/unixccompiler.py
+++ b/distutils2/compiler/unixccompiler.py
@@ -98,9 +98,9 @@ def _darwin_compiler_fixup(compiler_so, cc_args):
sysroot = compiler_so[idx+1]
if sysroot and not os.path.isdir(sysroot):
- logger.warning("Compiling with an SDK that doesn't seem to exist: %s",
- sysroot)
- logger.warning("Please check your Xcode installation")
+ logger.warning(
+ "compiling with an SDK that doesn't seem to exist: %r;\n"
+ "please check your Xcode installation", sysroot)
return compiler_so
diff --git a/distutils2/config.py b/distutils2/config.py
index 5b6e54e..bb36e7e 100644
--- a/distutils2/config.py
+++ b/distutils2/config.py
@@ -5,6 +5,7 @@
import os.path
import os
import sys
+import logging
from ConfigParser import RawConfigParser
from shlex import split
@@ -91,7 +92,8 @@ class Config(object):
if os.path.isfile(local_file):
files.append(local_file)
- logger.debug("using config files: %s" % ', '.join(files))
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.debug("using config files: %s", ', '.join(files))
return files
def _convert_metadata(self, name, value):
@@ -171,7 +173,7 @@ class Config(object):
files = dict([(key, _convert(key, value))
for key, value in content['files'].iteritems()])
self.dist.packages = []
- self.dist.package_dir = pkg_dir = files.get('packages_root')
+ self.dist.package_dir = files.get('packages_root')
packages = files.get('packages', [])
if isinstance(packages, str):
@@ -249,7 +251,7 @@ class Config(object):
parser = RawConfigParser()
for filename in filenames:
- logger.debug(" reading %s" % filename)
+ logger.debug(" reading %s", filename)
parser.read(filename)
if os.path.split(filename)[-1] == 'setup.cfg':
diff --git a/distutils2/dist.py b/distutils2/dist.py
index d952334..fe434b1 100644
--- a/distutils2/dist.py
+++ b/distutils2/dist.py
@@ -293,10 +293,10 @@ Common commands: (see '--help-commands' for more)
opt_dict = self.command_options.get(cmd_name)
if opt_dict is None:
self.announce(indent +
- "no option dict for '%s' command" % cmd_name)
+ "no option dict for %r command" % cmd_name)
else:
self.announce(indent +
- "option dict for '%s' command:" % cmd_name)
+ "option dict for %r command:" % cmd_name)
out = pformat(opt_dict)
for line in out.split('\n'):
self.announce(indent + " " + line)
@@ -401,7 +401,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 %r" % command)
self.commands.append(command)
# Dig up the command class that implements this command, so we
@@ -420,15 +420,15 @@ Common commands: (see '--help-commands' for more)
if hasattr(cmd_class, meth):
continue
raise DistutilsClassError(
- 'command "%s" must implement "%s"' % (cmd_class, meth))
+ 'command %r must implement %r' % (cmd_class, meth))
# 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 "
- "'user_options' attribute (a list of tuples)") % cmd_class)
+ "command class %s must provide "
+ "'user_options' attribute (a list of tuples)" % cmd_class)
# If the command class has a list of negative alias options,
# merge it in with the global negative aliases.
@@ -466,7 +466,7 @@ Common commands: (see '--help-commands' for more)
func()
else:
raise DistutilsClassError(
- "invalid help function %r for help option '%s': "
+ "invalid help function %r for help option %r: "
"must be a callable object (function, etc.)"
% (func, help_option))
@@ -537,7 +537,7 @@ Common commands: (see '--help-commands' for more)
fix_help_options(cls.help_options))
else:
parser.set_option_table(cls.user_options)
- parser.print_help("Options for '%s' command:" % cls.__name__)
+ parser.print_help("Options for %r command:" % cls.__name__)
print('')
print(gen_usage(self.script_name))
@@ -639,7 +639,7 @@ Common commands: (see '--help-commands' for more)
cmd_obj = self.command_obj.get(command)
if not cmd_obj and create:
logger.debug("Distribution.get_command_obj(): " \
- "creating '%s' command object" % command)
+ "creating %r command object", command)
cls = get_command_class(command)
cmd_obj = self.command_obj[command] = cls(self)
@@ -669,10 +669,10 @@ Common commands: (see '--help-commands' for more)
if option_dict is None:
option_dict = self.get_option_dict(command_name)
- logger.debug(" setting options for '%s' command:" % command_name)
+ logger.debug(" setting options for %r command:", command_name)
for (option, (source, value)) in option_dict.iteritems():
- logger.debug(" %s = %s (from %s)" % (option, value, source))
+ logger.debug(" %s = %s (from %s)", option, value, source)
try:
bool_opts = [x.replace('-', '_')
for x in command_obj.boolean_options]
@@ -693,7 +693,7 @@ Common commands: (see '--help-commands' for more)
setattr(command_obj, option, value)
else:
raise DistutilsOptionError(
- "error in %s: command '%s' has no such option '%s'" %
+ "error in %s: command %r has no such option %r" %
(source, command_name, option))
except ValueError, msg:
raise DistutilsOptionError(msg)
diff --git a/distutils2/errors.py b/distutils2/errors.py
index 4b006b3..bbf5497 100644
--- a/distutils2/errors.py
+++ b/distutils2/errors.py
@@ -9,7 +9,6 @@ This module is safe to use in "from ... import *" mode; it only exports
symbols whose names start with "Distutils" and end with "Error"."""
-
class DistutilsError(Exception):
"""The root of all Distutils evil."""
@@ -135,3 +134,11 @@ class HugeMajorVersionNumError(IrrationalVersionError):
This guard can be disabled by setting that option False.
"""
pass
+
+
+class InstallationException(Exception):
+ """Base exception for installation scripts"""
+
+
+class InstallationConflict(InstallationException):
+ """Raised when a conflict is detected"""
diff --git a/distutils2/index/__init__.py b/distutils2/index/__init__.py
index 312662f..c80b873 100644
--- a/distutils2/index/__init__.py
+++ b/distutils2/index/__init__.py
@@ -6,6 +6,6 @@ __all__ = ['simple',
'xmlrpc',
'dist',
'errors',
- 'mirrors',]
+ 'mirrors']
from dist import ReleaseInfo, ReleasesList, DistInfo
diff --git a/distutils2/index/dist.py b/distutils2/index/dist.py
index fe6c616..233eec7 100644
--- a/distutils2/index/dist.py
+++ b/distutils2/index/dist.py
@@ -109,7 +109,8 @@ class ReleaseInfo(IndexReference):
self.dists = {}
return self.dists
- def add_distribution(self, dist_type='sdist', python_version=None, **params):
+ def add_distribution(self, dist_type='sdist', python_version=None,
+ **params):
"""Add distribution informations to this release.
If distribution information is already set for this distribution type,
add the given url paths to the distribution. This can be useful while
@@ -323,7 +324,7 @@ class DistInfo(IndexReference):
filename = self.download(path)
content_type = mimetypes.guess_type(filename)[0]
- self._unpacked_dir = unpack_archive(filename)
+ self._unpacked_dir = unpack_archive(filename, path)
return self._unpacked_dir
diff --git a/distutils2/index/mirrors.py b/distutils2/index/mirrors.py
index 49d5dd1..885082c 100644
--- a/distutils2/index/mirrors.py
+++ b/distutils2/index/mirrors.py
@@ -1,4 +1,4 @@
-"""Utilities related to the mirror infrastructure defined in PEP 381.
+"""Utilities related to the mirror infrastructure defined in PEP 381.
See http://www.python.org/dev/peps/pep-0381/
"""
@@ -7,6 +7,7 @@ import socket
DEFAULT_MIRROR_URL = "last.pypi.python.org"
+
def get_mirrors(hostname=None):
"""Return the list of mirrors from the last record found on the DNS
entry::
@@ -19,7 +20,7 @@ def get_mirrors(hostname=None):
"""
if hostname is None:
hostname = DEFAULT_MIRROR_URL
-
+
# return the last mirror registered on PyPI.
try:
hostname = socket.gethostbyname_ex(hostname)[0]
@@ -30,23 +31,24 @@ def get_mirrors(hostname=None):
# determine the list from the last one.
return ["%s.%s" % (s, end_letter[1]) for s in string_range(end_letter[0])]
+
def string_range(last):
"""Compute the range of string between "a" and last.
-
+
This works for simple "a to z" lists, but also for "a to zz" lists.
"""
for k in range(len(last)):
- for x in product(ascii_lowercase, repeat=k+1):
+ for x in product(ascii_lowercase, repeat=(k + 1)):
result = ''.join(x)
yield result
if result == last:
return
+
def product(*args, **kwds):
pools = map(tuple, args) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
- result = [x+[y] for x in result for y in pool]
+ result = [x + [y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
-
diff --git a/distutils2/index/simple.py b/distutils2/index/simple.py
index cd88698..7fda538 100644
--- a/distutils2/index/simple.py
+++ b/distutils2/index/simple.py
@@ -11,7 +11,6 @@ import socket
import sys
import urllib2
import urlparse
-import logging
import os
from distutils2 import logger
@@ -168,7 +167,7 @@ class Crawler(BaseClient):
if predicate.name.lower() in self._projects and not force_update:
return self._projects.get(predicate.name.lower())
prefer_final = self._get_prefer_final(prefer_final)
- logger.info('Reading info on PyPI about %s' % predicate.name)
+ logger.info('reading info on PyPI about %s', predicate.name)
self._process_index_page(predicate.name)
if predicate.name.lower() not in self._projects:
@@ -306,8 +305,8 @@ class Crawler(BaseClient):
infos = get_infos_from_url(link, project_name,
is_external=not self.index_url in url)
except CantParseArchiveName, e:
- logging.warning("version has not been parsed: %s"
- % e)
+ logger.warning(
+ "version has not been parsed: %s", e)
else:
self._register_release(release_info=infos)
else:
diff --git a/distutils2/index/wrapper.py b/distutils2/index/wrapper.py
index b2b5700..d032f95 100644
--- a/distutils2/index/wrapper.py
+++ b/distutils2/index/wrapper.py
@@ -9,6 +9,7 @@ _WRAPPER_MAPPINGS = {'get_release': 'simple',
_WRAPPER_INDEXES = {'xmlrpc': xmlrpc.Client,
'simple': simple.Crawler}
+
def switch_index_if_fails(func, wrapper):
"""Decorator that switch of index (for instance from xmlrpc to simple)
if the first mirror return an empty list or raises an exception.
@@ -82,11 +83,11 @@ class ClientWrapper(object):
other_indexes = [i for i in self._indexes
if i != self._default_index]
for index in other_indexes:
- real_method = getattr(self._indexes[index], method_name, None)
+ real_method = getattr(self._indexes[index], method_name,
+ None)
if real_method:
break
if real_method:
return switch_index_if_fails(real_method, self)
else:
raise AttributeError("No index have attribute '%s'" % method_name)
-
diff --git a/distutils2/index/xmlrpc.py b/distutils2/index/xmlrpc.py
index 54d7367..f6e22b6 100644
--- a/distutils2/index/xmlrpc.py
+++ b/distutils2/index/xmlrpc.py
@@ -103,7 +103,6 @@ class Client(BaseClient):
project.sort_releases(prefer_final)
return project
-
def get_distributions(self, project_name, version):
"""Grab informations about distributions from XML-RPC.
@@ -165,7 +164,7 @@ class Client(BaseClient):
p['version'], metadata={'summary': p['summary']},
index=self._index))
except IrrationalVersionError, e:
- logging.warn("Irrational version error found: %s" % e)
+ logging.warn("Irrational version error found: %s", e)
return [self._projects[p['name'].lower()] for p in projects]
def get_all_projects(self):
diff --git a/distutils2/install.py b/distutils2/install.py
index 4d3ea5a..053787f 100644
--- a/distutils2/install.py
+++ b/distutils2/install.py
@@ -12,6 +12,7 @@ import sys
import stat
import errno
import itertools
+import logging
import tempfile
from distutils2 import logger
@@ -21,7 +22,8 @@ from distutils2._backport.sysconfig import get_config_var
from distutils2.depgraph import generate_graph
from distutils2.index import wrapper
from distutils2.index.errors import ProjectNotFound, ReleaseNotFound
-from distutils2.errors import DistutilsError
+from distutils2.errors import (DistutilsError, InstallationException,
+ InstallationConflict)
from distutils2.version import get_version_predicate
@@ -29,14 +31,6 @@ __all__ = ['install_dists', 'install_from_infos', 'get_infos', 'remove',
'install']
-class InstallationException(Exception):
- """Base exception for installation scripts"""
-
-
-class InstallationConflict(InstallationException):
- """Raised when a conflict is detected"""
-
-
def _move_files(files, destination):
"""Move the list of files in the destination folder, keeping the same
structure.
@@ -75,7 +69,7 @@ def _run_d1_install(archive_dir, path):
record_file = os.path.join(archive_dir, 'RECORD')
os.system(cmd % (sys.executable, path, record_file))
if not os.path.exists(record_file):
- raise ValueError('Failed to install.')
+ raise ValueError('failed to install')
return open(record_file).read().split('\n')
@@ -134,12 +128,12 @@ def install_dists(dists, path, paths=sys.path):
installed_dists, installed_files = [], []
for dist in dists:
- logger.info('Installing %s %s' % (dist.name, dist.version))
+ logger.info('installing %s %s', dist.name, dist.version)
try:
installed_files.extend(_install_dist(dist, path))
installed_dists.append(dist)
except Exception, e:
- logger.info('Failed. %s' % str(e))
+ logger.info('failed: %s', e)
# reverting
for installed_dist in installed_dists:
@@ -243,7 +237,7 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True):
conflict.
"""
if not installed:
- logger.info('Reading installed distributions')
+ logger.info('reading installed distributions')
installed = get_distributions(use_egg_info=True)
infos = {'install': [], 'remove': [], 'conflict': []}
@@ -258,8 +252,8 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True):
if predicate.name.lower() != installed_project.name.lower():
continue
found = True
- logger.info('Found %s %s' % (installed_project.name,
- installed_project.version))
+ logger.info('found %s %s', installed_project.name,
+ installed_project.version)
# if we already have something installed, check it matches the
# requirements
@@ -268,7 +262,7 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True):
break
if not found:
- logger.info('Project not installed.')
+ logger.info('project not installed')
if not index:
index = wrapper.ClientWrapper()
@@ -283,7 +277,7 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True):
release = releases.get_last(requirements, prefer_final=prefer_final)
if release is None:
- logger.info('Could not find a matching project')
+ logger.info('could not find a matching project')
return infos
# this works for Metadata 1.2
@@ -358,12 +352,12 @@ def remove(project_name, paths=sys.path):
finally:
shutil.rmtree(tmp)
- logger.info('Removing %r...' % project_name)
+ logger.info('removing %r...', project_name)
file_count = 0
for file_ in rmfiles:
os.remove(file_)
- file_count +=1
+ file_count += 1
dir_count = 0
for dirname in rmdirs:
@@ -391,20 +385,20 @@ def remove(project_name, paths=sys.path):
if os.path.exists(dist.path):
shutil.rmtree(dist.path)
- logger.info('Success ! Removed %d files and %d dirs' % \
- (file_count, dir_count))
+ logger.info('success: removed %d files and %d dirs',
+ file_count, dir_count)
def install(project):
- logger.info('Getting information about "%s".' % project)
+ logger.info('getting information about %r', project)
try:
info = get_infos(project)
except InstallationException:
- logger.info('Cound not find "%s".' % project)
+ logger.info('cound not find %r', project)
return
if info['install'] == []:
- logger.info('Nothing to install.')
+ logger.info('nothing to install')
return
install_path = get_config_var('base')
@@ -413,8 +407,9 @@ def install(project):
info['install'], info['remove'], info['conflict'])
except InstallationConflict, e:
- projects = ['%s %s' % (p.name, p.version) for p in e.args[0]]
- logger.info('"%s" conflicts with "%s"' % (project, ','.join(projects)))
+ if logger.isEnabledFor(logging.INFO):
+ projects = ['%s %s' % (p.name, p.version) for p in e.args[0]]
+ logger.info('%r conflicts with %s', project, ','.join(projects))
def _main(**attrs):
diff --git a/distutils2/manifest.py b/distutils2/manifest.py
index e5862dd..a6fa72f 100644
--- a/distutils2/manifest.py
+++ b/distutils2/manifest.py
@@ -95,7 +95,7 @@ class Manifest(object):
try:
self._process_template_line(line)
except DistutilsTemplateError, msg:
- logging.warning("%s, %s" % (path_or_file, msg))
+ logging.warning("%s, %s", path_or_file, msg)
def write(self, path):
"""Write the file list in 'self.filelist' (presumably as filled in
@@ -111,14 +111,14 @@ class Manifest(object):
if first_line != '# file GENERATED by distutils, do NOT edit\n':
logging.info("not writing to manually maintained "
- "manifest file '%s'", path)
+ "manifest file %r", path)
return
self.sort()
self.remove_duplicates()
content = self.files[:]
content.insert(0, '# file GENERATED by distutils, do NOT edit')
- logging.info("writing manifest file '%s'", path)
+ logging.info("writing manifest file %r", path)
write_file(path, content)
def read(self, path):
@@ -126,7 +126,7 @@ class Manifest(object):
fill in 'self.filelist', the list of files to include in the source
distribution.
"""
- logging.info("reading manifest file '%s'" % path)
+ logging.info("reading manifest file %r", path)
manifest = open(path)
try:
for line in manifest.readlines():
@@ -168,14 +168,14 @@ class Manifest(object):
'global-include', 'global-exclude'):
if len(words) < 2:
raise DistutilsTemplateError(
- "'%s' expects <pattern1> <pattern2> ..." % action)
+ "%r expects <pattern1> <pattern2> ..." % action)
patterns = map(convert_path, words[1:])
elif action in ('recursive-include', 'recursive-exclude'):
if len(words) < 3:
raise DistutilsTemplateError(
- "'%s' expects <dir> <pattern1> <pattern2> ..." % action)
+ "%r expects <dir> <pattern1> <pattern2> ..." % action)
dir = convert_path(words[1])
patterns = map(convert_path, words[2:])
@@ -183,12 +183,12 @@ class Manifest(object):
elif action in ('graft', 'prune'):
if len(words) != 2:
raise DistutilsTemplateError(
- "'%s' expects a single <dir_pattern>" % action)
+ "%r expects a single <dir_pattern>" % action)
dir_pattern = convert_path(words[1])
else:
- raise DistutilsTemplateError("unknown action '%s'" % action)
+ raise DistutilsTemplateError("unknown action %r" % action)
return action, patterns, dir, dir_pattern
@@ -206,53 +206,52 @@ class Manifest(object):
if action == 'include':
for pattern in patterns:
if not self._include_pattern(pattern, anchor=1):
- logging.warning("warning: no files found matching '%s'" %
- pattern)
+ logging.warning("no files found matching %r", pattern)
elif action == 'exclude':
for pattern in patterns:
if not self.exclude_pattern(pattern, anchor=1):
- logging.warning(("warning: no previously-included files "
- "found matching '%s'") % pattern)
+ logging.warning("no previously-included files "
+ "found matching %r", pattern)
elif action == 'global-include':
for pattern in patterns:
if not self._include_pattern(pattern, anchor=0):
- logging.warning(("warning: no files found matching '%s' " +
- "anywhere in distribution") % pattern)
+ logging.warning("no files found matching %r "
+ "anywhere in distribution", pattern)
elif action == 'global-exclude':
for pattern in patterns:
if not self.exclude_pattern(pattern, anchor=0):
- logging.warning(("warning: no previously-included files "
- "matching '%s' found anywhere in distribution") %
- pattern)
+ logging.warning("no previously-included files "
+ "matching %r found anywhere in "
+ "distribution", pattern)
elif action == 'recursive-include':
for pattern in patterns:
if not self._include_pattern(pattern, prefix=dir):
- logging.warning(("warning: no files found matching '%s' "
- "under directory '%s'" % (pattern, dir)))
+ logging.warning("no files found matching %r "
+ "under directory %r", pattern, dir)
elif action == 'recursive-exclude':
for pattern in patterns:
if not self.exclude_pattern(pattern, prefix=dir):
- logging.warning(("warning: no previously-included files "
- "matching '%s' found under directory '%s'") %
- (pattern, dir))
+ logging.warning("no previously-included files "
+ "matching %r found under directory %r",
+ pattern, dir)
elif action == 'graft':
if not self._include_pattern(None, prefix=dir_pattern):
- logging.warning("warning: no directories found matching '%s'" %
- dir_pattern)
+ logging.warning("no directories found matching %r",
+ dir_pattern)
elif action == 'prune':
if not self.exclude_pattern(None, prefix=dir_pattern):
- logging.warning(("no previously-included directories found " +
- "matching '%s'") % dir_pattern)
+ logging.warning("no previously-included directories found "
+ "matching %r", dir_pattern)
else:
raise DistutilsInternalError(
- "this cannot happen: invalid action '%s'" % action)
+ "this cannot happen: invalid action %r" % action)
def _include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
"""Select strings (presumably filenames) from 'self.files' that
diff --git a/distutils2/metadata.py b/distutils2/metadata.py
index 89a54c0..f3e195d 100644
--- a/distutils2/metadata.py
+++ b/distutils2/metadata.py
@@ -3,8 +3,6 @@
Supports all metadata formats (1.0, 1.1, 1.2).
"""
-import os
-import sys
import re
from StringIO import StringIO
from email import message_from_file
@@ -41,8 +39,8 @@ except ImportError:
_HAS_DOCUTILS = False
# public API of this module
-__all__ = ['Metadata', 'PKG_INFO_ENCODING',
- 'PKG_INFO_PREFERRED_VERSION']
+__all__ = ['Metadata', 'get_metadata_version', 'metadata_to_dict',
+ 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION']
# Encoding used for the PKG-INFO files
PKG_INFO_ENCODING = 'utf-8'
@@ -77,13 +75,12 @@ _345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
'Obsoletes-Dist', 'Requires-External', 'Maintainer',
'Maintainer-email', 'Project-URL')
-_345_REQUIRED = ('Name', 'Version')
-
_ALL_FIELDS = set()
_ALL_FIELDS.update(_241_FIELDS)
_ALL_FIELDS.update(_314_FIELDS)
_ALL_FIELDS.update(_345_FIELDS)
+
def _version2fieldlist(version):
if version == '1.0':
return _241_FIELDS
@@ -140,46 +137,95 @@ def _best_version(fields):
# default marker when 1.0 is disqualified
return '1.2'
-_ATTR2FIELD = {'metadata_version': 'Metadata-Version',
- 'name': 'Name',
- 'version': 'Version',
- 'platform': 'Platform',
- 'supported_platform': 'Supported-Platform',
- 'summary': 'Summary',
- 'description': 'Description',
- 'keywords': 'Keywords',
- 'home_page': 'Home-page',
- 'author': 'Author',
- 'author_email': 'Author-email',
- 'maintainer': 'Maintainer',
- 'maintainer_email': 'Maintainer-email',
- 'license': 'License',
- 'classifier': 'Classifier',
- 'download_url': 'Download-URL',
- 'obsoletes_dist': 'Obsoletes-Dist',
- 'provides_dist': 'Provides-Dist',
- 'requires_dist': 'Requires-Dist',
- 'requires_python': 'Requires-Python',
- 'requires_external': 'Requires-External',
- 'requires': 'Requires',
- 'provides': 'Provides',
- 'obsoletes': 'Obsoletes',
- 'project_url': 'Project-URL',
- }
+
+def get_metadata_version(metadata):
+ """Return the Metadata-Version attribute
+
+ - *metadata* give a METADATA object
+ """
+ return metadata['Metadata-Version']
+
+
+def metadata_to_dict(metadata):
+ """Convert a metadata object to a dict
+
+ - *metadata* give a METADATA object
+ """
+ data = {
+ 'metadata_version': metadata['Metadata-Version'],
+ 'name': metadata['Name'],
+ 'version': metadata['Version'],
+ 'summary': metadata['Summary'],
+ 'home_page': metadata['Home-page'],
+ 'author': metadata['Author'],
+ 'author_email': metadata['Author-email'],
+ 'license': metadata['License'],
+ 'description': metadata['Description'],
+ 'keywords': metadata['Keywords'],
+ 'platform': metadata['Platform'],
+ 'classifier': metadata['Classifier'],
+ 'download_url': metadata['Download-URL'],
+ }
+
+ if metadata['Metadata-Version'] == '1.2':
+ data['requires_dist'] = metadata['Requires-Dist']
+ data['requires_python'] = metadata['Requires-Python']
+ data['requires_external'] = metadata['Requires-External']
+ data['provides_dist'] = metadata['Provides-Dist']
+ data['obsoletes_dist'] = metadata['Obsoletes-Dist']
+ data['project_url'] = [','.join(url) for url in
+ metadata['Project-URL']]
+
+ elif metadata['Metadata-Version'] == '1.1':
+ data['provides'] = metadata['Provides']
+ data['requires'] = metadata['Requires']
+ data['obsoletes'] = metadata['Obsoletes']
+
+ return data
+
+
+_ATTR2FIELD = {
+ 'metadata_version': 'Metadata-Version',
+ 'name': 'Name',
+ 'version': 'Version',
+ 'platform': 'Platform',
+ 'supported_platform': 'Supported-Platform',
+ 'summary': 'Summary',
+ 'description': 'Description',
+ 'keywords': 'Keywords',
+ 'home_page': 'Home-page',
+ 'author': 'Author',
+ 'author_email': 'Author-email',
+ 'maintainer': 'Maintainer',
+ 'maintainer_email': 'Maintainer-email',
+ 'license': 'License',
+ 'classifier': 'Classifier',
+ 'download_url': 'Download-URL',
+ 'obsoletes_dist': 'Obsoletes-Dist',
+ 'provides_dist': 'Provides-Dist',
+ 'requires_dist': 'Requires-Dist',
+ 'requires_python': 'Requires-Python',
+ 'requires_external': 'Requires-External',
+ 'requires': 'Requires',
+ 'provides': 'Provides',
+ 'obsoletes': 'Obsoletes',
+ 'project_url': 'Project-URL',
+}
_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
_VERSIONS_FIELDS = ('Requires-Python',)
_VERSION_FIELDS = ('Version',)
_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
- 'Requires', 'Provides', 'Obsoletes-Dist',
- 'Provides-Dist', 'Requires-Dist', 'Requires-External',
- 'Project-URL', 'Supported-Platform')
+ 'Requires', 'Provides', 'Obsoletes-Dist',
+ 'Provides-Dist', 'Requires-Dist', 'Requires-External',
+ 'Project-URL', 'Supported-Platform')
_LISTTUPLEFIELDS = ('Project-URL',)
_ELEMENTSFIELD = ('Keywords',)
_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description')
+
class NoDefault(object):
"""Marker object used for clean representation"""
def __repr__(self):
@@ -187,6 +233,7 @@ class NoDefault(object):
_MISSING = NoDefault()
+
class Metadata(object):
"""The metadata of a release.
@@ -205,7 +252,6 @@ class Metadata(object):
display_warnings=False):
self._fields = {}
self.display_warnings = display_warnings
- self.version = None
self.requires_files = []
self.docutils_support = _HAS_DOCUTILS
self.platform_dependent = platform_dependent
@@ -220,8 +266,7 @@ class Metadata(object):
self.update(mapping)
def _set_best_version(self):
- self.version = _best_version(self._fields)
- self._fields['Metadata-Version'] = self.version
+ self._fields['Metadata-Version'] = _best_version(self._fields)
def _write_field(self, file, name, value):
file.write('%s: %s\n' % (name, value))
@@ -318,9 +363,9 @@ class Metadata(object):
def read_file(self, fileob):
"""Read the metadata values from a file object."""
msg = message_from_file(fileob)
- self.version = msg['metadata-version']
+ self._fields['Metadata-Version'] = msg['metadata-version']
- for field in _version2fieldlist(self.version):
+ for field in _version2fieldlist(self['Metadata-Version']):
if field in _LISTFIELDS:
# we can have multiple lines
values = msg.get_all(field)
@@ -344,7 +389,7 @@ class Metadata(object):
def write_file(self, fileobject):
"""Write the PKG-INFO format data to a file object."""
self._set_best_version()
- for field in _version2fieldlist(self.version):
+ for field in _version2fieldlist(self['Metadata-Version']):
values = self.get(field)
if field in _ELEMENTSFIELD:
self._write_field(fileobject, field, ','.join(values))
@@ -471,12 +516,12 @@ class Metadata(object):
# XXX should check the versions (if the file was loaded)
missing, warnings = [], []
- for attr in ('Name', 'Version'):
+ for attr in ('Name', 'Version'): # required by PEP 345
if attr not in self:
missing.append(attr)
if strict and missing != []:
- msg = "missing required metadata: %s" % ', '.join(missing)
+ msg = 'missing required metadata: %s' % ', '.join(missing)
raise MetadataMissingError(msg)
for attr in ('Home-page', 'Author'):
@@ -506,14 +551,13 @@ class Metadata(object):
return missing, warnings
+ # Mapping API
+
def keys(self):
- """Dict like api"""
- return _version2fieldlist(self.version)
+ return _version2fieldlist(self['Metadata-Version'])
def values(self):
- """Dict like api"""
return [self[key] for key in self.keys()]
def items(self):
- """Dict like api"""
return [(key, self[key]) for key in self.keys()]
diff --git a/distutils2/run.py b/distutils2/run.py
index 991d607..410caa2 100644
--- a/distutils2/run.py
+++ b/distutils2/run.py
@@ -4,7 +4,6 @@ from optparse import OptionParser
import logging
from distutils2 import logger
-from distutils2.util import grok_environment_error
from distutils2.errors import (DistutilsSetupError, DistutilsArgError,
DistutilsError, CCompilerError)
from distutils2.dist import Distribution
@@ -106,12 +105,7 @@ def commands_main(**attrs):
dist.run_commands()
except KeyboardInterrupt:
raise SystemExit("interrupted")
- except (IOError, os.error), exc:
- error = grok_environment_error(exc)
- raise SystemExit(error)
-
- except (DistutilsError,
- CCompilerError), msg:
+ except (IOError, os.error, DistutilsError, CCompilerError), msg:
raise SystemExit("error: " + str(msg))
return dist
diff --git a/distutils2/tests/support.py b/distutils2/tests/support.py
index b4c039c..4f16d08 100644
--- a/distutils2/tests/support.py
+++ b/distutils2/tests/support.py
@@ -51,6 +51,9 @@ class LoggingCatcher(object):
def setUp(self):
super(LoggingCatcher, self).setUp()
+ # TODO read the new logging docs and/or the python-dev posts about
+ # logging and tests to properly use a handler instead of
+ # monkey-patching
self.old_log = logger._log
logger._log = self._log
logger.setLevel(logging.INFO)
diff --git a/distutils2/tests/test_command_build_py.py b/distutils2/tests/test_command_build_py.py
index 38ff7a6..6d30eee 100644
--- a/distutils2/tests/test_command_build_py.py
+++ b/distutils2/tests/test_command_build_py.py
@@ -116,7 +116,7 @@ class BuildPyTestCase(support.TempdirManager,
finally:
sys.dont_write_bytecode = old_dont_write_bytecode
- self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
+ self.assertIn('byte-compiling is disabled', self.logs[0][2][1])
def test_suite():
return unittest.makeSuite(BuildPyTestCase)
diff --git a/distutils2/tests/test_command_install_lib.py b/distutils2/tests/test_command_install_lib.py
index 7fb4e7a..d0d7ec8 100644
--- a/distutils2/tests/test_command_install_lib.py
+++ b/distutils2/tests/test_command_install_lib.py
@@ -97,7 +97,7 @@ class InstallLibTestCase(support.TempdirManager,
finally:
sys.dont_write_bytecode = old_dont_write_bytecode
- self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
+ self.assertIn('byte-compiling is disabled', self.logs[0][2][1])
def test_suite():
return unittest.makeSuite(InstallLibTestCase)
diff --git a/distutils2/tests/test_command_sdist.py b/distutils2/tests/test_command_sdist.py
index 90f826e..f43e6cc 100644
--- a/distutils2/tests/test_command_sdist.py
+++ b/distutils2/tests/test_command_sdist.py
@@ -95,9 +95,6 @@ class SDistTestCase(support.TempdirManager, support.LoggingCatcher,
dist.include_package_data = True
cmd = sdist(dist)
cmd.dist_dir = 'dist'
- def _warn(*args):
- pass
- cmd.warn = _warn
return dist, cmd
@unittest.skipUnless(zlib, "requires zlib")
@@ -250,7 +247,7 @@ class SDistTestCase(support.TempdirManager, support.LoggingCatcher,
cmd.ensure_finalized()
cmd.run()
warnings = self.get_logs(logging.WARN)
- self.assertEqual(len(warnings), 1)
+ self.assertEqual(len(warnings), 2)
# trying with a complete set of metadata
self.clear_logs()
@@ -262,7 +259,8 @@ class SDistTestCase(support.TempdirManager, support.LoggingCatcher,
# removing manifest generated warnings
warnings = [warn for warn in warnings if
not warn.endswith('-- skipping')]
- self.assertEqual(len(warnings), 0)
+ # the remaining warning is about the use of the default file list
+ self.assertEqual(len(warnings), 1)
def test_show_formats(self):
diff --git a/distutils2/tests/test_index_dist.py b/distutils2/tests/test_index_dist.py
index 09ae3d3..ac6a377 100644
--- a/distutils2/tests/test_index_dist.py
+++ b/distutils2/tests/test_index_dist.py
@@ -160,13 +160,23 @@ class TestDistInfo(TempdirManager, unittest.TestCase):
@use_pypi_server('downloads_with_md5')
def test_unpack(self, server):
url = "%s/simple/foobar/foobar-0.1.tar.gz" % server.full_address
- dist = Dist(url=url)
+ dist1 = Dist(url=url)
# doing an unpack
- here = self.mkdtemp()
- there = dist.unpack(here)
- result = os.listdir(there)
- self.assertIn('paf', result)
- os.remove('paf')
+ dist1_here = self.mkdtemp()
+ dist1_there = dist1.unpack(path=dist1_here)
+ # assert we unpack to the path provided
+ self.assertEqual(dist1_here, dist1_there)
+ dist1_result = os.listdir(dist1_there)
+ self.assertIn('paf', dist1_result)
+ os.remove(os.path.join(dist1_there, 'paf'))
+
+ # Test unpack works without a path argument
+ dist2 = Dist(url=url)
+ # doing an unpack
+ dist2_there = dist2.unpack()
+ dist2_result = os.listdir(dist2_there)
+ self.assertIn('paf', dist2_result)
+ os.remove(os.path.join(dist2_there, 'paf'))
def test_hashname(self):
# Invalid hashnames raises an exception on assignation
diff --git a/distutils2/tests/test_manifest.py b/distutils2/tests/test_manifest.py
index 5f768eb..fc37315 100644
--- a/distutils2/tests/test_manifest.py
+++ b/distutils2/tests/test_manifest.py
@@ -1,6 +1,5 @@
"""Tests for distutils.manifest."""
import os
-import sys
import logging
from StringIO import StringIO
@@ -25,10 +24,11 @@ file1
class ManifestTestCase(support.TempdirManager,
+ # enable this after LoggingCatcher is fixed
+ #support.LoggingCatcher,
unittest.TestCase):
def test_manifest_reader(self):
-
tmpdir = self.mkdtemp()
MANIFEST = os.path.join(tmpdir, 'MANIFEST.in')
f = open(MANIFEST, 'w')
@@ -38,9 +38,10 @@ class ManifestTestCase(support.TempdirManager,
f.close()
manifest = Manifest()
+ # remove this when LoggingCatcher is fixed
warns = []
- def _warn(msg):
- warns.append(msg)
+ def _warn(*args):
+ warns.append(args[0])
old_warn = logging.warning
logging.warning = _warn
@@ -53,7 +54,7 @@ class ManifestTestCase(support.TempdirManager,
# and 3 warnings issued (we ddidn't provided the files)
self.assertEqual(len(warns), 3)
for warn in warns:
- self.assertIn('warning: no files found matching', warn)
+ self.assertIn('no files found matching', warn)
# manifest also accepts file-like objects
old_warn = logging.warning
diff --git a/distutils2/tests/test_metadata.py b/distutils2/tests/test_metadata.py
index 746ba68..46830ab 100644
--- a/distutils2/tests/test_metadata.py
+++ b/distutils2/tests/test_metadata.py
@@ -4,7 +4,7 @@ import sys
import platform
from StringIO import StringIO
-from distutils2.metadata import (Metadata,
+from distutils2.metadata import (Metadata, get_metadata_version,
PKG_INFO_PREFERRED_VERSION)
from distutils2.tests import run_unittest, unittest
from distutils2.tests.support import LoggingCatcher, WarningsCatcher
@@ -126,18 +126,23 @@ class MetadataTestCase(LoggingCatcher, WarningsCatcher,
del metadata['Obsoletes-Dist']
metadata['Version'] = '1'
self.assertEqual(metadata['Metadata-Version'], '1.0')
+ self.assertEqual(get_metadata_version(metadata), '1.0')
PKG_INFO = os.path.join(os.path.dirname(__file__),
'SETUPTOOLS-PKG-INFO')
metadata.read_file(StringIO(open(PKG_INFO).read()))
self.assertEqual(metadata['Metadata-Version'], '1.0')
+ self.assertEqual(get_metadata_version(metadata), '1.0')
PKG_INFO = os.path.join(os.path.dirname(__file__),
'SETUPTOOLS-PKG-INFO2')
metadata.read_file(StringIO(open(PKG_INFO).read()))
self.assertEqual(metadata['Metadata-Version'], '1.1')
+ self.assertEqual(get_metadata_version(metadata), '1.1')
- metadata.version = '1.618'
+ # Update the _fields dict directly to prevent 'Metadata-Version'
+ # from being updated by the _set_best_version() method.
+ metadata._fields['Metadata-Version'] = '1.618'
self.assertRaises(MetadataUnrecognizedVersionError, metadata.keys)
# XXX Spurious Warnings were disabled
@@ -169,7 +174,7 @@ class MetadataTestCase(LoggingCatcher, WarningsCatcher,
metadata['Project-URL'] = [('one', 'http://ok')]
self.assertEqual(metadata['Project-URL'],
[('one', 'http://ok')])
- self.assertEqual(metadata.version, '1.2')
+ self.assertEqual(metadata['Metadata-Version'], '1.2')
def test_check_version(self):
metadata = Metadata()
@@ -244,9 +249,13 @@ class MetadataTestCase(LoggingCatcher, WarningsCatcher,
def test_best_choice(self):
metadata = Metadata()
metadata['Version'] = '1.0'
- self.assertEqual(metadata.version, PKG_INFO_PREFERRED_VERSION)
+ self.assertEqual(metadata['Metadata-Version'],
+ PKG_INFO_PREFERRED_VERSION)
+ self.assertEqual(get_metadata_version(metadata),
+ PKG_INFO_PREFERRED_VERSION)
metadata['Classifier'] = ['ok']
- self.assertEqual(metadata.version, '1.2')
+ self.assertEqual(metadata['Metadata-Version'], '1.2')
+ self.assertEqual(get_metadata_version(metadata), '1.2')
def test_project_urls(self):
# project-url is a bit specific, make sure we write it
diff --git a/distutils2/tests/test_mkcfg.py b/distutils2/tests/test_mkcfg.py
index 3caeca0..c49a877 100644
--- a/distutils2/tests/test_mkcfg.py
+++ b/distutils2/tests/test_mkcfg.py
@@ -8,6 +8,7 @@ from textwrap import dedent
from distutils2.tests import run_unittest, support, unittest
from distutils2.mkcfg import MainProgram
from distutils2.mkcfg import ask_yn, ask, main
+from distutils2._backport import sysconfig
class MkcfgTestCase(support.TempdirManager,
@@ -22,12 +23,18 @@ class MkcfgTestCase(support.TempdirManager,
self._cwd = os.getcwd()
self.wdir = self.mkdtemp()
os.chdir(self.wdir)
+ # patch sysconfig
+ self._old_get_paths = sysconfig.get_paths
+ sysconfig.get_paths = lambda *args, **kwargs: {
+ 'man': sys.prefix + '/share/man',
+ 'doc': sys.prefix + '/share/doc/pyxfoil',}
def tearDown(self):
super(MkcfgTestCase, self).tearDown()
sys.stdin = self._stdin
sys.stdout = self._stdout
os.chdir(self._cwd)
+ sysconfig.get_paths = self._old_get_paths
def test_ask_yn(self):
sys.stdin.write('y\n')
diff --git a/distutils2/util.py b/distutils2/util.py
index 6c51774..95c4105 100644
--- a/distutils2/util.py
+++ b/distutils2/util.py
@@ -181,29 +181,6 @@ def subst_vars(s, local_vars):
raise ValueError("invalid variable '$%s'" % var)
-def grok_environment_error(exc, prefix="error: "):
- """Generate a useful error message from an EnvironmentError.
-
- This will generate an IOError or an OSError exception object.
- Handles Python 1.5.1 and 1.5.2 styles, and
- does what it can to deal with exception objects that don't have a
- filename (which happens when the error is due to a two-file operation,
- such as 'rename()' or 'link()'. Returns the error message as a string
- prefixed with 'prefix'.
- """
- # check for Python 1.5.2-style {IO,OS}Error exception objects
- if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):
- if exc.filename:
- error = prefix + "%s: %s" % (exc.filename, exc.strerror)
- else:
- # two-argument functions in posix module don't
- # include the filename in the exception object!
- error = prefix + "%s" % exc.strerror
- else:
- error = prefix + str(exc[-1])
-
- return error
-
# Needed by 'split_quoted()'
_wordchars_re = _squote_re = _dquote_re = None
@@ -928,41 +905,6 @@ def read_pypirc(repository=DEFAULT_REPOSITORY, realm=DEFAULT_REALM):
return {}
-def metadata_to_dict(meta):
- """XXX might want to move it to the Metadata class."""
- data = {
- 'metadata_version': meta.version,
- 'name': meta['Name'],
- 'version': meta['Version'],
- 'summary': meta['Summary'],
- 'home_page': meta['Home-page'],
- 'author': meta['Author'],
- 'author_email': meta['Author-email'],
- 'license': meta['License'],
- 'description': meta['Description'],
- 'keywords': meta['Keywords'],
- 'platform': meta['Platform'],
- 'classifier': meta['Classifier'],
- 'download_url': meta['Download-URL'],
- }
-
- if meta.version == '1.2':
- data['requires_dist'] = meta['Requires-Dist']
- data['requires_python'] = meta['Requires-Python']
- data['requires_external'] = meta['Requires-External']
- data['provides_dist'] = meta['Provides-Dist']
- data['obsoletes_dist'] = meta['Obsoletes-Dist']
- data['project_url'] = [','.join(url) for url in
- meta['Project-URL']]
-
- elif meta.version == '1.1':
- data['provides'] = meta['Provides']
- data['requires'] = meta['Requires']
- data['obsoletes'] = meta['Obsoletes']
-
- return data
-
-
# utility functions for 2to3 support
def run_2to3(files, doctests_only=False, fixer_names=None,