[Distutils] patches: ez_setup.py: don't import setuptools into your current address space in order to learn its version number
zooko
zooko at zooko.com
Sat Sep 29 00:43:36 CEST 2007
On Sep 27, 2007, at 10:51 AM, Phillip J. Eby wrote:
> It won't work correctly. First, pkg_resources is part of
> setuptools, so if you install a new version of setuptools, you have
> to reload() it too.
>
> Second, it's not *safe* to reload it, if it or setuptools were
> already imported at the time the function is called. That's
> because easy_install runs the setup.py of a package it's building
> from source. So if you use easy_install to install a package that
> needs a newer version, reloading pkg_resources or setuptools (and
> note that setuptools is a package with lots of submodules!) will
> break the host easy_install process.
Okay. Attached is a patch that doesn't import pkg_resources and
doesn't reload anything. I haven't yet tested it -- I am submitting
it only to inform the discussion and get any early feedback from you
on whether the very idea is sound.
Regards,
Zooko
diff -rN -u old-up/setuptools-0.6c7/ez_setup.py new-up/
setuptools-0.6c7/ez_setup.py
--- old-up/setuptools-0.6c7/ez_setup.py 2007-09-28 16:41:24.000000000
-0600
+++ new-up/setuptools-0.6c7/ez_setup.py 2007-09-28 16:41:25.000000000
-0600
@@ -1,4 +1,4 @@
-#!python
+#!/usr/bin/env python
"""Bootstrap setuptools installation
If you want to use setuptools in your package's setup.py, just
include this
@@ -13,7 +13,7 @@
This file can also be run as a script to install or upgrade setuptools.
"""
-import sys
+import os, re, subprocess, sys
DEFAULT_VERSION = "0.6c7"
DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/"
% sys.version[:3]
@@ -44,8 +44,6 @@
'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
}
-import sys, os
-
def _validate_md5(egg_name, data):
if egg_name in md5_data:
from md5 import md5
@@ -58,6 +56,42 @@
sys.exit(2)
return data
+# The following code to parse versions is copied from
pkg_resources.py so that
+# we can parse versions without importing that module.
+component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
+replace = {'pre':'c',
'preview':'c','-':'final-','rc':'c','dev':'@'}.get
+
+def _parse_version_parts(s):
+ for part in component_re.split(s):
+ part = replace(part,part)
+ if not part or part=='.':
+ continue
+ if part[:1] in '0123456789':
+ yield part.zfill(8) # pad for numeric comparison
+ else:
+ yield '*'+part
+
+ yield '*final' # ensure that alpha/beta/candidate are before final
+
+def parse_version(s):
+ parts = []
+ for part in _parse_version_parts(s.lower()):
+ if part.startswith('*'):
+ if part<'*final': # remove '-' before a prerelease tag
+ while parts and parts[-1]=='*final-': parts.pop()
+ # remove trailing zeros from each series of numeric parts
+ while parts and parts[-1]=='00000000':
+ parts.pop()
+ parts.append(part)
+ return tuple(parts)
+
+def setuptools_is_new_enough(required_version):
+ """Return True if setuptools is already installed and has a version
+ number >= required_version."""
+ sub = subprocess.Popen([sys.executable, "-c", "import
setuptools;print setuptools.__version__"], stdout=subprocess.PIPE)
+ verstr = sub.stdout.read().strip()
+ ver = parse_version(verstr)
+ return ver and ver >= parse_version(required_version)
def use_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir,
@@ -74,32 +108,11 @@
this routine will print a message to ``sys.stderr`` and raise
SystemExit in
an attempt to abort the calling script.
"""
- try:
- import setuptools
- if setuptools.__version__ == '0.0.1':
- print >>sys.stderr, (
- "You have an obsolete version of setuptools installed.
Please\n"
- "remove it from your system entirely before rerunning
this script."
- )
- sys.exit(2)
- except ImportError:
+ if not setuptools_is_new_enough(version):
egg = download_setuptools(version, download_base, to_dir,
download_delay)
sys.path.insert(0, egg)
import setuptools; setuptools.bootstrap_install_from = egg
- import pkg_resources
- try:
- pkg_resources.require("setuptools>="+version)
-
- except pkg_resources.VersionConflict, e:
- # XXX could we install in a subprocess here?
- print >>sys.stderr, (
- "The required version of setuptools (>=%s) is not
available, and\n"
- "can't be installed while this script is running. Please
install\n"
- " a more recent version first.\n\n(Currently using %r)"
- ) % (version, e.args[0])
- sys.exit(2)
-
def download_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir,
delay = 15
@@ -150,9 +163,14 @@
def main(argv, version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
- try:
- import setuptools
- except ImportError:
+ if setuptools_is_new_enough(version):
+ if argv:
+ from setuptools.command.easy_install import main
+ main(argv)
+ else:
+ print "Setuptools version",version,"or greater has been
installed."
+ print '(Run "ez_setup.py -U setuptools" to reinstall or
upgrade.)'
+ else:
egg = None
try:
egg = download_setuptools(version, delay=0)
@@ -162,31 +180,6 @@
finally:
if egg and os.path.exists(egg):
os.unlink(egg)
- else:
- if setuptools.__version__ == '0.0.1':
- # tell the user to uninstall obsolete version
- use_setuptools(version)
-
- req = "setuptools>="+version
- import pkg_resources
- try:
- pkg_resources.require(req)
- except pkg_resources.VersionConflict:
- try:
- from setuptools.command.easy_install import main
- except ImportError:
- from easy_install import main
- main(list(argv)+[download_setuptools(delay=0)])
- sys.exit(0) # try to force an exit
- else:
- if argv:
- from setuptools.command.easy_install import main
- main(argv)
- else:
- print "Setuptools version",version,"or greater has been
installed."
- print '(Run "ez_setup.py -U setuptools" to reinstall or
upgrade.)'
-
-
def update_md5(filenames):
"""Update our built-in md5 registry"""
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: ez_setup-subp.patch.txt
Url: http://mail.python.org/pipermail/distutils-sig/attachments/20070928/6555aa54/attachment.txt
More information about the Distutils-SIG
mailing list