Merge lp:~sidnei/lazr-js/newer-buildout into lp:lazr-js

Proposed by Sidnei da Silva
Status: Merged
Approved by: Gary Poster
Approved revision: 173
Merged at revision: not available
Proposed branch: lp:~sidnei/lazr-js/newer-buildout
Merge into: lp:lazr-js
Diff against target: 1085 lines (+610/-384)
6 files modified
Makefile (+3/-2)
bootstrap.py (+126/-103)
distribute_setup.py (+477/-0)
ez_setup.py (+0/-275)
setup.py (+2/-2)
versions.cfg (+2/-2)
To merge this branch: bzr merge lp:~sidnei/lazr-js/newer-buildout
Reviewer Review Type Date Requested Status
Gary Poster (community) Approve
Graham Binns (community) Abstain
Review via email: mp+21417@code.launchpad.net

Description of the change

- Update zc.buildout to 1.4.3
- Replace setuptools by distribute, since the former doesn't work for
  me anymore on Lucid.

To post a comment you must log in.
lp:~sidnei/lazr-js/newer-buildout updated
172. By Sidnei da Silva

- Revert unwanted change

Revision history for this message
Graham Binns (gmb) wrote :

I'm not happy reviewing this branch as I don't have the necessary knowledge. I'm asking Gary to either review this or find someone else who has the necessary contextual knowledge to do so.

review: Abstain
Revision history for this message
Gary Poster (gary) wrote :
Download full text (15.1 KiB)

Hi Sidnei. Looks good, but there's a practical problem in that it doesn't work for me on Karmic. Interesting that setuptools doesn't work for you on Lucid. More below.

The Makefile fails for me on Karmic like this:

bzr checkout lp:lazr-source-dependencies download-cache
mkdir eggs
if test ! -h src-py/lazrjs ; then \
 ln -s ../src-js/lazrjs src-py/lazrjs;\
 fi
python -S bootstrap.py \
  --distribute_setup-source=distribute_setup.py \
  --download-base=download-cache/dist --eggs=eggs
Downloading file:///home/gary/launchpad/lp-sourcedeps/newer-buildout/download-cache/dist/distribute-0.6.10.tar.gz
Extracting in /tmp/tmpTmz0tV
Now working in /tmp/tmpTmz0tV/distribute-0.6.10
Building a Distribute egg in /home/gary/launchpad/lp-sourcedeps/newer-buildout/eggs
/home/gary/launchpad/lp-sourcedeps/newer-buildout/eggs/distribute-0.6.10-py2.6.egg
Traceback (most recent call last):
  File "bootstrap.py", line 147, in <module>
    PYTHONPATH=ws.find(pkg_resources.Requirement.parse('distribute')).location)
AttributeError: 'NoneType' object has no attribute 'location'
make: *** [bin/buildout] Error 1

This is a general problem with buildout and a system Python. I see we are using a hacked version of my old bootstrap.py. I've fixed this particular problem in my buildout branch for Jim. However, when I copy over my new bootstrap.py, I get a new error.

gary@garybuntu:~/launchpad/lp-sourcedeps/newer-buildout$ make
if test ! -h src-py/lazrjs ; then \
 ln -s ../src-js/lazrjs src-py/lazrjs;\
 fi
python -S bootstrap.py \
  --distribute \
                --setup-source=distribute_setup.py \
  --download-base=download-cache/dist --eggs=eggs
Downloading file:///home/gary/launchpad/lp-sourcedeps/newer-buildout/download-cache/dist/distribute-0.6.10.tar.gz
Extracting in /tmp/tmpBtweFh
Now working in /tmp/tmpBtweFh/distribute-0.6.10
Building a Distribute egg in /home/gary/launchpad/lp-sourcedeps/newer-buildout/eggs
/home/gary/launchpad/lp-sourcedeps/newer-buildout/eggs/distribute-0.6.10-py2.6.egg
/home/gary/launchpad/lp-sourcedeps/newer-buildout/bootstrap.py:129: UserWarning: Module pkg_resources was already imported from /usr/lib/python2.6/dist-packages/pkg_resources.pyc, but /home/gary/launchpad/lp-sourcedeps/newer-buildout/eggs/distribute-0.6.10-py2.6.egg is being added to sys.path
  pkg_resources.working_set.add_entry(path)
/home/gary/launchpad/lp-sourcedeps/newer-buildout/bootstrap.py:129: UserWarning: Module site was already imported from /usr/lib/python2.6/site.pyc, but /home/gary/launchpad/lp-sourcedeps/newer-buildout/eggs/distribute-0.6.10-py2.6.egg is being added to sys.path
  pkg_resources.working_set.add_entry(path)
Traceback (most recent call last):
  File "bootstrap.py", line 179, in <module>
    ws.require(requirement)
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 626, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 524, in resolve
    raise DistributionNotFound(req) # XXX put more info here
pkg_resources.DistributionNotFound: setuptools
make: *** [bin/buildout] Error 1

That's...

review: Needs Fixing
lp:~sidnei/lazr-js/newer-buildout updated
173. By Sidnei da Silva

- Merge from gary's branch

Revision history for this message
Gary Poster (gary) wrote :

You reported my changes continued to work for you on lucid.

Heh, ok, I don't like my sys.modules thing but I don't know anything better, so sure, approved. :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2009-12-04 17:55:51 +0000
3+++ Makefile 2010-03-16 15:59:22 +0000
4@@ -44,8 +44,9 @@
5 ln -s ../src-js/lazrjs src-py/lazrjs;\
6 fi
7
8- $(SHHH) $(PYTHON) -S bootstrap.py\
9- --ez_setup-source=ez_setup.py \
10+ $(SHHH) $(PYTHON) -S bootstrap.py \
11+ --distribute \
12+ --setup-source=distribute_setup.py \
13 --download-base=download-cache/dist --eggs=eggs
14
15 $(PY): bin/buildout buildout.cfg setup.py
16
17=== modified file 'bootstrap.py'
18--- bootstrap.py 2009-10-21 21:43:07 +0000
19+++ bootstrap.py 2010-03-16 15:59:22 +0000
20@@ -17,106 +17,121 @@
21 The script accepts buildout command-line options, so you can
22 use the -c option to specify an alternate configuration file.
23
24-$Id: bootstrap.py 101930 2009-07-15 18:34:35Z gary $
25+$Id$
26 """
27
28-import os, re, shutil, sys, tempfile, textwrap, urllib, urllib2
29-
30-# We have to manually parse our options rather than using one of the stdlib
31-# tools because we want to pass the ones we don't recognize along to
32-# zc.buildout.buildout.main.
33-
34-configuration = {
35- '--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
36- '--version': '',
37- '--download-base': None,
38- '--eggs': None}
39-
40-helpstring = __doc__ + textwrap.dedent('''
41- This script recognizes the following options itself. The first option it
42- encounters that is not one of these will cause the script to stop parsing
43- options and pass the rest on to buildout. Therefore, if you want to use
44- any of the following options *and* buildout command-line options like
45- -c, first use the following options, and then use the buildout options.
46-
47- Options:
48- --version=ZC_BUILDOUT_VERSION
49- Specify a version number of the zc.buildout to use
50- --ez_setup-source=URL_OR_FILE
51- Specify a URL or file location for the ez_setup file.
52- Defaults to
53- %(--ez_setup-source)s
54- --download-base=URL_OR_DIRECTORY
55- Specify a URL or directory for downloading setuptools and
56- zc.buildout. Defaults to PyPI.
57- --eggs=DIRECTORY
58- Specify a directory for storing eggs. Defaults to a temporary
59- directory that is deleted when the bootstrap script completes.
60-
61- By using --ez_setup-source and --download-base to point to local resources,
62- you can keep this script from going over the network.
63- ''' % configuration)
64-match_equals = re.compile(r'(%s)=(.*)' % ('|'.join(configuration),)).match
65-args = sys.argv[1:]
66-if args == ['--help']:
67- print helpstring
68- sys.exit(0)
69-
70-# If we end up using a temporary directory for storing our eggs, this will
71-# hold the path of that directory. On the other hand, if an explicit directory
72-# is specified in the argv, this will remain None.
73-tmpeggs = None
74-
75-while args:
76- val = args[0]
77- if val in configuration:
78- del args[0]
79- if not args or args[0].startswith('-'):
80- print "ERROR: %s requires an argument."
81- print helpstring
82- sys.exit(1)
83- configuration[val] = args[0]
84+import os, shutil, sys, tempfile, textwrap, urllib, urllib2
85+from optparse import OptionParser
86+
87+clean_path = sys.path[:]
88+import site
89+sys.path[:] = clean_path
90+for k, v in sys.modules.items():
91+ if (hasattr(v, '__path__') and
92+ len(v.__path__)==1 and
93+ not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
94+ # This is a namespace package. Remove it.
95+ sys.modules.pop(k)
96+
97+is_jython = sys.platform.startswith('java')
98+
99+setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
100+distribute_source = 'http://python-distribute.org/distribute_setup.py'
101+
102+# parsing arguments
103+def normalize_to_url(option, opt_str, value, parser):
104+ if value:
105+ if '://' not in value: # It doesn't smell like a URL.
106+ value = 'file://%s' % (
107+ urllib.pathname2url(
108+ os.path.abspath(os.path.expanduser(value))),)
109+ if opt_str == '--download-base' and not value.endswith('/'):
110+ # Download base needs a trailing slash to make the world happy.
111+ value += '/'
112 else:
113- match = match_equals(val)
114- if match and match.group(1) in configuration:
115- configuration[match.group(1)] = match.group(2)
116- else:
117- break
118- del args[0]
119-
120-for name in ('--ez_setup-source', '--download-base'):
121- val = configuration[name]
122- if val is not None and '://' not in val: # We're being lazy.
123- configuration[name] = 'file://%s' % (
124- urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)
125-
126-if (configuration['--download-base'] and
127- not configuration['--download-base'].endswith('/')):
128- # Download base needs a trailing slash to make the world happy.
129- configuration['--download-base'] += '/'
130-
131-if not configuration['--eggs']:
132- configuration['--eggs'] = tmpeggs = tempfile.mkdtemp()
133+ value = None
134+ name = opt_str[2:].replace('-', '_')
135+ setattr(parser.values, name, value)
136+
137+usage = '''\
138+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
139+
140+Bootstraps a buildout-based project.
141+
142+Simply run this script in a directory containing a buildout.cfg, using the
143+Python that you want bin/buildout to use.
144+
145+Note that by using --setup-source and --download-base to point to
146+local resources, you can keep this script from going over the network.
147+'''
148+
149+parser = OptionParser(usage=usage)
150+parser.add_option("-v", "--version", dest="version",
151+ help="use a specific zc.buildout version")
152+parser.add_option("-d", "--distribute",
153+ action="store_true", dest="use_distribute", default=False,
154+ help="Use Distribute rather than Setuptools.")
155+parser.add_option("--setup-source", action="callback", dest="setup_source",
156+ callback=normalize_to_url, nargs=1, type="string",
157+ help=("Specify a URL or file location for the setup file. "
158+ "If you use Setuptools, this will default to " +
159+ setuptools_source + "; if you use Distribute, this "
160+ "will default to " + distribute_source +"."))
161+parser.add_option("--download-base", action="callback", dest="download_base",
162+ callback=normalize_to_url, nargs=1, type="string",
163+ help=("Specify a URL or directory for downloading "
164+ "zc.buildout and either Setuptools or Distribute. "
165+ "Defaults to PyPI."))
166+parser.add_option("--eggs",
167+ help=("Specify a directory for storing eggs. Defaults to "
168+ "a temporary directory that is deleted when the "
169+ "bootstrap script completes."))
170+parser.add_option("-c", None, action="store", dest="config_file",
171+ help=("Specify the path to the buildout configuration "
172+ "file to be used."))
173+
174+options, args = parser.parse_args()
175+
176+# if -c was provided, we push it back into args for buildout' main function
177+if options.config_file is not None:
178+ args += ['-c', options.config_file]
179+
180+if options.eggs:
181+ eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
182 else:
183- configuration['--eggs'] = os.path.abspath(
184- os.path.expanduser(configuration['--eggs']))
185-
186-# The requirement is what we will pass to setuptools to specify zc.buildout.
187-requirement = 'zc.buildout'
188-if configuration['--version']:
189- requirement += '==' + configuration['--version']
190+ eggs_dir = tempfile.mkdtemp()
191+
192+if options.setup_source is None:
193+ if options.use_distribute:
194+ options.setup_source = distribute_source
195+ else:
196+ options.setup_source = setuptools_source
197+
198+args = args + ['bootstrap']
199+
200
201 try:
202+ to_reload = False
203+ import pkg_resources
204+ to_reload = True
205+ if not hasattr(pkg_resources, '_distribute'):
206+ raise ImportError
207 import setuptools # A flag. Sometimes pkg_resources is installed alone.
208- import pkg_resources
209 except ImportError:
210+ ez_code = urllib2.urlopen(
211+ options.setup_source).read().replace('\r\n', '\n')
212 ez = {}
213- exec urllib2.urlopen(configuration['--ez_setup-source']).read() in ez
214- setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0)
215- if configuration['--download-base']:
216- setuptools_args['download_base'] = configuration['--download-base']
217- ez['use_setuptools'](**setuptools_args)
218- import pkg_resources
219+ exec ez_code in ez
220+ setup_args = dict(to_dir=eggs_dir, download_delay=0)
221+ if options.download_base:
222+ setup_args['download_base'] = options.download_base
223+ if options.use_distribute:
224+ setup_args['no_fake'] = True
225+ ez['use_setuptools'](**setup_args)
226+ if to_reload:
227+ reload(pkg_resources)
228+ else:
229+ import pkg_resources
230 # This does not (always?) update the default working set. We will
231 # do it.
232 for path in sys.path:
233@@ -132,39 +147,47 @@
234 else:
235 def quote (c):
236 return c
237+
238 cmd = [quote(sys.executable),
239 '-c',
240 quote('from setuptools.command.easy_install import main; main()'),
241 '-mqNxd',
242- quote(configuration['--eggs'])]
243-
244-if configuration['--download-base']:
245- cmd.extend(['-f', quote(configuration['--download-base'])])
246-
247+ quote(eggs_dir)]
248+
249+if options.download_base:
250+ cmd.extend(['-f', quote(options.download_base)])
251+
252+requirement = 'zc.buildout'
253+if options.version:
254+ requirement = '=='.join((requirement, options.version))
255 cmd.append(requirement)
256
257+if options.use_distribute:
258+ setup_requirement = 'distribute'
259+else:
260+ setup_requirement = 'setuptools'
261 ws = pkg_resources.working_set
262 env = dict(
263 os.environ,
264- PYTHONPATH=ws.find(pkg_resources.Requirement.parse('setuptools')).location)
265+ PYTHONPATH=ws.find(
266+ pkg_resources.Requirement.parse(setup_requirement)).location)
267
268-is_jython = sys.platform.startswith('java')
269 if is_jython:
270 import subprocess
271 exitcode = subprocess.Popen(cmd, env=env).wait()
272-else: # Windows needs this, apparently; otherwise we would prefer subprocess
273+else: # Windows prefers this, apparently; otherwise we would prefer subprocess
274 exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
275 if exitcode != 0:
276 sys.stdout.flush()
277+ sys.stderr.flush()
278 print ("An error occured when trying to install zc.buildout. "
279 "Look above this message for any errors that "
280 "were output by easy_install.")
281 sys.exit(exitcode)
282
283-ws.add_entry(configuration['--eggs'])
284+ws.add_entry(eggs_dir)
285 ws.require(requirement)
286 import zc.buildout.buildout
287-args.append('bootstrap')
288 zc.buildout.buildout.main(args)
289-if tmpeggs is not None:
290- shutil.rmtree(tmpeggs)
291+if not options.eggs: # clean up temporary egg directory
292+ shutil.rmtree(eggs_dir)
293
294=== added file 'distribute_setup.py'
295--- distribute_setup.py 1970-01-01 00:00:00 +0000
296+++ distribute_setup.py 2010-03-16 15:59:22 +0000
297@@ -0,0 +1,477 @@
298+#!python
299+"""Bootstrap distribute installation
300+
301+If you want to use setuptools in your package's setup.py, just include this
302+file in the same directory with it, and add this to the top of your setup.py::
303+
304+ from distribute_setup import use_setuptools
305+ use_setuptools()
306+
307+If you want to require a specific version of setuptools, set a download
308+mirror, or use an alternate download directory, you can do so by supplying
309+the appropriate options to ``use_setuptools()``.
310+
311+This file can also be run as a script to install or upgrade setuptools.
312+"""
313+import os
314+import sys
315+import time
316+import fnmatch
317+import tempfile
318+import tarfile
319+from distutils import log
320+
321+try:
322+ from site import USER_SITE
323+except ImportError:
324+ USER_SITE = None
325+
326+try:
327+ import subprocess
328+
329+ def _python_cmd(*args):
330+ args = (sys.executable,) + args
331+ return subprocess.call(args) == 0
332+
333+except ImportError:
334+ # will be used for python 2.3
335+ def _python_cmd(*args):
336+ args = (sys.executable,) + args
337+ # quoting arguments if windows
338+ if sys.platform == 'win32':
339+ def quote(arg):
340+ if ' ' in arg:
341+ return '"%s"' % arg
342+ return arg
343+ args = [quote(arg) for arg in args]
344+ return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
345+
346+DEFAULT_VERSION = "0.6.10"
347+DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
348+SETUPTOOLS_FAKED_VERSION = "0.6c11"
349+
350+SETUPTOOLS_PKG_INFO = """\
351+Metadata-Version: 1.0
352+Name: setuptools
353+Version: %s
354+Summary: xxxx
355+Home-page: xxx
356+Author: xxx
357+Author-email: xxx
358+License: xxx
359+Description: xxx
360+""" % SETUPTOOLS_FAKED_VERSION
361+
362+
363+def _install(tarball):
364+ # extracting the tarball
365+ tmpdir = tempfile.mkdtemp()
366+ log.warn('Extracting in %s', tmpdir)
367+ old_wd = os.getcwd()
368+ try:
369+ os.chdir(tmpdir)
370+ tar = tarfile.open(tarball)
371+ _extractall(tar)
372+ tar.close()
373+
374+ # going in the directory
375+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
376+ os.chdir(subdir)
377+ log.warn('Now working in %s', subdir)
378+
379+ # installing
380+ log.warn('Installing Distribute')
381+ if not _python_cmd('setup.py', 'install'):
382+ log.warn('Something went wrong during the installation.')
383+ log.warn('See the error message above.')
384+ finally:
385+ os.chdir(old_wd)
386+
387+
388+def _build_egg(egg, tarball, to_dir):
389+ # extracting the tarball
390+ tmpdir = tempfile.mkdtemp()
391+ log.warn('Extracting in %s', tmpdir)
392+ old_wd = os.getcwd()
393+ try:
394+ os.chdir(tmpdir)
395+ tar = tarfile.open(tarball)
396+ _extractall(tar)
397+ tar.close()
398+
399+ # going in the directory
400+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
401+ os.chdir(subdir)
402+ log.warn('Now working in %s', subdir)
403+
404+ # building an egg
405+ log.warn('Building a Distribute egg in %s', to_dir)
406+ _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
407+
408+ finally:
409+ os.chdir(old_wd)
410+ # returning the result
411+ log.warn(egg)
412+ if not os.path.exists(egg):
413+ raise IOError('Could not build the egg.')
414+
415+
416+def _do_download(version, download_base, to_dir, download_delay):
417+ egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
418+ % (version, sys.version_info[0], sys.version_info[1]))
419+ if not os.path.exists(egg):
420+ tarball = download_setuptools(version, download_base,
421+ to_dir, download_delay)
422+ _build_egg(egg, tarball, to_dir)
423+ sys.path.insert(0, egg)
424+ import setuptools
425+ setuptools.bootstrap_install_from = egg
426+
427+
428+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
429+ to_dir=os.curdir, download_delay=15, no_fake=True):
430+ # making sure we use the absolute path
431+ to_dir = os.path.abspath(to_dir)
432+ was_imported = 'pkg_resources' in sys.modules or \
433+ 'setuptools' in sys.modules
434+ try:
435+ try:
436+ import pkg_resources
437+ if not hasattr(pkg_resources, '_distribute'):
438+ if not no_fake:
439+ _fake_setuptools()
440+ raise ImportError
441+ except ImportError:
442+ return _do_download(version, download_base, to_dir, download_delay)
443+ try:
444+ pkg_resources.require("distribute>="+version)
445+ return
446+ except pkg_resources.VersionConflict:
447+ e = sys.exc_info()[1]
448+ if was_imported:
449+ sys.stderr.write(
450+ "The required version of distribute (>=%s) is not available,\n"
451+ "and can't be installed while this script is running. Please\n"
452+ "install a more recent version first, using\n"
453+ "'easy_install -U distribute'."
454+ "\n\n(Currently using %r)\n" % (version, e.args[0]))
455+ sys.exit(2)
456+ else:
457+ del pkg_resources, sys.modules['pkg_resources'] # reload ok
458+ return _do_download(version, download_base, to_dir,
459+ download_delay)
460+ except pkg_resources.DistributionNotFound:
461+ return _do_download(version, download_base, to_dir,
462+ download_delay)
463+ finally:
464+ if not no_fake:
465+ _create_fake_setuptools_pkg_info(to_dir)
466+
467+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
468+ to_dir=os.curdir, delay=15):
469+ """Download distribute from a specified location and return its filename
470+
471+ `version` should be a valid distribute version number that is available
472+ as an egg for download under the `download_base` URL (which should end
473+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
474+ `delay` is the number of seconds to pause before an actual download
475+ attempt.
476+ """
477+ # making sure we use the absolute path
478+ to_dir = os.path.abspath(to_dir)
479+ try:
480+ from urllib.request import urlopen
481+ except ImportError:
482+ from urllib2 import urlopen
483+ tgz_name = "distribute-%s.tar.gz" % version
484+ url = download_base + tgz_name
485+ saveto = os.path.join(to_dir, tgz_name)
486+ src = dst = None
487+ if not os.path.exists(saveto): # Avoid repeated downloads
488+ try:
489+ log.warn("Downloading %s", url)
490+ src = urlopen(url)
491+ # Read/write all in one block, so we don't create a corrupt file
492+ # if the download is interrupted.
493+ data = src.read()
494+ dst = open(saveto, "wb")
495+ dst.write(data)
496+ finally:
497+ if src:
498+ src.close()
499+ if dst:
500+ dst.close()
501+ return os.path.realpath(saveto)
502+
503+
504+def _patch_file(path, content):
505+ """Will backup the file then patch it"""
506+ existing_content = open(path).read()
507+ if existing_content == content:
508+ # already patched
509+ log.warn('Already patched.')
510+ return False
511+ log.warn('Patching...')
512+ _rename_path(path)
513+ f = open(path, 'w')
514+ try:
515+ f.write(content)
516+ finally:
517+ f.close()
518+ return True
519+
520+
521+def _same_content(path, content):
522+ return open(path).read() == content
523+
524+def _no_sandbox(function):
525+ def __no_sandbox(*args, **kw):
526+ try:
527+ from setuptools.sandbox import DirectorySandbox
528+ def violation(*args):
529+ pass
530+ DirectorySandbox._old = DirectorySandbox._violation
531+ DirectorySandbox._violation = violation
532+ patched = True
533+ except ImportError:
534+ patched = False
535+
536+ try:
537+ return function(*args, **kw)
538+ finally:
539+ if patched:
540+ DirectorySandbox._violation = DirectorySandbox._old
541+ del DirectorySandbox._old
542+
543+ return __no_sandbox
544+
545+@_no_sandbox
546+def _rename_path(path):
547+ new_name = path + '.OLD.%s' % time.time()
548+ log.warn('Renaming %s into %s', path, new_name)
549+ os.rename(path, new_name)
550+ return new_name
551+
552+def _remove_flat_installation(placeholder):
553+ if not os.path.isdir(placeholder):
554+ log.warn('Unkown installation at %s', placeholder)
555+ return False
556+ found = False
557+ for file in os.listdir(placeholder):
558+ if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
559+ found = True
560+ break
561+ if not found:
562+ log.warn('Could not locate setuptools*.egg-info')
563+ return
564+
565+ log.warn('Removing elements out of the way...')
566+ pkg_info = os.path.join(placeholder, file)
567+ if os.path.isdir(pkg_info):
568+ patched = _patch_egg_dir(pkg_info)
569+ else:
570+ patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
571+
572+ if not patched:
573+ log.warn('%s already patched.', pkg_info)
574+ return False
575+ # now let's move the files out of the way
576+ for element in ('setuptools', 'pkg_resources.py', 'site.py'):
577+ element = os.path.join(placeholder, element)
578+ if os.path.exists(element):
579+ _rename_path(element)
580+ else:
581+ log.warn('Could not find the %s element of the '
582+ 'Setuptools distribution', element)
583+ return True
584+
585+
586+def _after_install(dist):
587+ log.warn('After install bootstrap.')
588+ placeholder = dist.get_command_obj('install').install_purelib
589+ _create_fake_setuptools_pkg_info(placeholder)
590+
591+@_no_sandbox
592+def _create_fake_setuptools_pkg_info(placeholder):
593+ if not placeholder or not os.path.exists(placeholder):
594+ log.warn('Could not find the install location')
595+ return
596+ pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
597+ setuptools_file = 'setuptools-%s-py%s.egg-info' % \
598+ (SETUPTOOLS_FAKED_VERSION, pyver)
599+ pkg_info = os.path.join(placeholder, setuptools_file)
600+ if os.path.exists(pkg_info):
601+ log.warn('%s already exists', pkg_info)
602+ return
603+
604+ log.warn('Creating %s', pkg_info)
605+ f = open(pkg_info, 'w')
606+ try:
607+ f.write(SETUPTOOLS_PKG_INFO)
608+ finally:
609+ f.close()
610+
611+ pth_file = os.path.join(placeholder, 'setuptools.pth')
612+ log.warn('Creating %s', pth_file)
613+ f = open(pth_file, 'w')
614+ try:
615+ f.write(os.path.join(os.curdir, setuptools_file))
616+ finally:
617+ f.close()
618+
619+def _patch_egg_dir(path):
620+ # let's check if it's already patched
621+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
622+ if os.path.exists(pkg_info):
623+ if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
624+ log.warn('%s already patched.', pkg_info)
625+ return False
626+ _rename_path(path)
627+ os.mkdir(path)
628+ os.mkdir(os.path.join(path, 'EGG-INFO'))
629+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
630+ f = open(pkg_info, 'w')
631+ try:
632+ f.write(SETUPTOOLS_PKG_INFO)
633+ finally:
634+ f.close()
635+ return True
636+
637+
638+def _before_install():
639+ log.warn('Before install bootstrap.')
640+ _fake_setuptools()
641+
642+
643+def _under_prefix(location):
644+ if 'install' not in sys.argv:
645+ return True
646+ args = sys.argv[sys.argv.index('install')+1:]
647+ for index, arg in enumerate(args):
648+ for option in ('--root', '--prefix'):
649+ if arg.startswith('%s=' % option):
650+ top_dir = arg.split('root=')[-1]
651+ return location.startswith(top_dir)
652+ elif arg == option:
653+ if len(args) > index:
654+ top_dir = args[index+1]
655+ return location.startswith(top_dir)
656+ elif option == '--user' and USER_SITE is not None:
657+ return location.startswith(USER_SITE)
658+ return True
659+
660+
661+def _fake_setuptools():
662+ log.warn('Scanning installed packages')
663+ try:
664+ import pkg_resources
665+ except ImportError:
666+ # we're cool
667+ log.warn('Setuptools or Distribute does not seem to be installed.')
668+ return
669+ ws = pkg_resources.working_set
670+ try:
671+ setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
672+ replacement=False))
673+ except TypeError:
674+ # old distribute API
675+ setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
676+
677+ if setuptools_dist is None:
678+ log.warn('No setuptools distribution found')
679+ return
680+ # detecting if it was already faked
681+ setuptools_location = setuptools_dist.location
682+ log.warn('Setuptools installation detected at %s', setuptools_location)
683+
684+ # if --root or --preix was provided, and if
685+ # setuptools is not located in them, we don't patch it
686+ if not _under_prefix(setuptools_location):
687+ log.warn('Not patching, --root or --prefix is installing Distribute'
688+ ' in another location')
689+ return
690+
691+ # let's see if its an egg
692+ if not setuptools_location.endswith('.egg'):
693+ log.warn('Non-egg installation')
694+ res = _remove_flat_installation(setuptools_location)
695+ if not res:
696+ return
697+ else:
698+ log.warn('Egg installation')
699+ pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
700+ if (os.path.exists(pkg_info) and
701+ _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
702+ log.warn('Already patched.')
703+ return
704+ log.warn('Patching...')
705+ # let's create a fake egg replacing setuptools one
706+ res = _patch_egg_dir(setuptools_location)
707+ if not res:
708+ return
709+ log.warn('Patched done.')
710+ _relaunch()
711+
712+
713+def _relaunch():
714+ log.warn('Relaunching...')
715+ # we have to relaunch the process
716+ args = [sys.executable] + sys.argv
717+ sys.exit(subprocess.call(args))
718+
719+
720+def _extractall(self, path=".", members=None):
721+ """Extract all members from the archive to the current working
722+ directory and set owner, modification time and permissions on
723+ directories afterwards. `path' specifies a different directory
724+ to extract to. `members' is optional and must be a subset of the
725+ list returned by getmembers().
726+ """
727+ import copy
728+ import operator
729+ from tarfile import ExtractError
730+ directories = []
731+
732+ if members is None:
733+ members = self
734+
735+ for tarinfo in members:
736+ if tarinfo.isdir():
737+ # Extract directories with a safe mode.
738+ directories.append(tarinfo)
739+ tarinfo = copy.copy(tarinfo)
740+ tarinfo.mode = 448 # decimal for oct 0700
741+ self.extract(tarinfo, path)
742+
743+ # Reverse sort directories.
744+ if sys.version_info < (2, 4):
745+ def sorter(dir1, dir2):
746+ return cmp(dir1.name, dir2.name)
747+ directories.sort(sorter)
748+ directories.reverse()
749+ else:
750+ directories.sort(key=operator.attrgetter('name'), reverse=True)
751+
752+ # Set correct owner, mtime and filemode on directories.
753+ for tarinfo in directories:
754+ dirpath = os.path.join(path, tarinfo.name)
755+ try:
756+ self.chown(tarinfo, dirpath)
757+ self.utime(tarinfo, dirpath)
758+ self.chmod(tarinfo, dirpath)
759+ except ExtractError:
760+ e = sys.exc_info()[1]
761+ if self.errorlevel > 1:
762+ raise
763+ else:
764+ self._dbg(1, "tarfile: %s" % e)
765+
766+
767+def main(argv, version=DEFAULT_VERSION):
768+ """Install or upgrade setuptools and EasyInstall"""
769+ tarball = download_setuptools()
770+ _install(tarball)
771+
772+
773+if __name__ == '__main__':
774+ main(sys.argv[1:])
775
776=== removed file 'ez_setup.py'
777--- ez_setup.py 2009-10-21 21:43:07 +0000
778+++ ez_setup.py 1970-01-01 00:00:00 +0000
779@@ -1,275 +0,0 @@
780-#!python
781-"""Bootstrap setuptools installation
782-
783-If you want to use setuptools in your package's setup.py, just include this
784-file in the same directory with it, and add this to the top of your setup.py::
785-
786- from ez_setup import use_setuptools
787- use_setuptools()
788-
789-If you want to require a specific version of setuptools, set a download
790-mirror, or use an alternate download directory, you can do so by supplying
791-the appropriate options to ``use_setuptools()``.
792-
793-This file can also be run as a script to install or upgrade setuptools.
794-"""
795-import sys
796-DEFAULT_VERSION = "0.6c9"
797-DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
798-
799-md5_data = {
800- 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
801- 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
802- 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
803- 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
804- 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
805- 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
806- 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
807- 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
808- 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
809- 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
810- 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
811- 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
812- 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
813- 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
814- 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
815- 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
816- 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
817- 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
818- 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
819- 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
820- 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
821- 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
822- 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
823- 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
824- 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
825- 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
826- 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
827- 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
828- 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
829- 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
830- 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',
831- 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',
832- 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',
833- 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
834-}
835-
836-import sys, os
837-try: from hashlib import md5
838-except ImportError: from md5 import md5
839-
840-def _validate_md5(egg_name, data):
841- if egg_name in md5_data:
842- digest = md5(data).hexdigest()
843- if digest != md5_data[egg_name]:
844- print >>sys.stderr, (
845- "md5 validation of %s failed! (Possible download problem?)"
846- % egg_name
847- )
848- sys.exit(2)
849- return data
850-
851-def use_setuptools(
852- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
853- download_delay=15
854-):
855- """Automatically find/download setuptools and make it available on sys.path
856-
857- `version` should be a valid setuptools version number that is available
858- as an egg for download under the `download_base` URL (which should end with
859- a '/'). `to_dir` is the directory where setuptools will be downloaded, if
860- it is not already available. If `download_delay` is specified, it should
861- be the number of seconds that will be paused before initiating a download,
862- should one be required. If an older version of setuptools is installed,
863- this routine will print a message to ``sys.stderr`` and raise SystemExit in
864- an attempt to abort the calling script.
865- """
866- was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
867- def do_download():
868- egg = download_setuptools(version, download_base, to_dir, download_delay)
869- sys.path.insert(0, egg)
870- import setuptools; setuptools.bootstrap_install_from = egg
871- try:
872- import pkg_resources
873- except ImportError:
874- return do_download()
875- try:
876- pkg_resources.require("setuptools>="+version); return
877- except pkg_resources.VersionConflict, e:
878- if was_imported:
879- print >>sys.stderr, (
880- "The required version of setuptools (>=%s) is not available, and\n"
881- "can't be installed while this script is running. Please install\n"
882- " a more recent version first, using 'easy_install -U setuptools'."
883- "\n\n(Currently using %r)"
884- ) % (version, e.args[0])
885- sys.exit(2)
886- else:
887- del pkg_resources, sys.modules['pkg_resources'] # reload ok
888- return do_download()
889- except pkg_resources.DistributionNotFound:
890- return do_download()
891-
892-def download_setuptools(
893- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
894- delay = 15
895-):
896- """Download setuptools from a specified location and return its filename
897-
898- `version` should be a valid setuptools version number that is available
899- as an egg for download under the `download_base` URL (which should end
900- with a '/'). `to_dir` is the directory where the egg will be downloaded.
901- `delay` is the number of seconds to pause before an actual download attempt.
902- """
903- import urllib2, shutil
904- egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
905- url = download_base + egg_name
906- saveto = os.path.join(to_dir, egg_name)
907- src = dst = None
908- if not os.path.exists(saveto): # Avoid repeated downloads
909- try:
910- from distutils import log
911- if delay:
912- log.warn("""
913----------------------------------------------------------------------------
914-This script requires setuptools version %s to run (even to display
915-help). I will attempt to download it for you (from
916-%s), but
917-you may need to enable firewall access for this script first.
918-I will start the download in %d seconds.
919-
920-(Note: if this machine does not have network access, please obtain the file
921-
922- %s
923-
924-and place it in this directory before rerunning this script.)
925----------------------------------------------------------------------------""",
926- version, download_base, delay, url
927- ); from time import sleep; sleep(delay)
928- log.warn("Downloading %s", url)
929- src = urllib2.urlopen(url)
930- # Read/write all in one block, so we don't create a corrupt file
931- # if the download is interrupted.
932- data = _validate_md5(egg_name, src.read())
933- dst = open(saveto,"wb"); dst.write(data)
934- finally:
935- if src: src.close()
936- if dst: dst.close()
937- return os.path.realpath(saveto)
938-
939-
940-
941-
942-
943-
944-
945-
946-
947-
948-
949-
950-
951-
952-
953-
954-
955-
956-
957-
958-
959-
960-
961-
962-
963-
964-
965-
966-
967-
968-
969-
970-
971-
972-
973-
974-def main(argv, version=DEFAULT_VERSION):
975- """Install or upgrade setuptools and EasyInstall"""
976- try:
977- import setuptools
978- except ImportError:
979- egg = None
980- try:
981- egg = download_setuptools(version, delay=0)
982- sys.path.insert(0,egg)
983- from setuptools.command.easy_install import main
984- return main(list(argv)+[egg]) # we're done here
985- finally:
986- if egg and os.path.exists(egg):
987- os.unlink(egg)
988- else:
989- if setuptools.__version__ == '0.0.1':
990- print >>sys.stderr, (
991- "You have an obsolete version of setuptools installed. Please\n"
992- "remove it from your system entirely before rerunning this script."
993- )
994- sys.exit(2)
995-
996- req = "setuptools>="+version
997- import pkg_resources
998- try:
999- pkg_resources.require(req)
1000- except pkg_resources.VersionConflict:
1001- try:
1002- from setuptools.command.easy_install import main
1003- except ImportError:
1004- from easy_install import main
1005- main(list(argv)+[download_setuptools(delay=0)])
1006- sys.exit(0) # try to force an exit
1007- else:
1008- if argv:
1009- from setuptools.command.easy_install import main
1010- main(argv)
1011- else:
1012- print "Setuptools version",version,"or greater has been installed."
1013- print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
1014-
1015-def update_md5(filenames):
1016- """Update our built-in md5 registry"""
1017-
1018- import re
1019-
1020- for name in filenames:
1021- base = os.path.basename(name)
1022- f = open(name,'rb')
1023- md5_data[base] = md5(f.read()).hexdigest()
1024- f.close()
1025-
1026- data = [" %r: %r,\n" % it for it in md5_data.items()]
1027- data.sort()
1028- repl = "".join(data)
1029-
1030- import inspect
1031- srcfile = inspect.getsourcefile(sys.modules[__name__])
1032- f = open(srcfile, 'rb'); src = f.read(); f.close()
1033-
1034- match = re.search("\nmd5_data = {\n([^}]+)}", src)
1035- if not match:
1036- print >>sys.stderr, "Internal error!"
1037- sys.exit(2)
1038-
1039- src = src[:match.start(1)] + repl + src[match.end(1):]
1040- f = open(srcfile,'w')
1041- f.write(src)
1042- f.close()
1043-
1044-
1045-if __name__=='__main__':
1046- if len(sys.argv)>2 and sys.argv[1]=='--md5update':
1047- update_md5(sys.argv[2:])
1048- else:
1049- main(sys.argv[1:])
1050-
1051-
1052-
1053-
1054-
1055
1056=== modified file 'setup.py'
1057--- setup.py 2009-12-16 13:52:09 +0000
1058+++ setup.py 2010-03-16 15:59:22 +0000
1059@@ -1,7 +1,7 @@
1060 # Copyright 2009 Canonical Ltd. All rights reserved.
1061
1062-import ez_setup
1063-ez_setup.use_setuptools()
1064+import distribute_setup
1065+distribute_setup.use_setuptools()
1066
1067 import sys
1068 from setuptools import setup, find_packages
1069
1070=== modified file 'versions.cfg'
1071--- versions.cfg 2009-11-13 20:43:37 +0000
1072+++ versions.cfg 2010-03-16 15:59:22 +0000
1073@@ -8,10 +8,10 @@
1074 cssutils = 0.9.6
1075 lazr.testing = 0.1.1
1076 mocker = 0.10.1
1077-setuptools = 0.6c9
1078+distribute = 0.6.10
1079 simplejson = 2.0.9
1080 z3c.recipe.tag = 0.2.0
1081-zc.buildout = 1.4.1
1082+zc.buildout = 1.4.3
1083 zc.recipe.egg = 1.2.2
1084 zc.recipe.testrunner = 1.2.0
1085 zope.exceptions = 3.5.2

Subscribers

People subscribed via source and target branches