diff options
| author | ?ric Araujo <merwok@netwok.org> | 2011-09-18 20:20:13 +0200 |
|---|---|---|
| committer | ?ric Araujo <merwok@netwok.org> | 2011-09-18 20:20:13 +0200 |
| commit | 506cfea8bbd41e865bc36a836bdbc05aae8d74bb (patch) | |
| tree | 3bae418473347324060850aab8d34e162b33ecc9 /distutils2 | |
| parent | 8c928044705a70bb845cb45f76edb6eb71393866 (diff) | |
| download | disutils2-506cfea8bbd41e865bc36a836bdbc05aae8d74bb.tar.gz | |
Fix the backport fixes.
Backports:
- sysconfig is now always imported from our backports
- when hashlib is not found, our backport is used instead of the md5
module (debatable; we could just drop hashlib)
Version-dependent features:
- PEP 370 features are only enabled for 2.6+
- the check for sys.dont_write_bytecode was fixed to use getattr
with a default value instead of hasattr
Idioms/syntax:
- octal literals lost their extra 0
- misused try/except blocks have been changed back to try/finally
(it?s legal in 2.4 too, it?s only try/except/finally that isn?t)
- exception catching uses the regular 2.x idiom instead of sys.exc_info
- file objects are closed within finally blocks (this causes much
whitespace changes but actually makes diff with packaging easier)
Renamed modules:
- some missed renamings (_thread, Queue, isAlive, urllib.urlsplit, etc.)
were fixed
Other:
- a few false positive replacements of ?packaging? by ?distutils2? in
comments or docstrings were reverted
- util.is_packaging regained its name
- assorted whitespace/comment/import changes to match packaging
Diffstat (limited to 'distutils2')
53 files changed, 654 insertions, 570 deletions
diff --git a/distutils2/__init__.py b/distutils2/__init__.py index 1dfb997..9d330d2 100644 --- a/distutils2/__init__.py +++ b/distutils2/__init__.py @@ -1,4 +1,4 @@ -"""Support for distutils2, distribution and installation of Python projects. +"""Support for packaging, distribution and installation of Python projects. Third-party tools can use parts of distutils2 as building blocks without causing the other modules to be imported: diff --git a/distutils2/_backport/tests/test_sysconfig.py b/distutils2/_backport/tests/test_sysconfig.py index 2987732..93da719 100644 --- a/distutils2/_backport/tests/test_sysconfig.py +++ b/distutils2/_backport/tests/test_sysconfig.py @@ -254,7 +254,8 @@ class TestSysConfig(EnvironRestorer, unittest.TestCase): # Issue 7880 def get(python): cmd = [python, '-c', - 'import sysconfig; print sysconfig.get_platform()'] + 'from distutils2._backport import sysconfig; ' + 'print sysconfig.get_platform()'] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=os.environ) return p.communicate() real = os.path.realpath(sys.executable) diff --git a/distutils2/command/__init__.py b/distutils2/command/__init__.py index c80dde1..2babdda 100644 --- a/distutils2/command/__init__.py +++ b/distutils2/command/__init__.py @@ -28,8 +28,11 @@ _COMMANDS = { 'bdist_wininst': 'distutils2.command.bdist_wininst.bdist_wininst', 'register': 'distutils2.command.register.register', 'upload': 'distutils2.command.upload.upload', - 'upload_docs': 'distutils2.command.upload_docs.upload_docs'} + 'upload_docs': 'distutils2.command.upload_docs.upload_docs', +} +# XXX use OrderedDict to preserve the grouping (build-related, install-related, +# distribution-related) STANDARD_COMMANDS = set(_COMMANDS) diff --git a/distutils2/command/bdist.py b/distutils2/command/bdist.py index 1d6adea..d45842a 100644 --- a/distutils2/command/bdist.py +++ b/distutils2/command/bdist.py @@ -58,7 +58,7 @@ class bdist(Command): # This is of course very simplistic. The various UNIX family operating # systems have their specific formats, but they are out of scope for us; # bdist_dumb is, well, dumb; it's more a building block for other - # distutils2 tools than a real end-user binary format. + # packaging tools than a real end-user binary format. default_format = {'posix': 'gztar', 'nt': 'zip', 'os2': 'zip'} @@ -75,9 +75,8 @@ class bdist(Command): 'wininst': ('bdist_wininst', "Windows executable installer"), 'zip': ('bdist_dumb', "ZIP file"), - 'msi': ('bdist_msi', "Microsoft Installer") - } - + 'msi': ('bdist_msi', "Microsoft Installer"), + } def initialize_options(self): self.bdist_base = None @@ -109,8 +108,9 @@ class bdist(Command): try: self.formats = [self.default_format[os.name]] except KeyError: - raise PackagingPlatformError("don't know how to create built distributions " + \ - "on platform %s" % os.name) + raise PackagingPlatformError( + "don't know how to create built distributions " + "on platform %s" % os.name) if self.dist_dir is None: self.dist_dir = "dist" diff --git a/distutils2/command/bdist_dumb.py b/distutils2/command/bdist_dumb.py index 1a6da38..b15e743 100644 --- a/distutils2/command/bdist_dumb.py +++ b/distutils2/command/bdist_dumb.py @@ -7,11 +7,12 @@ sys.prefix or sys.exec_prefix. import os from shutil import rmtree -from sysconfig import get_python_version from distutils2.util import get_platform from distutils2.command.cmd import Command from distutils2.errors import PackagingPlatformError from distutils2 import logger +from distutils2._backport.sysconfig import get_python_version + class bdist_dumb(Command): @@ -44,10 +45,9 @@ class bdist_dumb(Command): boolean_options = ['keep-temp', 'skip-build', 'relative'] - default_format = { 'posix': 'gztar', - 'nt': 'zip', - 'os2': 'zip' } - + default_format = {'posix': 'gztar', + 'nt': 'zip', + 'os2': 'zip'} def initialize_options(self): self.bdist_dir = None @@ -69,8 +69,9 @@ class bdist_dumb(Command): try: self.format = self.default_format[os.name] except KeyError: - raise PackagingPlatformError(("don't know how to create dumb built distributions " + - "on platform %s") % os.name) + raise PackagingPlatformError( + "don't know how to create dumb built distributions " + "on platform %s" % os.name) self.set_undefined_options('bdist', 'dist_dir', 'plat_name') diff --git a/distutils2/command/bdist_msi.py b/distutils2/command/bdist_msi.py index aa09644..ad96911 100644 --- a/distutils2/command/bdist_msi.py +++ b/distutils2/command/bdist_msi.py @@ -8,7 +8,7 @@ import os import msilib -from sysconfig import get_python_version +from distutils2._backport.sysconfig import get_python_version from shutil import rmtree from distutils2.command.cmd import Command from distutils2.version import NormalizedVersion @@ -391,19 +391,23 @@ class bdist_msi(Command): if self.pre_install_script: scriptfn = os.path.join(self.bdist_dir, "preinstall.bat") f = open(scriptfn, "w") - # The batch file will be executed with [PYTHON], so that %1 - # is the path to the Python interpreter; %0 will be the path - # of the batch file. - # rem =""" - # %1 %0 - # exit - # """ - # <actual script> - f.write('rem ="""\n%1 %0\nexit\n"""\n') - fp = open(self.pre_install_script) - f.write(fp.read()) - fp.close() - f.close() + try: + # The batch file will be executed with [PYTHON], so that %1 + # is the path to the Python interpreter; %0 will be the path + # of the batch file. + # rem =""" + # %1 %0 + # exit + # """ + # <actual script> + f.write('rem ="""\n%1 %0\nexit\n"""\n') + fp = open(self.pre_install_script) + try: + f.write(fp.read()) + finally: + fp.close() + finally: + f.close() add_data(self.db, "Binary", [("PreInstall", msilib.Binary(scriptfn)), ]) diff --git a/distutils2/command/bdist_wininst.py b/distutils2/command/bdist_wininst.py index ef32977..81a8391 100644 --- a/distutils2/command/bdist_wininst.py +++ b/distutils2/command/bdist_wininst.py @@ -6,11 +6,11 @@ import sys import os from shutil import rmtree -from sysconfig import get_python_version from distutils2.command.cmd import Command from distutils2.errors import PackagingOptionError, PackagingPlatformError from distutils2 import logger from distutils2.util import get_platform +from distutils2._backport.sysconfig import get_python_version class bdist_wininst(Command): @@ -246,49 +246,56 @@ class bdist_wininst(Command): if bitmap: fp = open(bitmap, "rb") - bitmapdata = fp.read() - fp.close() + try: + bitmapdata = fp.read() + finally: + fp.close() bitmaplen = len(bitmapdata) else: bitmaplen = 0 file = open(installer_name, "wb") - file.write(self.get_exe_bytes()) - if bitmap: - file.write(bitmapdata) + try: + file.write(self.get_exe_bytes()) + if bitmap: + file.write(bitmapdata) - # Convert cfgdata from unicode to ascii, mbcs encoded - if isinstance(cfgdata, unicode): - cfgdata = cfgdata.encode("mbcs") + # Convert cfgdata from unicode to ascii, mbcs encoded + if isinstance(cfgdata, unicode): + cfgdata = cfgdata.encode("mbcs") - # Append the pre-install script - cfgdata = cfgdata + "\0" - if self.pre_install_script: - fp = open(self.pre_install_script) - script_data = fp.read() - fp.close() - cfgdata = cfgdata + script_data + "\n\0" - else: - # empty pre-install script + # Append the pre-install script cfgdata = cfgdata + "\0" - file.write(cfgdata) - - # The 'magic number' 0x1234567B is used to make sure that the - # binary layout of 'cfgdata' is what the wininst.exe binary - # expects. If the layout changes, increment that number, make - # the corresponding changes to the wininst.exe sources, and - # recompile them. - header = struct.pack("<iii", - 0x1234567B, # tag - len(cfgdata), # length - bitmaplen, # number of bytes in bitmap - ) - file.write(header) - file.close() - - fp = open(arcname, "rb") - file.write(fp.read()) - fp.close() + if self.pre_install_script: + fp = open(self.pre_install_script) + try: + script_data = fp.read() + finally: + fp.close() + cfgdata = cfgdata + script_data + "\n\0" + else: + # empty pre-install script + cfgdata = cfgdata + "\0" + file.write(cfgdata) + + # The 'magic number' 0x1234567B is used to make sure that the + # binary layout of 'cfgdata' is what the wininst.exe binary + # expects. If the layout changes, increment that number, make + # the corresponding changes to the wininst.exe sources, and + # recompile them. + header = struct.pack("<iii", + 0x1234567B, # tag + len(cfgdata), # length + bitmaplen, # number of bytes in bitmap + ) + file.write(header) + fp = open(arcname, "rb") + try: + file.write(fp.read()) + finally: + fp.close() + finally: + file.close() def get_installer_filename(self, fullname): # Factored out to allow overriding in subclasses @@ -344,6 +351,8 @@ class bdist_wininst(Command): filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix)) fp = open(filename, "rb") - content = fp.read() - fp.close() + try: + content = fp.read() + finally: + fp.close() return content diff --git a/distutils2/command/build_clib.py b/distutils2/command/build_clib.py index 677a2ee..0a8807f 100644 --- a/distutils2/command/build_clib.py +++ b/distutils2/command/build_clib.py @@ -16,7 +16,7 @@ distribution and needed by extension modules. import os from distutils2.command.cmd import Command from distutils2.errors import PackagingSetupError -from distutils2.compiler import customize_compiler +from distutils2.compiler import customize_compiler, new_compiler from distutils2 import logger @@ -93,7 +93,6 @@ class build_clib(Command): return # Yech -- this is cut 'n pasted from build_ext.py! - from distutils2.compiler import new_compiler self.compiler = new_compiler(compiler=self.compiler, dry_run=self.dry_run, force=self.force) diff --git a/distutils2/command/build_ext.py b/distutils2/command/build_ext.py index ad2077b..8b61533 100644 --- a/distutils2/command/build_ext.py +++ b/distutils2/command/build_ext.py @@ -1,9 +1,5 @@ """Build extension modules.""" -# FIXME Is this module limited to C extensions or do C++ extensions work too? -# The docstring of this module said that C++ was not supported, but other -# comments contradict that. - import os import re import sys @@ -20,7 +16,10 @@ from distutils2.compiler.extension import Extension from distutils2 import logger import site -HAS_USER_SITE = True +if sys.version_info[:2] >= (2, 6): + HAS_USER_SITE = True +else: + HAS_USER_SITE = False if os.name == 'nt': from distutils2.compiler.msvccompiler import get_build_version @@ -363,12 +362,11 @@ class build_ext(Command): for ext in self.extensions: try: self.build_extension(ext) - except (CCompilerError, PackagingError, CompileError): + except (CCompilerError, PackagingError, CompileError), e: if not ext.optional: raise logger.warning('%s: building extension %r failed: %s', - self.get_command_name(), ext.name, - sys.exc_info()[1]) + self.get_command_name(), ext.name, e) def build_extension(self, ext): sources = ext.sources @@ -608,8 +606,7 @@ class build_ext(Command): template = "python%d%d" if self.debug: template = template + '_d' - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + pythonlib = template % sys.version_info[:2] # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] @@ -623,22 +620,19 @@ class build_ext(Command): # not at this time - AIM Apr01 #if self.debug: # template = template + '_d' - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + pythonlib = template % sys.version_info[:2] # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] elif sys.platform[:6] == "cygwin": template = "python%d.%d" - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + pythonlib = template % sys.version_info[:2] # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] elif sys.platform[:6] == "atheos": template = "python%d.%d" - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + pythonlib = template % sys.version_info[:2] # Get SHLIBS from Makefile extra = [] for lib in sysconfig.get_config_var('SHLIBS').split(): @@ -656,8 +650,8 @@ class build_ext(Command): else: if sysconfig.get_config_var('Py_ENABLE_SHARED'): - pythonlib = 'python%s.%s' % ( - sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff) + template = 'python%d.%d' + sys.abiflags + pythonlib = template % sys.version_info[:2] return ext.libraries + [pythonlib] else: return ext.libraries diff --git a/distutils2/command/build_py.py b/distutils2/command/build_py.py index f9b6787..fec81a9 100644 --- a/distutils2/command/build_py.py +++ b/distutils2/command/build_py.py @@ -388,12 +388,12 @@ class build_py(Command, Mixin2to3): self.build_module(module, module_file, package) def byte_compile(self, files): - if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode: + if getattr(sys, 'dont_write_bytecode', False): logger.warning('%s: byte-compiling is disabled, skipping.', self.get_command_name()) return - from distutils2.util import byte_compile + from distutils2.util import byte_compile # FIXME use compileall prefix = self.build_lib if prefix[-1] != os.sep: prefix = prefix + os.sep diff --git a/distutils2/command/build_scripts.py b/distutils2/command/build_scripts.py index a61f382..8a48e07 100644 --- a/distutils2/command/build_scripts.py +++ b/distutils2/command/build_scripts.py @@ -130,9 +130,11 @@ class build_scripts(Command, Mixin2to3): "from the script encoding (%s)" % ( shebang, encoding)) outf = open(outfile, "wb") - outf.write(shebang) - outf.writelines(f.readlines()) - outf.close() + try: + outf.write(shebang) + outf.writelines(f.readlines()) + finally: + outf.close() if f: f.close() else: @@ -146,7 +148,7 @@ class build_scripts(Command, Mixin2to3): logger.info("changing mode of %s", file) else: oldmode = os.stat(file).st_mode & 07777 - newmode = (oldmode | 00555) & 07777 + newmode = (oldmode | 0555) & 07777 if newmode != oldmode: logger.info("changing mode of %s from %o to %o", file, oldmode, newmode) diff --git a/distutils2/command/cmd.py b/distutils2/command/cmd.py index 8fe2e7b..9076906 100644 --- a/distutils2/command/cmd.py +++ b/distutils2/command/cmd.py @@ -5,6 +5,7 @@ import re from shutil import copyfile, move from distutils2 import util from distutils2 import logger +from distutils2.util import make_archive from distutils2.errors import PackagingOptionError @@ -403,9 +404,9 @@ class Command(object): def make_archive(self, base_name, format, root_dir=None, base_dir=None, owner=None, group=None): - return util.make_archive(base_name, format, root_dir, - base_dir, dry_run=self.dry_run, - owner=owner, group=group) + return make_archive(base_name, format, root_dir, + base_dir, dry_run=self.dry_run, + owner=owner, group=group) def make_file(self, infiles, outfile, func, args, exec_msg=None, skip_msg=None, level=1): diff --git a/distutils2/command/config.py b/distutils2/command/config.py index 3386dd4..e3af2e5 100644 --- a/distutils2/command/config.py +++ b/distutils2/command/config.py @@ -111,14 +111,16 @@ class config(Command): def _gen_temp_sourcefile(self, body, headers, lang): filename = "_configtest" + LANG_EXT[lang] file = open(filename, "w") - if headers: - for header in headers: - file.write("#include <%s>\n" % header) - file.write("\n") - file.write(body) - if body[-1] != "\n": - file.write("\n") - file.close() + try: + if headers: + for header in headers: + file.write("#include <%s>\n" % header) + file.write("\n") + file.write(body) + if body[-1] != "\n": + file.write("\n") + finally: + file.close() return filename def _preprocess(self, body, headers, include_dirs, lang): @@ -208,14 +210,17 @@ class config(Command): pattern = re.compile(pattern) file = open(out) - match = False - while True: - line = file.readline() - if line == '': - break - if pattern.search(line): - match = True - break + try: + match = False + while True: + line = file.readline() + if line == '': + break + if pattern.search(line): + match = True + break + finally: + file.close() self._clean() return match @@ -347,5 +352,7 @@ def dump_file(filename, head=None): else: logger.info(head) file = open(filename) - logger.info(file.read()) - file.close() + try: + logger.info(file.read()) + finally: + file.close() diff --git a/distutils2/command/install_data.py b/distutils2/command/install_data.py index 78cb6e2..c1fd462 100644 --- a/distutils2/command/install_data.py +++ b/distutils2/command/install_data.py @@ -2,7 +2,7 @@ # Contributed by Bastian Kleineidam -import os, sys +import os from shutil import Error from distutils2 import logger from distutils2.util import convert_path @@ -48,8 +48,7 @@ class install_data(Command): self.mkpath(dir_dest) try: out = self.copy_file(_file[0], dir_dest)[0] - except Error: - e = sys.exc_info()[1] + except Error, e: logger.warning('%s: %s', self.get_command_name(), e) out = destination diff --git a/distutils2/command/install_dist.py b/distutils2/command/install_dist.py index 5c591b1..89ea15f 100644 --- a/distutils2/command/install_dist.py +++ b/distutils2/command/install_dist.py @@ -295,9 +295,9 @@ class install_dist(Command): self.dump_dirs("post-expand_dirs()") - # Create directories in the home dir: + # Create directories under USERBASE if HAS_USER_SITE and self.user: - self.create_home_path() + self.create_user_dirs() # Pick the actual directory to install all modules to: either # install_purelib or install_platlib, depending on whether this @@ -494,14 +494,12 @@ class install_dist(Command): attr = "install_" + name setattr(self, attr, change_root(self.root, getattr(self, attr))) - def create_home_path(self): - """Create directories under ~.""" - if HAS_USER_SITE and not self.user: - return + def create_user_dirs(self): + """Create directories under USERBASE as needed.""" home = convert_path(os.path.expanduser("~")) for name, path in self.config_vars.items(): if path.startswith(home) and not os.path.isdir(path): - os.makedirs(path, 00700) + os.makedirs(path, 0700) # -- Command execution methods ------------------------------------- diff --git a/distutils2/command/install_distinfo.py b/distutils2/command/install_distinfo.py index 8beabd4..50382a3 100644 --- a/distutils2/command/install_distinfo.py +++ b/distutils2/command/install_distinfo.py @@ -8,7 +8,7 @@ import os import re try: import hashlib -except ImportError: #<2.5 +except ImportError: from distutils2._backport import hashlib from distutils2.command.cmd import Command @@ -32,7 +32,7 @@ class install_distinfo(Command): ('no-record', None, "do not generate a RECORD file"), ('no-resources', None, - "do not generate a RESSOURCES list installed file") + "do not generate a RESSOURCES list installed file"), ] boolean_options = ['requested', 'no-record', 'no-resources'] diff --git a/distutils2/command/install_lib.py b/distutils2/command/install_lib.py index ef02c14..028e1aa 100644 --- a/distutils2/command/install_lib.py +++ b/distutils2/command/install_lib.py @@ -114,7 +114,7 @@ class install_lib(Command): return outfiles def byte_compile(self, files): - if hasattr(sys, 'dont_write_bytecode'): + if getattr(sys, 'dont_write_bytecode', False): # XXX do we want this? because a Python runs without bytecode # doesn't mean that the *dists should not contain bytecode #--or does it? @@ -122,7 +122,7 @@ class install_lib(Command): self.get_command_name()) return - from distutils2.util import byte_compile + from distutils2.util import byte_compile # FIXME use compileall # Get the "--root" directory supplied to the "install_dist" command, # and use it as a prefix to strip off the purported filename diff --git a/distutils2/command/install_scripts.py b/distutils2/command/install_scripts.py index e8cb332..3bed33c 100644 --- a/distutils2/command/install_scripts.py +++ b/distutils2/command/install_scripts.py @@ -48,7 +48,7 @@ class install_scripts(Command): if self.dry_run: logger.info("changing mode of %s", file) else: - mode = (os.stat(file).st_mode | 00555) & 07777 + mode = (os.stat(file).st_mode | 0555) & 07777 logger.info("changing mode of %s to %o", file, mode) os.chmod(file, mode) diff --git a/distutils2/command/register.py b/distutils2/command/register.py index 6f28585..de69a2f 100644 --- a/distutils2/command/register.py +++ b/distutils2/command/register.py @@ -2,14 +2,13 @@ # Contributed by Richard Jones -import sys import getpass -import urlparse import urllib2 +import urlparse from distutils2 import logger from distutils2.util import (read_pypirc, generate_pypirc, DEFAULT_REPOSITORY, - DEFAULT_REALM, get_pypirc_path, encode_multipart) + DEFAULT_REALM, get_pypirc_path, encode_multipart) from distutils2.command.cmd import Command class register(Command): @@ -246,13 +245,12 @@ Your selection [default 1]: ''') data = '' try: result = opener.open(req) - except urllib2.HTTPError: - e = sys.exc_info()[1] + except urllib2.HTTPError, e: if self.show_response: data = e.fp.read() result = e.code, e.msg - except urllib2.URLError: - result = 500, str(sys.exc_info()[1]) + except urllib2.URLError, e: + result = 500, str(e) else: if self.show_response: data = result.read() diff --git a/distutils2/command/sdist.py b/distutils2/command/sdist.py index d03a448..b124f73 100644 --- a/distutils2/command/sdist.py +++ b/distutils2/command/sdist.py @@ -9,7 +9,7 @@ from shutil import rmtree from distutils2 import logger from distutils2.util import resolve_name, get_archive_formats from distutils2.errors import (PackagingPlatformError, PackagingOptionError, - PackagingModuleError, PackagingFileError) + PackagingModuleError, PackagingFileError) from distutils2.command import get_command_names from distutils2.command.cmd import Command from distutils2.manifest import Manifest @@ -143,8 +143,8 @@ class sdist(Command): continue try: builder = resolve_name(builder) - except ImportError: - raise PackagingModuleError(sys.exc_info()[1]) + except ImportError, e: + raise PackagingModuleError(e) builders.append(builder) @@ -337,7 +337,7 @@ class sdist(Command): """ return self.archive_files - def create_tree(self, base_dir, files, mode=00777, verbose=1, + def create_tree(self, base_dir, files, mode=0777, verbose=1, dry_run=False): need_dir = set() for file in files: diff --git a/distutils2/command/upload.py b/distutils2/command/upload.py index 6c9d69a..0bdac4a 100644 --- a/distutils2/command/upload.py +++ b/distutils2/command/upload.py @@ -1,6 +1,6 @@ """Upload a distribution to a project index.""" -import os, sys +import os import socket import logging import platform @@ -16,7 +16,7 @@ from urllib2 import urlopen, Request from distutils2 import logger from distutils2.errors import PackagingOptionError from distutils2.util import (spawn, read_pypirc, DEFAULT_REPOSITORY, - DEFAULT_REALM, encode_multipart) + DEFAULT_REALM, encode_multipart) from distutils2.command.cmd import Command @@ -105,8 +105,10 @@ class upload(Command): # Fill in the data - send all the metadata in case we need to # register a new release f = open(filename, 'rb') - content = f.read() - f.close() + try: + content = f.read() + finally: + f.close() data = self.distribution.metadata.todict() @@ -123,8 +125,10 @@ class upload(Command): if self.sign: fp = open(filename + '.asc') - sig = fp.read() - fp.close() + try: + sig = fp.read() + finally: + fp.close() data['gpg_signature'] = [ (os.path.basename(filename) + ".asc", sig)] @@ -156,11 +160,10 @@ class upload(Command): result = urlopen(request) status = result.code reason = result.msg - except socket.error: - logger.error(sys.exc_info()[1]) + except socket.error, e: + logger.error(e) return - except HTTPError: - e = sys.exc_info()[1] + except HTTPError, e: status = e.code reason = e.msg diff --git a/distutils2/command/upload_docs.py b/distutils2/command/upload_docs.py index 7f3523f..2f813d3 100644 --- a/distutils2/command/upload_docs.py +++ b/distutils2/command/upload_docs.py @@ -1,6 +1,6 @@ """Upload HTML documentation to a project index.""" -import os, sys +import os import base64 import socket import zipfile @@ -11,7 +11,7 @@ from StringIO import StringIO from distutils2 import logger from distutils2.util import (read_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM, - encode_multipart) + encode_multipart) from distutils2.errors import PackagingFileError from distutils2.command.cmd import Command @@ -20,13 +20,15 @@ def zip_dir(directory): """Compresses recursively contents of directory into a BytesIO object""" destination = StringIO() zip_file = zipfile.ZipFile(destination, "w") - for root, dirs, files in os.walk(directory): - for name in files: - full = os.path.join(root, name) - relative = root[len(directory):].lstrip(os.path.sep) - dest = os.path.join(relative, name) - zip_file.write(full, dest) - zip_file.close() + try: + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + relative = root[len(directory):].lstrip(os.path.sep) + dest = os.path.join(relative, name) + zip_file.write(full, dest) + finally: + zip_file.close() return destination @@ -88,7 +90,8 @@ class upload_docs(Command): content_type, body = encode_multipart(fields, files) credentials = self.username + ':' + self.password - auth = "Basic " + base64.encodebytes(credentials.encode()).strip() + # FIXME should use explicit encoding + auth = "Basic " + base64.encodestring(credentials.encode()).strip() logger.info("Submitting documentation to %s", self.repository) @@ -110,8 +113,8 @@ class upload_docs(Command): conn.endheaders() conn.send(body) - except socket.error: - logger.error(sys.exc_info()[1]) + except socket.error, e: + logger.error(e) return r = conn.getresponse() diff --git a/distutils2/compiler/bcppcompiler.py b/distutils2/compiler/bcppcompiler.py index d44468b..b7d5bb3 100644 --- a/distutils2/compiler/bcppcompiler.py +++ b/distutils2/compiler/bcppcompiler.py @@ -7,10 +7,10 @@ # someone should sit down and factor out the common code as # WindowsCCompiler! --GPW -import os, sys +import os from distutils2.errors import (PackagingExecError, CompileError, LibError, - LinkError, UnknownFileError) + LinkError, UnknownFileError) from distutils2.compiler.ccompiler import CCompiler from distutils2.compiler import gen_preprocess_options from distutils2.file_util import write_file @@ -104,8 +104,8 @@ class BCPPCompiler(CCompiler) : # This needs to be compiled to a .res file -- do it now. try: self.spawn(["brcc32", "-fo", obj, src]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) continue # the 'for' loop # The next two are both for the real compiler. @@ -128,8 +128,8 @@ class BCPPCompiler(CCompiler) : self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs + [src]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) return objects @@ -146,8 +146,8 @@ class BCPPCompiler(CCompiler) : pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except PackagingExecError: - raise LibError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LibError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) @@ -268,8 +268,8 @@ class BCPPCompiler(CCompiler) : self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except PackagingExecError: - raise LinkError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LinkError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) diff --git a/distutils2/compiler/ccompiler.py b/distutils2/compiler/ccompiler.py index a8a479b..8ea2e50 100644 --- a/distutils2/compiler/ccompiler.py +++ b/distutils2/compiler/ccompiler.py @@ -8,7 +8,7 @@ import os from shutil import move from distutils2 import logger from distutils2.util import split_quoted, execute, newer_group, spawn -from distutils2.errors import (CompileError, LinkError, UnknownFileError) +from distutils2.errors import CompileError, LinkError, UnknownFileError from distutils2.compiler import gen_preprocess_options @@ -728,14 +728,16 @@ class CCompiler(object): library_dirs = [] fd, fname = tempfile.mkstemp(".c", funcname, text=True) f = os.fdopen(fd, "w") - for incl in includes: - f.write("""#include "%s"\n""" % incl) - f.write("""\ + try: + for incl in includes: + f.write("""#include "%s"\n""" % incl) + f.write("""\ main (int argc, char **argv) { %s(); } """ % funcname) - f.close() + finally: + f.close() try: objects = self.compile([fname], include_dirs=include_dirs) except CompileError: @@ -852,7 +854,7 @@ main (int argc, char **argv) { return return move(src, dst) - def mkpath(self, name, mode=00777): + def mkpath(self, name, mode=0777): name = os.path.normpath(name) if os.path.isdir(name) or name == '': return diff --git a/distutils2/compiler/cygwinccompiler.py b/distutils2/compiler/cygwinccompiler.py index b580f66..2b1c59a 100644 --- a/distutils2/compiler/cygwinccompiler.py +++ b/distutils2/compiler/cygwinccompiler.py @@ -156,14 +156,14 @@ class CygwinCCompiler(UnixCCompiler): # gcc needs '.res' and '.rc' compiled to object files !!! try: self.spawn(["windres", "-i", src, "-o", obj]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, 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 PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, @@ -345,12 +345,13 @@ def check_config_h(): fn = sysconfig.get_config_h_filename() try: config_h = open(fn) - 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 - config_h.close() - except IOError: - exc = sys.exc_info()[1] + try: + 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: + config_h.close() + except IOError, exc: return (CONFIG_H_UNCERTAIN, "couldn't read '%s': %s" % (fn, exc.strerror)) diff --git a/distutils2/compiler/msvc9compiler.py b/distutils2/compiler/msvc9compiler.py index 1cda8b0..a7a524e 100644 --- a/distutils2/compiler/msvc9compiler.py +++ b/distutils2/compiler/msvc9compiler.py @@ -14,7 +14,7 @@ import sys import re from distutils2.errors import (PackagingExecError, PackagingPlatformError, - CompileError, LibError, LinkError) + CompileError, LibError, LinkError) from distutils2.compiler.ccompiler import CCompiler from distutils2.compiler import gen_lib_options from distutils2 import logger @@ -477,8 +477,8 @@ class MSVCCompiler(CCompiler) : try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) continue elif ext in self._mc_extensions: # Compile .MC to .RC file to .RES file. @@ -504,8 +504,8 @@ class MSVCCompiler(CCompiler) : self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) continue else: # how to handle this file? @@ -517,8 +517,8 @@ class MSVCCompiler(CCompiler) : self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) return objects @@ -542,8 +542,8 @@ class MSVCCompiler(CCompiler) : pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except PackagingExecError: - raise LibError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LibError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) @@ -620,8 +620,8 @@ class MSVCCompiler(CCompiler) : self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except PackagingExecError: - raise LinkError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LinkError(msg) # embed the manifest # XXX - this is somewhat fragile - if mt.exe fails, distutils @@ -637,8 +637,8 @@ class MSVCCompiler(CCompiler) : try: self.spawn(['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) - except PackagingExecError: - raise LinkError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LinkError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) diff --git a/distutils2/compiler/msvccompiler.py b/distutils2/compiler/msvccompiler.py index 34a5072..fb4d521 100644 --- a/distutils2/compiler/msvccompiler.py +++ b/distutils2/compiler/msvccompiler.py @@ -12,7 +12,7 @@ import sys import os from distutils2.errors import (PackagingExecError, PackagingPlatformError, - CompileError, LibError, LinkError) + CompileError, LibError, LinkError) from distutils2.compiler.ccompiler import CCompiler from distutils2.compiler import gen_lib_options from distutils2 import logger @@ -386,8 +386,8 @@ class MSVCCompiler(CCompiler): try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) continue elif ext in self._mc_extensions: @@ -415,8 +415,8 @@ class MSVCCompiler(CCompiler): self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) continue else: # how to handle this file? @@ -429,8 +429,8 @@ class MSVCCompiler(CCompiler): self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) return objects @@ -448,8 +448,8 @@ class MSVCCompiler(CCompiler): pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except PackagingExecError: - raise LibError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LibError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) @@ -515,8 +515,8 @@ class MSVCCompiler(CCompiler): self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except PackagingExecError: - raise LinkError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LinkError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) diff --git a/distutils2/compiler/unixccompiler.py b/distutils2/compiler/unixccompiler.py index e80a030..02af746 100644 --- a/distutils2/compiler/unixccompiler.py +++ b/distutils2/compiler/unixccompiler.py @@ -127,7 +127,7 @@ class UnixCCompiler(CCompiler): executables['ranlib'] = ["ranlib"] # Needed for the filename generation methods provided by the base - # class, CCompiler. NB. whoever instantiates/uses a particular + # class, CCompiler. XXX whoever instantiates/uses a particular # UnixCCompiler instance should set 'shared_lib_ext' -- we set a # reasonable common default here, but it's not necessarily used on all # Unices! @@ -165,8 +165,8 @@ class UnixCCompiler(CCompiler): self.mkpath(os.path.dirname(output_file)) try: self.spawn(pp_args) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): compiler_so = self.compiler_so @@ -175,8 +175,8 @@ class UnixCCompiler(CCompiler): try: self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs) - except PackagingExecError: - raise CompileError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise CompileError(msg) def create_static_lib(self, objects, output_libname, output_dir=None, debug=False, target_lang=None): @@ -199,8 +199,8 @@ class UnixCCompiler(CCompiler): if self.ranlib: try: self.spawn(self.ranlib + [output_filename]) - except PackagingExecError: - raise LibError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LibError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) @@ -253,8 +253,8 @@ class UnixCCompiler(CCompiler): linker = _darwin_compiler_fixup(linker, ld_args) self.spawn(linker + ld_args) - except PackagingExecError: - raise LinkError(sys.exc_info()[1]) + except PackagingExecError, msg: + raise LinkError(msg) else: logger.debug("skipping %s (up-to-date)", output_filename) diff --git a/distutils2/config.py b/distutils2/config.py index 30f92c9..1a85651 100644 --- a/distutils2/config.py +++ b/distutils2/config.py @@ -1,8 +1,8 @@ """Utilities to find and read config files used by distutils2.""" -import codecs import os import sys +import codecs import logging from shlex import split @@ -11,7 +11,7 @@ from distutils2 import logger from distutils2.errors import PackagingOptionError from distutils2.compiler.extension import Extension from distutils2.util import (check_environ, iglob, resolve_name, strtobool, - split_multiline) + split_multiline) from distutils2.compiler import set_compiler from distutils2.command import set_command from distutils2.markers import interpret @@ -142,9 +142,9 @@ class Config(object): for line in setup_hooks: try: hook = resolve_name(line) - except ImportError: + except ImportError, e: logger.warning('cannot find setup hook: %s', - sys.exc_info()[1].args[0]) + e.args[0]) else: self.setup_hooks.append(hook) self.run_hooks(content) @@ -178,8 +178,10 @@ class Config(object): for filename in filenames: # will raise if file not found description_file = open(filename) - value.append(description_file.read().strip()) - description_file.close() + try: + value.append(description_file.read().strip()) + finally: + description_file.close() # add filename as a required file if filename not in metadata.requires_files: metadata.requires_files.append(filename) @@ -290,8 +292,10 @@ class Config(object): for filename in filenames: logger.debug(" reading %s", filename) f = codecs.open(filename, 'r', encoding='utf-8') - parser.readfp(f) - f.close() + try: + parser.readfp(f) + finally: + f.close() if os.path.split(filename)[-1] == 'setup.cfg': self._read_setup_cfg(parser, filename) @@ -348,8 +352,8 @@ class Config(object): setattr(self.dist, opt, strtobool(val)) else: setattr(self.dist, opt, val) - except ValueError: - raise PackagingOptionError(sys.exc_info()[1]) + except ValueError, msg: + raise PackagingOptionError(msg) def _load_compilers(self, compilers): compilers = split_multiline(compilers) diff --git a/distutils2/create.py b/distutils2/create.py index cbb5ef9..1d141ca 100644 --- a/distutils2/create.py +++ b/distutils2/create.py @@ -18,30 +18,33 @@ be called as *pysetup create*. # Ask for a description # Detect scripts (not sure how. #! outside of package?) -import codecs import os import re import imp import sys import glob +import codecs import shutil -from distutils2._backport import sysconfig -if 'any' not in dir(__builtins__): - from distutils2._backport import any -try: - from hashlib import md5 -except ImportError: #<2.5 - from md5 import md5 from textwrap import dedent -from distutils2.util import cmp_to_key, detect_encoding from ConfigParser import RawConfigParser +from distutils2.util import cmp_to_key, detect_encoding # importing this with an underscore as it should be replaced by the # dict form or another structures for all purposes from distutils2._trove import all_classifiers as _CLASSIFIERS_LIST from distutils2.version import is_valid_version +from distutils2._backport import sysconfig +try: + any +except NameError: + from distutils2._backport import any +try: + from hashlib import md5 +except ImportError: + from distutils2._backport.hashlib import md5 + _FILENAME = 'setup.cfg' -_DEFAULT_CFG = '.pypkgcreate' +_DEFAULT_CFG = '.pypkgcreate' # FIXME use a section in user .pydistutils.cfg _helptext = { 'name': ''' @@ -117,11 +120,16 @@ def load_setup(): been loaded before, because we are monkey patching its setup function with a particular one""" f = open("setup.py", "rb") - encoding, lines = detect_encoding(f.readline) - f.close() + try: + encoding, lines = detect_encoding(f.readline) + finally: + f.close() f = open("setup.py") - imp.load_module("setup", f, "setup.py", (".py", "r", imp.PY_SOURCE)) - f.close() + try: + imp.load_module("setup", f, "setup.py", (".py", "r", imp.PY_SOURCE)) + finally: + f.close() + def ask_yn(question, default=None, helptext=None): question += ' (y/n)' @@ -133,6 +141,10 @@ def ask_yn(question, default=None, helptext=None): print '\nERROR: You must select "Y" or "N".\n' +# XXX use util.ask +# FIXME: if prompt ends with '?', don't add ':' + + def ask(question, default=None, helptext=None, required=True, lengthy=False, multiline=False): prompt = u'%s: ' % (question,) @@ -280,50 +292,52 @@ class MainProgram(object): shutil.move(_FILENAME, '%s.old' % _FILENAME) fp = codecs.open(_FILENAME, 'w', encoding='utf-8') - fp.write(u'[metadata]\n') - # TODO use metadata module instead of hard-coding field-specific - # behavior here - - # simple string entries - for name in ('name', 'version', 'summary', 'download_url'): - fp.write(u'%s = %s\n' % (name, self.data.get(name, 'UNKNOWN'))) - - # optional string entries - if 'keywords' in self.data and self.data['keywords']: - fp.write(u'keywords = %s\n' % ' '.join(self.data['keywords'])) - for name in ('home_page', 'author', 'author_email', - 'maintainer', 'maintainer_email', 'description-file'): - if name in self.data and self.data[name]: - fp.write(u'%s = %s\n' % (name.decode('utf-8'), - self.data[name].decode('utf-8'))) - if 'description' in self.data: - fp.write( - u'description = %s\n' - % u'\n |'.join(self.data['description'].split('\n'))) - - # multiple use string entries - for name in ('platform', 'supported-platform', 'classifier', - 'requires-dist', 'provides-dist', 'obsoletes-dist', - 'requires-external'): - if not(name in self.data and self.data[name]): - continue - fp.write(u'%s = ' % name) - fp.write(u''.join(' %s\n' % val - for val in self.data[name]).lstrip()) - fp.write(u'\n[files]\n') - for name in ('packages', 'modules', 'scripts', - 'package_data', 'extra_files'): - if not(name in self.data and self.data[name]): - continue - fp.write(u'%s = %s\n' - % (name, u'\n '.join(self.data[name]).strip())) - fp.write(u'\nresources =\n') - for src, dest in self.data['resources']: - fp.write(u' %s = %s\n' % (src, dest)) - fp.write(u'\n') - fp.close() - - os.chmod(_FILENAME, 00644) + try: + fp.write(u'[metadata]\n') + # TODO use metadata module instead of hard-coding field-specific + # behavior here + + # simple string entries + for name in ('name', 'version', 'summary', 'download_url'): + fp.write(u'%s = %s\n' % (name, self.data.get(name, 'UNKNOWN'))) + + # optional string entries + if 'keywords' in self.data and self.data['keywords']: + fp.write(u'keywords = %s\n' % ' '.join(self.data['keywords'])) + for name in ('home_page', 'author', 'author_email', + 'maintainer', 'maintainer_email', 'description-file'): + if name in self.data and self.data[name]: + fp.write(u'%s = %s\n' % (name.decode('utf-8'), + self.data[name].decode('utf-8'))) + if 'description' in self.data: + fp.write( + u'description = %s\n' + % u'\n |'.join(self.data['description'].split('\n'))) + + # multiple use string entries + for name in ('platform', 'supported-platform', 'classifier', + 'requires-dist', 'provides-dist', 'obsoletes-dist', + 'requires-external'): + if not(name in self.data and self.data[name]): + continue + fp.write(u'%s = ' % name) + fp.write(u''.join(' %s\n' % val + for val in self.data[name]).lstrip()) + fp.write(u'\n[files]\n') + for name in ('packages', 'modules', 'scripts', + 'package_data', 'extra_files'): + if not(name in self.data and self.data[name]): + continue + fp.write(u'%s = %s\n' + % (name, u'\n '.join(self.data[name]).strip())) + fp.write(u'\nresources =\n') + for src, dest in self.data['resources']: + fp.write(u' %s = %s\n' % (src, dest)) + fp.write(u'\n') + finally: + fp.close() + + os.chmod(_FILENAME, 0644) print 'Wrote %r.' % _FILENAME def convert_py_to_cfg(self): @@ -418,8 +432,10 @@ class MainProgram(object): ref = ref.digest() for readme in glob.glob('README*'): fp = codecs.open(readme, encoding='utf-8') - contents = fp.read() - fp.close() + try: + contents = fp.read() + finally: + fp.close() contents = re.sub('\s', '', contents.lower()).encode() val = md5(contents).digest() if val == ref: diff --git a/distutils2/database.py b/distutils2/database.py index e6fdec1..52da386 100644 --- a/distutils2/database.py +++ b/distutils2/database.py @@ -1,15 +1,16 @@ """PEP 376 implementation.""" -from StringIO import StringIO import os import re import csv import sys import zipimport +from StringIO import StringIO try: from hashlib import md5 -except ImportError: #<2.5 - from md5 import md5 +except ImportError: + from distutils2._backport.hashlib import md5 + from distutils2 import logger from distutils2.errors import PackagingError from distutils2.version import suggest_normalized_version, VersionPredicate @@ -162,26 +163,30 @@ class Distribution(object): def _get_records(self, local=False): results = [] record = self.get_distinfo_file('RECORD') - record_reader = csv.reader(record, delimiter=',', - lineterminator='\n') - for row in record_reader: - missing = [None for i in range(len(row), 3)] - path, checksum, size = row + missing - if local: - path = path.replace('/', os.sep) - path = os.path.join(sys.prefix, path) - results.append((path, checksum, size)) - record.close() + try: + record_reader = csv.reader(record, delimiter=',', + lineterminator='\n') + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + if local: + path = path.replace('/', os.sep) + path = os.path.join(sys.prefix, path) + results.append((path, checksum, size)) + finally: + record.close() return results def get_resource_path(self, relative_path): resources_file = self.get_distinfo_file('RESOURCES') - resources_reader = csv.reader(resources_file, delimiter=',', - lineterminator='\n') - for relative, destination in resources_reader: - if relative == relative_path: - return destination - resources_file.close() + try: + resources_reader = csv.reader(resources_file, delimiter=',', + lineterminator='\n') + for relative, destination in resources_reader: + if relative == relative_path: + return destination + finally: + resources_file.close() raise KeyError( 'no resource file with relative path %r is installed' % relative_path) @@ -331,8 +336,10 @@ class EggInfoDistribution(object): try: req_path = os.path.join(path, 'EGG-INFO', 'requires.txt') fp = open(req_path, 'r') - requires = fp.read() - fp.close() + try: + requires = fp.read() + finally: + fp.close() except IOError: requires = None else: @@ -353,8 +360,10 @@ class EggInfoDistribution(object): path = os.path.join(path, 'PKG-INFO') try: fp = open(os.path.join(path, 'requires.txt'), 'r') - requires = fp.read() - fp.close() + try: + requires = fp.read() + finally: + fp.close() except IOError: requires = None self.metadata = Metadata(path=path) @@ -417,8 +426,10 @@ class EggInfoDistribution(object): def _md5(path): f = open(path, 'rb') - content = f.read() - f.close() + try: + content = f.read() + finally: + f.close() return md5(content).hexdigest() def _size(path): diff --git a/distutils2/depgraph.py b/distutils2/depgraph.py index da4679d..af8157c 100644 --- a/distutils2/depgraph.py +++ b/distutils2/depgraph.py @@ -234,8 +234,7 @@ def main(): graph = generate_graph(dists) finally: sys.stderr = old - except Exception: - e = sys.exc_info()[1] + except Exception, e: tempout.seek(0) tempout = tempout.read() print 'Could not generate the graph' @@ -259,8 +258,10 @@ def main(): filename = 'depgraph.dot' f = open(filename, 'w') - graph_to_dot(graph, f, True) - f.close() + try: + graph_to_dot(graph, f, True) + finally: + f.close() tempout.seek(0) tempout = tempout.read() print tempout diff --git a/distutils2/dist.py b/distutils2/dist.py index b27c122..051912b 100644 --- a/distutils2/dist.py +++ b/distutils2/dist.py @@ -1,21 +1,21 @@ -"""Class representing the distribution being built/installed/etc.""" +"""Class representing the project being built/installed/etc.""" import os import re -import sys -from distutils2.errors import (PackagingOptionError, PackagingArgError, - PackagingModuleError, PackagingClassError) -from distutils2.fancy_getopt import FancyGetopt -from distutils2.util import strtobool, resolve_name from distutils2 import logger -from distutils2.metadata import Metadata +from distutils2.util import strtobool, resolve_name +from distutils2.errors import (PackagingOptionError, PackagingArgError, + PackagingModuleError, PackagingClassError) from distutils2.config import Config from distutils2.command import get_command_class, STANDARD_COMMANDS +from distutils2.command.cmd import Command +from distutils2.metadata import Metadata +from distutils2.fancy_getopt import FancyGetopt # Regex to define acceptable Packaging 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 +# the same as a Python name -- leading underscores are not allowed. The fact +# that they're very similar is no coincidence: the default naming scheme is # to look for a Python module named after the command. command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$') @@ -33,17 +33,11 @@ def gen_usage(script_name): class Distribution(object): - """The core of the Packaging. Most of the work hiding behind 'setup' - is really done within a Distribution instance, which farms the work out - to the Packaging commands specified on the command line. - - Setup scripts will almost never instantiate Distribution directly, - unless the 'setup()' function is totally inadequate to their needs. - However, it is conceivable that a setup script might wish to subclass - Distribution for some specialized purpose, and then pass the subclass - to 'setup()' as the 'distclass' keyword argument. If so, it is - necessary to respect the expectations that 'setup' has of Distribution. - See the code for 'setup()', in run.py, for details. + """Class used to represent a project and work with it. + + Most of the work hiding behind 'pysetup run' is really done within a + Distribution instance, which farms the work out to the commands + specified on the command line. """ # 'global_options' describes the command-line options that may be @@ -64,8 +58,8 @@ class Distribution(object): common_usage = """\ Common commands: (see '--help-commands' for more) - pysetup run build will build the package underneath 'build/' - pysetup run install will install the package + pysetup run build will build the project underneath 'build/' + pysetup run install will install the project """ # options that are not propagated to the commands @@ -373,7 +367,7 @@ Common commands: (see '--help-commands' for more) commands=self.commands) return - return 1 + return True def _get_toplevel_options(self): """Return the non-display options recognized at the top level. @@ -403,8 +397,8 @@ Common commands: (see '--help-commands' for more) # it takes. try: cmd_class = get_command_class(command) - except PackagingModuleError: - raise PackagingArgError(sys.exc_info()[1]) + except PackagingModuleError, msg: + raise PackagingArgError(msg) # XXX We want to push this in distutils2.command # @@ -501,9 +495,6 @@ Common commands: (see '--help-commands' for more) lists per-command help for every command name or command class in 'commands'. """ - # late import because of mutual dependence between these modules - from distutils2.command.cmd import Command - if global_options: if display_options: options = self._get_toplevel_options() @@ -629,7 +620,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(): " \ + logger.debug("Distribution.get_command_obj(): " "creating %r command object", command) cls = get_command_class(command) @@ -685,8 +676,8 @@ Common commands: (see '--help-commands' for more) raise PackagingOptionError( "error in %s: command %r has no such option %r" % (source, command_name, option)) - except ValueError: - raise PackagingOptionError(sys.exc_info()[1]) + except ValueError, msg: + raise PackagingOptionError(msg) def get_reinitialized_command(self, command, reinit_subcommands=False): """Reinitializes a command to the state it was in when first @@ -707,7 +698,6 @@ Common commands: (see '--help-commands' for more) Returns the reinitialized command object. """ - from distutils2.command.cmd import Command if not isinstance(command, Command): command_name = command command = self.get_command_obj(command_name) @@ -716,6 +706,7 @@ Common commands: (see '--help-commands' for more) if not command.finalized: return command + command.initialize_options() self.have_run[command_name] = 0 command.finalized = False @@ -780,8 +771,8 @@ Common commands: (see '--help-commands' for more) if isinstance(hook, basestring): try: hook_obj = resolve_name(hook) - except ImportError: - raise PackagingModuleError(sys.exc_info()[1]) + except ImportError, e: + raise PackagingModuleError(e) else: hook_obj = hook diff --git a/distutils2/fancy_getopt.py b/distutils2/fancy_getopt.py index 1ff235a..966f843 100644 --- a/distutils2/fancy_getopt.py +++ b/distutils2/fancy_getopt.py @@ -237,8 +237,8 @@ class FancyGetopt(object): try: opts, args = getopt.getopt(args, short_opts, self.long_opts) - except getopt.error: - raise PackagingArgError(sys.exc_info()[1]) + except getopt.error, msg: + raise PackagingArgError(msg) for opt, val in opts: if len(opt) == 2 and opt[0] == '-': # it's a short option @@ -368,7 +368,7 @@ class FancyGetopt(object): if file is None: file = sys.stdout for line in self.generate_help(header): - file.write(line + u"\n") + file.write(line + "\n") def fancy_getopt(options, negative_opt, object, args): diff --git a/distutils2/install.py b/distutils2/install.py index 84716ce..90c5829 100644 --- a/distutils2/install.py +++ b/distutils2/install.py @@ -13,21 +13,22 @@ import errno import shutil import logging import tempfile -from sysconfig import get_config_var, get_path, is_python_build from distutils2 import logger from distutils2.dist import Distribution from distutils2.util import (_is_archive_file, ask, get_install_method, - egginfo_to_distinfo, unpack_archive) + egginfo_to_distinfo, unpack_archive) from distutils2.pypi import wrapper from distutils2.version import get_version_predicate from distutils2.database import get_distributions, get_distribution from distutils2.depgraph import generate_graph from distutils2.errors import (PackagingError, InstallationException, - InstallationConflict, CCompilerError) + InstallationConflict, CCompilerError) from distutils2.pypi.errors import ProjectNotFound, ReleaseNotFound from distutils2 import database +from distutils2._backport.sysconfig import (get_config_var, get_path, + is_python_build) __all__ = ['install_dists', 'install_from_infos', 'get_infos', 'remove', @@ -50,8 +51,7 @@ def _move_files(files, destination): # try to make the paths. try: os.makedirs(os.path.dirname(new)) - except OSError: - e = sys.exc_info()[1] + except OSError, e: if e.errno != errno.EEXIST: raise os.rename(old, new) @@ -88,8 +88,8 @@ def _run_packaging_install(path): dist.run_command('install_dist') name = dist.metadata['Name'] return database.get_distribution(name) is not None - except (IOError, os.error, PackagingError, CCompilerError): - raise ValueError("Failed to install, " + str(sys.exc_info()[1])) + except (IOError, os.error, PackagingError, CCompilerError), msg: + raise ValueError("Failed to install, " + str(msg)) def _install_dist(dist, path): @@ -160,9 +160,9 @@ def _run_install_from_dir(source_dir): try: func(source_dir) return True - except ValueError: + except ValueError, err: # failed to install - logger.info(str(sys.exc_info()[1])) + logger.info(str(err)) return False finally: os.chdir(old_dir) @@ -187,8 +187,8 @@ def install_dists(dists, path, paths=None): try: _install_dist(dist, path) installed_dists.append(dist) - except Exception: - logger.info('Failed: %s', sys.exc_info()[1]) + except Exception, e: + logger.info('Failed: %s', e) # reverting for installed_dist in installed_dists: @@ -396,8 +396,8 @@ def remove(project_name, paths=None, auto_confirm=True): def _move_file(source, target): try: os.rename(source, target) - except OSError: - return sys.exc_info()[1] + except OSError, err: + return err return None success = True @@ -496,9 +496,11 @@ def install(project): # trying to write a file there try: testfile = tempfile.NamedTemporaryFile(suffix=project, - dir=purelib_path) - testfile.write('test') - testfile.close() + dir=purelib_path) + try: + testfile.write('test') + finally: + testfile.close() except OSError: # FIXME this should check the errno, or be removed altogether (race # condition: the directory permissions could be changed between here @@ -523,8 +525,7 @@ def install(project): install_from_infos(install_path, info['install'], info['remove'], info['conflict']) - except InstallationConflict: - e = sys.exc_info()[1] + except InstallationConflict, e: if logger.isEnabledFor(logging.INFO): projects = ('%r %s' % (p.name, p.version) for p in e.args[0]) logger.info('%r conflicts with %s', project, ','.join(projects)) diff --git a/distutils2/manifest.py b/distutils2/manifest.py index 0bf0c72..9a8327b 100644 --- a/distutils2/manifest.py +++ b/distutils2/manifest.py @@ -8,13 +8,12 @@ The Manifest class can be used to: # XXX todo: document + add tests import re import os -import sys import fnmatch from distutils2 import logger from distutils2.util import write_file, convert_path from distutils2.errors import (PackagingTemplateError, - PackagingInternalError) + PackagingInternalError) __all__ = ['Manifest'] @@ -90,8 +89,8 @@ class Manifest(object): continue try: self._process_template_line(line) - except PackagingTemplateError: - logger.warning("%s, %s", path_or_file, sys.exc_info()[1]) + except PackagingTemplateError, msg: + logger.warning("%s, %s", path_or_file, msg) def write(self, path): """Write the file list in 'self.filelist' (presumably as filled in @@ -100,8 +99,10 @@ class Manifest(object): """ if os.path.isfile(path): fp = open(path) - first_line = fp.readline() - fp.close() + try: + first_line = fp.readline() + finally: + fp.close() if first_line != '# file GENERATED by distutils2, do NOT edit\n': logger.info("not writing to manually maintained " @@ -122,9 +123,11 @@ class Manifest(object): """ logger.info("reading manifest file %r", path) manifest = open(path) - for line in manifest.readlines(): - self.append(line) - manifest.close() + try: + for line in manifest.readlines(): + self.append(line) + finally: + manifest.close() def exclude_pattern(self, pattern, anchor=True, prefix=None, is_regex=False): diff --git a/distutils2/markers.py b/distutils2/markers.py index 6ec5079..155f341 100644 --- a/distutils2/markers.py +++ b/distutils2/markers.py @@ -6,6 +6,11 @@ import os from tokenize import generate_tokens, NAME, OP, STRING, ENDMARKER from StringIO import StringIO as BytesIO +try: + python_implementation = platform.python_implementation() +except AttributeError: + # FIXME import from compat + python_implementation = 'CPython' __all__ = ['interpret'] @@ -24,10 +29,7 @@ _OPERATORS = {'==': lambda x, y: x == y, def _operate(operation, x, y): return _OPERATORS[operation](x, y) -try: - python_implementation = platform.python_implementation() -except AttributeError: #<2.6 - assume CPython? - python_implementation = 'CPython' + # restricted set of variables _VARS = {'sys.platform': sys.platform, 'python_version': sys.version[:3], diff --git a/distutils2/metadata.py b/distutils2/metadata.py index 85adeb5..bf02716 100644 --- a/distutils2/metadata.py +++ b/distutils2/metadata.py @@ -3,8 +3,8 @@ Supports all metadata formats (1.0, 1.1, 1.2). """ -import codecs import re +import codecs import logging from StringIO import StringIO @@ -12,10 +12,10 @@ from email import message_from_file from distutils2 import logger from distutils2.markers import interpret from distutils2.version import (is_valid_predicate, is_valid_version, - is_valid_versions) + is_valid_versions) from distutils2.errors import (MetadataMissingError, - MetadataConflictError, - MetadataUnrecognizedVersionError) + MetadataConflictError, + MetadataUnrecognizedVersionError) try: # docutils is installed @@ -311,8 +311,10 @@ class Metadata(object): def read(self, filepath): """Read the metadata values from a file path.""" fp = codecs.open(filepath, 'r', encoding='utf-8') - self.read_file(fp) - fp.close() + try: + self.read_file(fp) + finally: + fp.close() def read_file(self, fileob): """Read the metadata values from a file object.""" @@ -335,8 +337,10 @@ class Metadata(object): def write(self, filepath): """Write the metadata fields to filepath.""" fp = codecs.open(filepath, 'w', encoding='utf-8') - self.write_file(fp) - fp.close() + try: + self.write_file(fp) + finally: + fp.close() def write_file(self, fileobject): """Write the PKG-INFO format data to a file object.""" diff --git a/distutils2/pypi/dist.py b/distutils2/pypi/dist.py index d284a66..aecf6dd 100644 --- a/distutils2/pypi/dist.py +++ b/distutils2/pypi/dist.py @@ -10,7 +10,7 @@ distribution objects contain download-related information. import re try: import hashlib -except ImportError: #<2.5 +except ImportError: from distutils2._backport import hashlib import tempfile import urllib @@ -328,9 +328,11 @@ class DistInfo(IndexReference): expected_hashval = self.url['hashval'] if None not in (expected_hashval, hashname): f = open(filename, 'rb') - hashval = hashlib.new(hashname) - hashval.update(f.read()) - f.close() + try: + hashval = hashlib.new(hashname) + hashval.update(f.read()) + finally: + f.close() if hashval.hexdigest() != expected_hashval: raise HashDoesNotMatch("got %s instead of %s" diff --git a/distutils2/pypi/simple.py b/distutils2/pypi/simple.py index a08f7d6..dc0823f 100644 --- a/distutils2/pypi/simple.py +++ b/distutils2/pypi/simple.py @@ -161,16 +161,18 @@ class Crawler(BaseClient): Return a list of names. """ index = self._open_url(self.index_url) - if '*' in name: - name.replace('*', '.*') - else: - name = "%s%s%s" % ('*.?', name, '*.?') - name = name.replace('*', '[^<]*') # avoid matching end tag - projectname = re.compile('<a[^>]*>(%s)</a>' % name, re.I) - matching_projects = [] + try: + if '*' in name: + name.replace('*', '.*') + else: + name = "%s%s%s" % ('*.?', name, '*.?') + name = name.replace('*', '[^<]*') # avoid matching end tag + projectname = re.compile('<a[^>]*>(%s)</a>' % name, re.I) + matching_projects = [] - index_content = index.read() - index.close() + index_content = index.read() + finally: + index.close() # FIXME should use bytes I/O and regexes instead of decoding index_content = index_content.decode() @@ -236,7 +238,9 @@ class Crawler(BaseClient): self._mirrors_used.add(self.index_url) index_url = self._mirrors.pop() # XXX use urlparse for a real check of missing scheme part - if not index_url.startswith(("http://", "https://", "file://")): + if not (index_url.startswith("http://") or + index_url.startswith("https://") or + index_url.startswith("file://")): index_url = "http://%s" % index_url if not index_url.endswith("/simple"): @@ -327,8 +331,7 @@ class Crawler(BaseClient): try: infos = get_infos_from_url(link, project_name, is_external=self.index_url not in url) - except CantParseArchiveName: - e = sys.exc_info()[1] + except CantParseArchiveName, e: if self.verbose: logger.warning( "version has not been parsed: %s", e) @@ -410,7 +413,7 @@ class Crawler(BaseClient): # authentication stuff if scheme in ('http', 'https'): - auth, host = urlparse.splituser(netloc) + auth, host = urllib2.splituser(netloc) else: auth = None @@ -432,21 +435,17 @@ class Crawler(BaseClient): request.add_header('User-Agent', USER_AGENT) try: fp = urllib2.urlopen(request) - except (ValueError, httplib.InvalidURL): - v = sys.exc_info()[1] + except (ValueError, httplib.InvalidURL), v: msg = ' '.join([str(arg) for arg in v.args]) raise PackagingPyPIError('%s %s' % (url, msg)) - except urllib2.HTTPError: - return sys.exc_info()[1] - except urllib2.URLError: - v = sys.exc_info()[1] + except urllib2.HTTPError, v: + return v + except urllib2.URLError, v: raise DownloadError("Download error for %s: %s" % (url, v.reason)) - except httplib.BadStatusLine: - v = sys.exc_info()[1] + except httplib.BadStatusLine, v: raise DownloadError('%s returned a bad status line. ' 'The server might be down, %s' % (url, v.line)) - except httplib.HTTPException: - v = sys.exc_info()[1] + except httplib.HTTPException, v: raise DownloadError("Download error for %s: %s" % (url, v)) except socket.timeout: raise DownloadError("The server timeouted") diff --git a/distutils2/pypi/wrapper.py b/distutils2/pypi/wrapper.py index fc63692..2179aba 100644 --- a/distutils2/pypi/wrapper.py +++ b/distutils2/pypi/wrapper.py @@ -31,8 +31,8 @@ def switch_index_if_fails(func, wrapper): try: response = method(*args, **kwargs) retry = False - except Exception: - exception = sys.exc_info()[1] + except Exception, e: + exception = e if not retry: break if retry and exception: diff --git a/distutils2/pypi/xmlrpc.py b/distutils2/pypi/xmlrpc.py index 47a3b32..7b5b065 100644 --- a/distutils2/pypi/xmlrpc.py +++ b/distutils2/pypi/xmlrpc.py @@ -13,7 +13,7 @@ from distutils2.errors import IrrationalVersionError from distutils2.version import get_version_predicate from distutils2.pypi.base import BaseClient from distutils2.pypi.errors import (ProjectNotFound, InvalidSearchField, - ReleaseNotFound) + ReleaseNotFound) from distutils2.pypi.dist import ReleaseInfo __all__ = ['Client', 'DEFAULT_XMLRPC_INDEX_URL'] @@ -171,8 +171,7 @@ class Client(BaseClient): project.add_release(release=ReleaseInfo(p['name'], p['version'], metadata={'summary': p['summary']}, index=self._index)) - except IrrationalVersionError: - e = sys.exc_info()[1] + except IrrationalVersionError, e: logger.warning("Irrational version error found: %s", e) return [self._projects[p['name'].lower()] for p in projects] diff --git a/distutils2/run.py b/distutils2/run.py index 9f97576..75b78f2 100644 --- a/distutils2/run.py +++ b/distutils2/run.py @@ -15,8 +15,8 @@ from distutils2.database import get_distribution, get_distributions from distutils2.depgraph import generate_graph from distutils2.fancy_getopt import FancyGetopt from distutils2.errors import (PackagingArgError, PackagingError, - PackagingModuleError, PackagingClassError, - CCompilerError) + PackagingModuleError, PackagingClassError, + CCompilerError) command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$') @@ -473,8 +473,8 @@ class Dispatcher(object): # it takes. try: cmd_class = get_command_class(command) - except PackagingModuleError: - raise PackagingArgError(sys.exc_info()[1]) + except PackagingModuleError, msg: + raise PackagingArgError(msg) # XXX We want to push this in distutils2.command # @@ -674,22 +674,21 @@ def main(args=None): old_level = logger.level old_handlers = list(logger.handlers) try: - dispatcher = Dispatcher(args) - if dispatcher.action is None: - return - return dispatcher() - except KeyboardInterrupt: - logger.info('interrupted') - return 1 - except (IOError, os.error, PackagingError, CCompilerError): - logger.exception(sys.exc_info()[1]) - return 1 - except: + try: + dispatcher = Dispatcher(args) + if dispatcher.action is None: + return + return dispatcher() + except KeyboardInterrupt: + logger.info('interrupted') + return 1 + except (IOError, os.error, PackagingError, CCompilerError), exc: + logger.exception(exc) + return 1 + finally: logger.setLevel(old_level) logger.handlers[:] = old_handlers - raise - logger.setLevel(old_level) - logger.handlers[:] = old_handlers + if __name__ == '__main__': sys.exit(main()) diff --git a/distutils2/tests/__main__.py b/distutils2/tests/__main__.py index b01cbd1..bdcc29d 100644 --- a/distutils2/tests/__main__.py +++ b/distutils2/tests/__main__.py @@ -4,8 +4,8 @@ import os import sys -import unittest2 -from .support import run_unittest, reap_children, reap_threads +from distutils2.tests import unittest +from distutils2.tests.support import reap_children, reap_threads, run_unittest @reap_threads @@ -13,7 +13,9 @@ def test_main(): try: start_dir = os.path.dirname(__file__) top_dir = os.path.dirname(os.path.dirname(start_dir)) - test_loader = unittest2.TestLoader() + test_loader = unittest.TestLoader() + # XXX find out how to use unittest.main, to get command-line options + # (failfast, catch, etc.) run_unittest(test_loader.discover(start_dir, top_level_dir=top_dir)) finally: reap_children() diff --git a/distutils2/tests/pypi_server.py b/distutils2/tests/pypi_server.py index 4d62986..3d25725 100644 --- a/distutils2/tests/pypi_server.py +++ b/distutils2/tests/pypi_server.py @@ -30,19 +30,21 @@ implementations (static HTTP and XMLRPC over HTTP). """ import os -import queue +import Queue import select import threading -import socketserver +import SocketServer +from BaseHTTPServer import HTTPServer +from SimpleHTTPServer import SimpleHTTPRequestHandler +from SimpleXMLRPCServer import SimpleXMLRPCServer + +from distutils2.tests import unittest + try: from functools import wraps except ImportError: from distutils2._backport.functools import wraps -from http.server import HTTPServer, SimpleHTTPRequestHandler -from xmlrpc.server import SimpleXMLRPCServer - -from distutils2.tests import unittest PYPI_DEFAULT_STATIC_PATH = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'pypiserver') @@ -117,7 +119,7 @@ class PyPIServer(threading.Thread): self.server = HTTPServer(('127.0.0.1', 0), PyPIRequestHandler) self.server.RequestHandlerClass.pypi_server = self - self.request_queue = queue.Queue() + self.request_queue = Queue.Queue() self._requests = [] self.default_response_status = 404 self.default_response_headers = [('Content-type', 'text/plain')] @@ -154,7 +156,7 @@ class PyPIServer(threading.Thread): def stop(self): """self shutdown is not supported for python < 2.6""" self._run = False - if self.is_alive(): + if self.isAlive(): self.join() self.server.server_close() @@ -171,7 +173,7 @@ class PyPIServer(threading.Thread): while True: try: self._requests.append(self.request_queue.get_nowait()) - except queue.Empty: + except Queue.Empty: break return self._requests @@ -275,7 +277,7 @@ class PyPIRequestHandler(SimpleHTTPRequestHandler): class PyPIXMLRPCServer(SimpleXMLRPCServer): def server_bind(self): """Override server_bind to store the server name.""" - socketserver.TCPServer.server_bind(self) + SocketServer.TCPServer.server_bind(self) host, port = self.socket.getsockname()[:2] self.server_port = port diff --git a/distutils2/tests/test_command_build.py b/distutils2/tests/test_command_build.py index e70b7b4..08bef58 100644 --- a/distutils2/tests/test_command_build.py +++ b/distutils2/tests/test_command_build.py @@ -3,7 +3,7 @@ import os import sys from distutils2.command.build import build -from sysconfig import get_platform +from distutils2._backport.sysconfig import get_platform from distutils2.tests import unittest, support diff --git a/distutils2/tests/test_command_build_ext.py b/distutils2/tests/test_command_build_ext.py index b0d8bc8..d73fe6c 100644 --- a/distutils2/tests/test_command_build_ext.py +++ b/distutils2/tests/test_command_build_ext.py @@ -5,6 +5,7 @@ import shutil import textwrap from StringIO import StringIO from distutils2._backport import sysconfig +from distutils2._backport.sysconfig import _CONFIG_VARS from distutils2.dist import Distribution from distutils2.errors import (UnknownFileError, CompileError, PackagingPlatformError) @@ -36,9 +37,10 @@ class BuildExtTestCase(support.TempdirManager, filename = _get_source_filename() if os.path.exists(filename): shutil.copy(filename, self.tmp_dir) - self.old_user_base = site.USER_BASE - site.USER_BASE = self.mkdtemp() - build_ext.USER_BASE = site.USER_BASE + if sys.version > "2.6": + self.old_user_base = site.USER_BASE + site.USER_BASE = self.mkdtemp() + build_ext.USER_BASE = site.USER_BASE def tearDown(self): # Get everything back to normal @@ -122,7 +124,6 @@ class BuildExtTestCase(support.TempdirManager, old = sys.platform sys.platform = 'sunos' # fooling finalize_options - from sysconfig import _CONFIG_VARS old_var = _CONFIG_VARS.get('Py_ENABLE_SHARED') _CONFIG_VARS['Py_ENABLE_SHARED'] = 1 diff --git a/distutils2/tests/test_command_upload_docs.py b/distutils2/tests/test_command_upload_docs.py index 65646e3..c023cd3 100644 --- a/distutils2/tests/test_command_upload_docs.py +++ b/distutils2/tests/test_command_upload_docs.py @@ -18,7 +18,7 @@ try: from distutils2.tests.pypi_server import PyPIServerTestCase except ImportError: threading = None - PyPIServerTestCase = object + PyPIServerTestCase = unittest.TestCase PYPIRC = """\ @@ -32,8 +32,7 @@ password = long_island """ -class UploadDocsTestCase(unittest.TestCase, - support.TempdirManager, +class UploadDocsTestCase(support.TempdirManager, support.EnvironRestorer, support.LoggingCatcher, PyPIServerTestCase): diff --git a/distutils2/tests/test_install.py b/distutils2/tests/test_install.py index 06a1181..f6b91f3 100644 --- a/distutils2/tests/test_install.py +++ b/distutils2/tests/test_install.py @@ -1,7 +1,6 @@ """Tests for the distutils2.install module.""" import os import logging -from sysconfig import is_python_build from tempfile import mkstemp from distutils2 import install @@ -9,6 +8,8 @@ from distutils2.pypi.xmlrpc import Client from distutils2.metadata import Metadata from distutils2.tests.support import (LoggingCatcher, TempdirManager, unittest, fake_dec) +from distutils2._backport.sysconfig import is_python_build + try: import threading from distutils2.tests.pypi_server import use_xmlrpc_server diff --git a/distutils2/tests/test_mixin2to3.py b/distutils2/tests/test_mixin2to3.py index 8cfdf7a..71bd74e 100644 --- a/distutils2/tests/test_mixin2to3.py +++ b/distutils2/tests/test_mixin2to3.py @@ -1,3 +1,4 @@ +import sys import textwrap from distutils2.tests import unittest, support @@ -8,8 +9,7 @@ class Mixin2to3TestCase(support.TempdirManager, support.LoggingCatcher, unittest.TestCase): - #@unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') - @unittest.skipIf(True, 'Not needed for backport') + @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') def test_convert_code_only(self): # used to check if code gets converted properly. code = "print 'test'" @@ -28,8 +28,7 @@ class Mixin2to3TestCase(support.TempdirManager, self.assertEqual(expected, converted) - #@unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') - @unittest.skipIf(True, 'Not needed for backport') + @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') def test_doctests_only(self): # used to check if doctests gets converted properly. doctest = textwrap.dedent('''\ @@ -62,8 +61,7 @@ class Mixin2to3TestCase(support.TempdirManager, self.assertEqual(expected, converted) - #@unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') - @unittest.skipIf(True, 'Not needed for backport') + @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') def test_additional_fixers(self): # used to check if use_2to3_fixers works code = 'type(x) is not T' diff --git a/distutils2/tests/test_pypi_simple.py b/distutils2/tests/test_pypi_simple.py index dde0b3a..4607a40 100644 --- a/distutils2/tests/test_pypi_simple.py +++ b/distutils2/tests/test_pypi_simple.py @@ -12,9 +12,9 @@ from distutils2.tests.support import (TempdirManager, LoggingCatcher, fake_dec) try: - import _thread + import thread as _thread from distutils2.tests.pypi_server import (use_pypi_server, PyPIServer, - PYPI_DEFAULT_STATIC_PATH) + PYPI_DEFAULT_STATIC_PATH) except ImportError: _thread = None use_pypi_server = fake_dec diff --git a/distutils2/util.py b/distutils2/util.py index 76caee4..38f6e7d 100644 --- a/distutils2/util.py +++ b/distutils2/util.py @@ -180,8 +180,8 @@ def subst_vars(s, local_vars): try: return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s) - except KeyError: - raise ValueError("invalid variable '$%s'" % sys.exc_info()[1]) + except KeyError, e: + raise ValueError("invalid variable '$%s'" % e) # Needed by 'split_quoted()' @@ -334,7 +334,7 @@ def byte_compile(py_files, optimize=0, force=False, prefix=None, """ # nothing is done if sys.dont_write_bytecode is True # FIXME this should not raise an error - if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode: + if getattr(sys, 'dont_write_bytecode', False): raise PackagingByteCompileError('byte-compiling is disabled.') # First, if the caller didn't force us into direct or indirect mode, @@ -354,7 +354,7 @@ def byte_compile(py_files, optimize=0, force=False, prefix=None, # run it with the appropriate flags. if not direct: from tempfile import mkstemp - # XXX script_fd may leak, use something better than mkstemp + # XXX use something better than mkstemp script_fd, script_name = mkstemp(".py") os.close(script_fd) script_fd = None @@ -365,33 +365,36 @@ def byte_compile(py_files, optimize=0, force=False, prefix=None, else: script = codecs.open(script_name, "w", encoding='utf-8') - script.write("""\ + try: + script.write("""\ from distutils2.util import byte_compile files = [ """) - # XXX would be nice to write absolute filenames, just for - # safety's sake (script should be more robust in the face of - # chdir'ing before running it). But this requires abspath'ing - # 'prefix' as well, and that breaks the hack in build_lib's - # 'byte_compile()' method that carefully tacks on a trailing - # slash (os.sep really) to make sure the prefix here is "just - # right". This whole prefix business is rather delicate -- the - # problem is that it's really a directory, but I'm treating it - # as a dumb string, so trailing slashes and so forth matter. - - #py_files = map(os.path.abspath, py_files) - #if prefix: - # prefix = os.path.abspath(prefix) - - script.write(",\n".join(map(repr, py_files)) + "]\n") - script.write(""" + # XXX would be nice to write absolute filenames, just for + # safety's sake (script should be more robust in the face of + # chdir'ing before running it). But this requires abspath'ing + # 'prefix' as well, and that breaks the hack in build_lib's + # 'byte_compile()' method that carefully tacks on a trailing + # slash (os.sep really) to make sure the prefix here is "just + # right". This whole prefix business is rather delicate -- the + # problem is that it's really a directory, but I'm treating it + # as a dumb string, so trailing slashes and so forth matter. + + #py_files = map(os.path.abspath, py_files) + #if prefix: + # prefix = os.path.abspath(prefix) + + script.write(",\n".join(map(repr, py_files)) + "]\n") + script.write(""" byte_compile(files, optimize=%r, force=%r, prefix=%r, base_dir=%r, verbose=%r, dry_run=False, direct=True) """ % (optimize, force, prefix, base_dir, verbose)) - script.close() + finally: + script.close() + cmd = [sys.executable, script_name] if optimize == 1: cmd.insert(1, "-O") @@ -553,9 +556,11 @@ def write_file(filename, contents): *contents* is a sequence of strings without line terminators. """ f = open(filename, "w") - for line in contents: - f.write(line + "\n") - f.close() + try: + for line in contents: + f.write(line + "\n") + finally: + f.close() def _is_package(path): return os.path.isdir(path) and os.path.isfile( @@ -657,8 +662,8 @@ def resolve_name(name): for part in parts[1:]: try: ret = getattr(ret, part) - except AttributeError: - raise ImportError(sys.exc_info()[1]) + except AttributeError, exc: + raise ImportError(exc) return ret @@ -775,6 +780,7 @@ if sys.platform == 'darwin': _cfg_target = None _cfg_target_split = None + def spawn(cmd, search_path=True, verbose=0, dry_run=False, env=None): """Run another program specified as a command list 'cmd' in a new process. @@ -872,11 +878,12 @@ def generate_pypirc(username, password): """Create a default .pypirc file.""" rc = get_pypirc_path() f = open(rc, 'w') - f.write(DEFAULT_PYPIRC % (username, password)) - f.close() - try: - os.chmod(rc, 00600) + f.write(DEFAULT_PYPIRC % (username, password)) + finally: + f.close() + try: + os.chmod(rc, 0600) except OSError: # should do something better here pass @@ -1084,8 +1091,10 @@ def cfg_to_args(path='setup.cfg'): raise PackagingFileError("file '%s' does not exist" % os.path.abspath(path)) f = codecs.open(path, encoding='utf-8') - config.readfp(f) - f.close() + try: + config.readfp(f) + finally: + f.close() kwargs = {} for arg in D1_D2_SETUP_ARGS: @@ -1108,8 +1117,10 @@ def cfg_to_args(path='setup.cfg'): in_cfg_value = [] for filename in filenames: fp = open(filename) - in_cfg_value.append(fp.read()) - fp.close() + try: + in_cfg_value.append(fp.read()) + finally: + fp.close() in_cfg_value = '\n\n'.join(in_cfg_value) else: continue @@ -1147,8 +1158,10 @@ def generate_setup_py(): raise PackagingFileError("a setup.py file already exists") fp = codecs.open("setup.py", "w", encoding='utf-8') - fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)}) - fp.close() + try: + fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)}) + finally: + fp.close() # Taken from the pip project @@ -1168,26 +1181,29 @@ def ask(message, options): def _parse_record_file(record_file): distinfo, extra_metadata, installed = ({}, [], []) rfile = open(record_file, 'r') - for path in rfile: - path = path.strip() - if path.endswith('egg-info') and os.path.isfile(path): - distinfo_dir = path.replace('egg-info', 'dist-info') - metadata = path - egginfo = path - elif path.endswith('egg-info') and os.path.isdir(path): - distinfo_dir = path.replace('egg-info', 'dist-info') - egginfo = path - for metadata_file in os.listdir(path): - metadata_fpath = os.path.join(path, metadata_file) - if metadata_file == 'PKG-INFO': - metadata = metadata_fpath - else: - extra_metadata.append(metadata_fpath) - elif 'egg-info' in path and os.path.isfile(path): - # skip extra metadata files - continue - else: - installed.append(path) + try: + for path in rfile: + path = path.strip() + if path.endswith('egg-info') and os.path.isfile(path): + distinfo_dir = path.replace('egg-info', 'dist-info') + metadata = path + egginfo = path + elif path.endswith('egg-info') and os.path.isdir(path): + distinfo_dir = path.replace('egg-info', 'dist-info') + egginfo = path + for metadata_file in os.listdir(path): + metadata_fpath = os.path.join(path, metadata_file) + if metadata_file == 'PKG-INFO': + metadata = metadata_fpath + else: + extra_metadata.append(metadata_fpath) + elif 'egg-info' in path and os.path.isfile(path): + # skip extra metadata files + continue + else: + installed.append(path) + finally: + rfile.close() distinfo['egginfo'] = egginfo distinfo['metadata'] = metadata @@ -1204,25 +1220,29 @@ def _parse_record_file(record_file): def _write_record_file(record_path, installed_files): f = codecs.open(record_path, 'w', encoding='utf-8') - writer = csv.writer(f, delimiter=',', lineterminator=os.linesep, - quotechar='"') + try: + writer = csv.writer(f, delimiter=',', lineterminator=os.linesep, + quotechar='"') - for fpath in installed_files: - if fpath.endswith('.pyc') or fpath.endswith('.pyo'): - # do not put size and md5 hash, as in PEP-376 - writer.writerow((fpath, '', '')) - else: - hash = hashlib.md5() - fp = open(fpath, 'rb') - hash.update(fp.read()) - fp.close() - md5sum = hash.hexdigest() - size = os.path.getsize(fpath) - writer.writerow((fpath, md5sum, size)) + for fpath in installed_files: + if fpath.endswith('.pyc') or fpath.endswith('.pyo'): + # do not put size and md5 hash, as in PEP-376 + writer.writerow((fpath, '', '')) + else: + hash = hashlib.md5() + fp = open(fpath, 'rb') + try: + hash.update(fp.read()) + finally: + fp.close() + md5sum = hash.hexdigest() + size = os.path.getsize(fpath) + writer.writerow((fpath, md5sum, size)) - # add the RECORD file itself - writer.writerow((record_path, '', '')) - f.close() + # add the RECORD file itself + writer.writerow((record_path, '', '')) + finally: + f.close() return record_path @@ -1258,8 +1278,10 @@ def egginfo_to_distinfo(record_file, installer=_DEFAULT_INSTALLER, installer_path = distinfo['installer_path'] logger.info('creating %s', installer_path) f = open(installer_path, 'w') - f.write(installer) - f.close() + try: + f.write(installer) + finally: + f.close() if requested: requested_path = distinfo['requested_path'] @@ -1301,13 +1323,15 @@ def _has_distutils_text(setup_py): def _has_text(setup_py, installer): installer_pattern = re.compile('import %s|from %s' % ( - installer[0], installer[1])) + installer[0], installer[0])) setup = codecs.open(setup_py, 'r', encoding='utf-8') - for line in setup: - if re.search(installer_pattern, line): - logger.debug("Found %s text in setup.py.", installer) - return True - setup.close() + try: + for line in setup: + if re.search(installer_pattern, line): + logger.debug("Found %s text in setup.py.", installer) + return True + finally: + setup.close() logger.debug("No %s text found in setup.py.", installer) return False @@ -1315,8 +1339,10 @@ def _has_text(setup_py, installer): def _has_required_metadata(setup_cfg): config = RawConfigParser() f = codecs.open(setup_cfg, 'r', encoding='utf8') - config.readfp(f) - f.close() + try: + config.readfp(f) + finally: + f.close() return (config.has_section('metadata') and 'name' in config.options('metadata') and 'version' in config.options('metadata')) @@ -1377,7 +1403,7 @@ def is_distutils(path): _has_distutils_text(setup_py)) -def is_distutils2(path): +def is_packaging(path): """Check if the project is based on distutils2 :param path: path to source directory containing a setup.cfg file. @@ -1398,7 +1424,7 @@ def get_install_method(path): Returns a string representing the best install method to use. """ - if is_distutils2(path): + if is_packaging(path): return "distutils2" elif is_setuptools(path): return "setuptools" @@ -1419,8 +1445,8 @@ def copy_tree(src, dst, preserve_mode=True, preserve_times=True, "cannot copy tree '%s': not a directory" % src) try: names = os.listdir(src) - except os.error: - errstr = sys.exc_info()[1][1] + except os.error, e: + errstr = e[1] if dry_run: names = [] else: @@ -1465,7 +1491,7 @@ _path_created = set() # 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=00777, verbose=True, dry_run=False): +def _mkpath(name, mode=0777, verbose=True, dry_run=False): # Detect a common bug -- name is None if not isinstance(name, basestring): raise PackagingInternalError( @@ -1506,8 +1532,7 @@ def _mkpath(name, mode=00777, verbose=True, dry_run=False): if not dry_run: try: os.mkdir(head, mode) - except OSError: - exc = sys.exc_info()[1] + except OSError, exc: if not (exc.errno == errno.EEXIST and os.path.isdir(head)): raise PackagingFileError( "could not create '%s': %s" % (head, exc.args[-1])) diff --git a/distutils2/version.py b/distutils2/version.py index c754b7d..9e4a7dc 100644 --- a/distutils2/version.py +++ b/distutils2/version.py @@ -182,7 +182,6 @@ class NormalizedVersion(object): return "%s('%s')" % (self.__class__.__name__, self) def _cannot_compare(self, other): - import pdb; pdb.set_trace() raise TypeError("cannot compare %s and %s" % (type(self).__name__, type(other).__name__)) |
