[Checkins] SVN: zc.buildout/trunk/src/zc/buildout/easy_install.
Added basic low-level support for a download cache.
Jim Fulton
jim at zope.com
Sun Mar 18 14:56:32 EDT 2007
Log message for revision 73327:
Added basic low-level support for a download cache.
This led to a pretty major refactoring.
Changed:
U zc.buildout/trunk/src/zc/buildout/easy_install.py
U zc.buildout/trunk/src/zc/buildout/easy_install.txt
-=-
Modified: zc.buildout/trunk/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.py 2007-03-18 18:48:45 UTC (rev 73326)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.py 2007-03-18 18:56:31 UTC (rev 73327)
@@ -104,9 +104,11 @@
'from setuptools.command.easy_install import main; main()'
)
+
class Installer:
_versions = {}
+ _download_cache = None
def __init__(self,
dest=None,
@@ -119,7 +121,10 @@
versions=None,
):
self._dest = dest
- self._links = list(links)
+ self._links = links = list(links)
+ if self._download_cache and (self._download_cache not in links):
+ links.insert(0, self._download_cache)
+
self._index_url = index
self._executable = executable
self._always_unzip = always_unzip
@@ -127,6 +132,8 @@
if dest is not None and dest not in path:
path.insert(0, dest)
self._path = path
+ if self._dest is None:
+ newest = False
self._newest = newest
self._env = pkg_resources.Environment(path,
python=_get_version(executable))
@@ -135,12 +142,12 @@
if versions is not None:
self._versions = versions
- def _satisfied(self, req):
+ def _satisfied(self, req, source=None):
dists = [dist for dist in self._env[req.project_name] if dist in req]
if not dists:
logger.debug('We have no distributions for %s that satisfies %s.',
req.project_name, req)
- return None
+ return None, self._obtain(req, source)
# Note that dists are sorted from best to worst, as promised by
# env.__getitem__
@@ -148,13 +155,13 @@
for dist in dists:
if (dist.precedence == pkg_resources.DEVELOP_DIST):
logger.debug('We have a develop egg for %s', req)
- return dist
+ return dist, None
if not self._newest:
# We don't need the newest, so we'll use the newest one we
# find, which is the first returned by
# Environment.__getitem__.
- return dists[0]
+ return dists[0], None
# Find an upper limit in the specs, if there is one:
specs = [(pkg_resources.parse_version(v), op) for (op, v) in req.specs]
@@ -189,7 +196,7 @@
if maxv is not None and best_we_have.version == maxv:
logger.debug('We have the best distribution that satisfies\n%s',
req)
- return best_we_have
+ return best_we_have, None
# We have some installed distros. There might, theoretically, be
# newer ones. Let's find out which ones are available and see if
@@ -198,7 +205,7 @@
if self._dest is not None:
- best_available = self._index.obtain(req)
+ best_available = self._obtain(req, source)
else:
best_available = None
@@ -208,7 +215,7 @@
logger.debug(
'There are no distros available that meet %s. Using our best.',
req)
- return best_we_have
+ return best_we_have, None
else:
# Let's find out if we already have the best available:
if best_we_have.parsed_version >= best_available.parsed_version:
@@ -216,148 +223,257 @@
logger.debug(
'We have the best distribution that satisfies\n%s',
req)
- return best_we_have
+ return best_we_have, None
- return None
+ return None, best_available
- def _call_easy_install(self, spec, ws, dest):
+ def _load_dist(self, dist):
+ dists = pkg_resources.Environment(
+ dist.location,
+ python=_get_version(self._executable),
+ )[dist.project_name]
+ assert len(dists) == 1
+ return dists[0]
- path = self._get_dist(pkg_resources.Requirement.parse('setuptools'),
- ws, False).location
+ def _call_easy_install(self, spec, ws, dest, dist):
- args = ('-c', _easy_install_cmd, '-mUNxd', _safe_arg(dest))
- if self._always_unzip:
- args += ('-Z', )
- level = logger.getEffectiveLevel()
- if level > 0:
- args += ('-q', )
- elif level < 0:
- args += ('-v', )
+ tmp = tempfile.mkdtemp(dir=dest)
+ try:
+ path = self._get_dist(
+ pkg_resources.Requirement.parse('setuptools'), ws, False,
+ )[0].location
- args += (spec, )
+ args = ('-c', _easy_install_cmd, '-mUNxd', _safe_arg(tmp))
+ if self._always_unzip:
+ args += ('-Z', )
+ level = logger.getEffectiveLevel()
+ if level > 0:
+ args += ('-q', )
+ elif level < 0:
+ args += ('-v', )
- if level <= logging.DEBUG:
- logger.debug('Running easy_install:\n%s "%s"\npath=%s\n',
- self._executable, '" "'.join(args), path)
+ args += (spec, )
- args += (dict(os.environ, PYTHONPATH=path), )
- sys.stdout.flush() # We want any pending output first
- exit_code = os.spawnle(os.P_WAIT, self._executable, self._executable,
- *args)
- assert exit_code == 0
+ if level <= logging.DEBUG:
+ logger.debug('Running easy_install:\n%s "%s"\npath=%s\n',
+ self._executable, '" "'.join(args), path)
+ args += (dict(os.environ, PYTHONPATH=path), )
+ sys.stdout.flush() # We want any pending output first
+ exit_code = os.spawnle(
+ os.P_WAIT, self._executable, self._executable,
+ *args)
+ dists = []
+ env = pkg_resources.Environment(
+ [tmp],
+ python=_get_version(self._executable),
+ )
+ for project in env:
+ dists.extend(env[project])
+
+ if exit_code:
+ logger.error(
+ "An error occured when trying to install %s."
+ "Look above this message for any errors that"
+ "were output by easy_install.",
+ dist)
+
+ if not dists:
+ raise zc.buildout.UserError("Couldn't install: %s" % dist)
+
+ if len(dists) > 1:
+ logger.warn("Installing %s\n"
+ "caused multiple distributions to be installed:\n"
+ "%s\n",
+ dist, '\n'.join(map(str, dists)))
+ else:
+ d = dists[0]
+ if d.project_name != dist.project_name:
+ logger.warn("Installing %s\n"
+ "Caused installation of a distribution:\n"
+ "%s\n"
+ "with a different project name.",
+ dist, d)
+ if d.version != dist.version:
+ logger.warn("Installing %s\n"
+ "Caused installation of a distribution:\n"
+ "%s\n"
+ "with a different version.",
+ dist, d)
+
+ result = []
+ for d in dists:
+ newloc = os.path.join(dest, os.path.basename(d.location))
+ if os.path.exists(newloc):
+ if os.path.is_dir(newloc):
+ shutil.rmtree(newloc)
+ else:
+ os.remove(newloc)
+ os.rename(d.location, newloc)
+
+ [d] = pkg_resources.Environment(
+ [newloc],
+ python=_get_version(self._executable),
+ )[d.project_name]
+
+ result.append(d)
+
+ return result
+
+ finally:
+ shutil.rmtree(tmp)
+
+ def _obtain(self, requirement, source=None):
+ index = self._index
+ if index.obtain(requirement) is None:
+ return None
+
+ best = []
+ bestv = ()
+ for dist in index[requirement.project_name]:
+ if dist not in requirement:
+ continue
+ if source and dist.precedence != pkg_resources.SOURCE_DIST:
+ continue
+ distv = dist.parsed_version
+ if distv > bestv:
+ best = [dist]
+ bestv = distv
+ elif distv == bestv:
+ best.append(dist)
+
+ if not best:
+ return None
+
+ if len(best) == 1:
+ return best[0]
+
+ if self._download_cache:
+ for dist in best:
+ if os.path.dirname(dist.location) == self._download_cache:
+ return dist
+
+ best.sort()
+ return best[-1]
+
+ def _fetch(self, dist, tmp):
+ return dist.clone(location=self._index.download(dist.location, tmp))
+
def _get_dist(self, requirement, ws, always_unzip):
__doing__ = 'Getting distribution for %s', requirement
# Maybe an existing dist is already the best dist that satisfies the
# requirement
- dist = self._satisfied(requirement)
+ dist, avail = self._satisfied(requirement)
if dist is None:
if self._dest is not None:
logger.info("Getting new distribution for %s", requirement)
- # Retrieve the dist:grokonepage
- index = self._index
- dist = index.obtain(requirement)
+ # Retrieve the dist:
+ if avail is None:
+ raise zc.buildout.UserError(
+ "Couldn't find a distribution for %s."
+ % requirement)
+
+ # We may overwrite distributions, so clear importer
+ # cache.
+ sys.path_importer_cache.clear()
+
+ tmp = self._download_cache
+ try:
+ if tmp:
+ if os.path.dirname(avail.location) == tmp:
+ dist = avail
+ else:
+ dist = self._fetch(avail, tmp)
+ else:
+ tmp = tempfile.mkdtemp('get_dist')
+ dist = self._fetch(avail, tmp)
+
if dist is None:
raise zc.buildout.UserError(
- "Couldn't find a distribution for %s."
- % requirement)
+ "Couln't download distribution %s." % avail)
- fname = dist.location
- if url_match(fname):
- fname = urlparse.urlparse(fname)[2]
-
- if fname.endswith('.egg'):
+ if dist.precedence == pkg_resources.EGG_DIST:
# It's already an egg, just fetch it into the dest
- tmp = tempfile.mkdtemp('get_dist')
- try:
- dist = index.fetch_distribution(requirement, tmp)
- if dist is None:
- raise zc.buildout.UserError(
- "Couln't download a distribution for %s."
- % requirement)
- newloc = os.path.join(
- self._dest, os.path.basename(dist.location))
+ newloc = os.path.join(
+ self._dest, os.path.basename(dist.location))
- if os.path.isdir(dist.location):
- # we got a directory. It must have been
- # obtained locally. Jut copy it.
- shutil.copytree(dist.location, newloc)
+ if os.path.isdir(dist.location):
+ # we got a directory. It must have been
+ # obtained locally. Just copy it.
+ shutil.copytree(dist.location, newloc)
+ else:
+
+ if self._always_unzip:
+ should_unzip = True
else:
+ metadata = pkg_resources.EggMetadata(
+ zipimport.zipimporter(dist.location)
+ )
+ should_unzip = (
+ metadata.has_metadata('not-zip-safe')
+ or
+ not metadata.has_metadata('zip-safe')
+ )
- if self._always_unzip:
- should_unzip = True
- else:
- metadata = pkg_resources.EggMetadata(
- zipimport.zipimporter(dist.location)
- )
- should_unzip = (
- metadata.has_metadata('not-zip-safe')
- or not metadata.has_metadata('zip-safe')
- )
+ if should_unzip:
+ setuptools.archive_util.unpack_archive(
+ dist.location, newloc)
+ else:
+ shutil.copyfile(dist.location, newloc)
- if should_unzip:
- setuptools.archive_util.unpack_archive(
- dist.location, newloc)
- else:
- shutil.copyfile(dist.location, newloc)
-
- finally:
- shutil.rmtree(tmp)
-
+ # Getting the dist from the environment causes the
+ # distribution meta data to be read. Cloning isn't
+ # good enough.
+ dists = pkg_resources.Environment(
+ [newloc],
+ python=_get_version(self._executable),
+ )[dist.project_name]
else:
- # It's some other kind of dist. We'll download it to
- # a temporary directory and let easy_install have it's
- # way with it:
- tmp = tempfile.mkdtemp('get_dist')
- try:
- dist = index.fetch_distribution(requirement, tmp)
+ # It's some other kind of dist. We'll let easy_install
+ # deal with it:
+ dists = self._call_easy_install(
+ dist.location, ws, self._dest, dist)
- # May need a new one. Call easy_install
- self._call_easy_install(dist.location, ws, self._dest)
- finally:
- shutil.rmtree(tmp)
+ finally:
+ if tmp != self._download_cache:
+ shutil.rmtree(tmp)
+ self._env.scan([self._dest])
+ dist = self._env.best_match(requirement, ws)
+ logger.info("Got %s", dist)
- # Because we have added a new egg, we need to rescan
- # the destination directory.
+ else:
+ dists = [dist]
- # We may overwrite distributions, so clear importer
- # cache.
- sys.path_importer_cache.clear()
-
- self._env.scan([self._dest])
- dist = self._env.best_match(requirement, ws)
- logger.info("Got %s", dist)
- else:
- dist = self._env.best_match(requirement, ws)
-
- if dist is None:
- raise ValueError("Couldn't find", requirement)
-
# XXX Need test for this
- if dist.has_metadata('dependency_links.txt'):
- for link in dist.get_metadata_lines('dependency_links.txt'):
- link = link.strip()
- if link not in self._links:
- self._links.append(link)
- self._index = _get_index(self._executable,
- self._index_url, self._links)
+ for dist in dists:
+ if dist.has_metadata('dependency_links.txt'):
+ for link in dist.get_metadata_lines('dependency_links.txt'):
+ link = link.strip()
+ if link not in self._links:
+ logger.debug('Adding find link %r from %s', link, dist)
+ self._links.append(link)
+ self._index = _get_index(self._executable,
+ self._index_url, self._links)
- # Check whether we picked a version and, if we did, report it:
- if not (
- dist.precedence == pkg_resources.DEVELOP_DIST
- or
- (len(requirement.specs) == 1 and requirement.specs[0][0] == '==')
- ):
- picked.debug('%s = %s', dist.project_name, dist.version)
+ for dist in dists:
+ # Check whether we picked a version and, if we did, report it:
+ if not (
+ dist.precedence == pkg_resources.DEVELOP_DIST
+ or
+ (len(requirement.specs) == 1
+ and
+ requirement.specs[0][0] == '==')
+ ):
+ picked.debug('%s = %s', dist.project_name, dist.version)
- return dist
+ return dists
def _maybe_add_setuptools(self, ws, dist):
if dist.has_metadata('namespace_packages.txt'):
@@ -376,8 +492,8 @@
pkg_resources.Requirement.parse('setuptools')
)
if ws.find(requirement) is None:
- dist = self._get_dist(requirement, ws, False)
- ws.add(dist)
+ for dist in self._get_dist(requirement, ws, False):
+ ws.add(dist)
def _constrain(self, requirement):
@@ -413,9 +529,9 @@
ws = working_set
for requirement in requirements:
- dist = self._get_dist(requirement, ws, self._always_unzip)
- ws.add(dist)
- self._maybe_add_setuptools(ws, dist)
+ for dist in self._get_dist(requirement, ws, self._always_unzip):
+ ws.add(dist)
+ self._maybe_add_setuptools(ws, dist)
# OK, we have the requested distributions and they're in the working
# set, but they may have unmet requirements. We'll simply keep
@@ -433,79 +549,95 @@
requirement = self._constrain(requirement)
if dest:
logger.debug('Getting required %s', requirement)
- dist = self._get_dist(requirement, ws, self._always_unzip)
- ws.add(dist)
- self._maybe_add_setuptools(ws, dist)
+ for dist in self._get_dist(requirement, ws, self._always_unzip
+ ):
+ ws.add(dist)
+ self._maybe_add_setuptools(ws, dist)
else:
break
return ws
def build(self, spec, build_ext):
- logger.debug('Building %r', spec)
requirement = self._constrain(pkg_resources.Requirement.parse(spec))
- dist = self._satisfied(requirement)
+ dist, avail = self._satisfied(requirement, 1)
if dist is not None:
- return dist.location
+ return [dist.location]
- undo = []
- try:
- tmp = tempfile.mkdtemp('build')
- undo.append(lambda : shutil.rmtree(tmp))
- tmp2 = tempfile.mkdtemp('build')
- undo.append(lambda : shutil.rmtree(tmp2))
+ # Retrieve the dist:
+ if avail is None:
+ raise zc.buildout.UserError(
+ "Couldn't find a source distribution for %s."
+ % requirement)
- dist = self._index.fetch_distribution(
- requirement, tmp2, False, True)
- if dist is None:
- raise zc.buildout.UserError(
- "Couldn't find a source distribution for %s."
- % requirement)
- setuptools.archive_util.unpack_archive(dist.location, tmp)
+ logger.debug('Building %r', spec)
- if os.path.exists(os.path.join(tmp, 'setup.py')):
- base = tmp
+ tmp = self._download_cache
+ try:
+ if tmp:
+ if os.path.dirname(avail.location) == tmp:
+ dist = avail
+ else:
+ dist = self._fetch(avail, tmp)
else:
- setups = glob.glob(os.path.join(tmp, '*', 'setup.py'))
- if not setups:
- raise distutils.errors.DistutilsError(
- "Couldn't find a setup script in %s"
- % os.path.basename(dist.location)
- )
- if len(setups) > 1:
- raise distutils.errors.DistutilsError(
- "Multiple setup scripts in %s"
- % os.path.basename(dist.location)
- )
- base = os.path.dirname(setups[0])
+ tmp = tempfile.mkdtemp('get_dist')
+ dist = self._fetch(avail, tmp)
+ build_tmp = tempfile.mkdtemp('build')
+ try:
+ setuptools.archive_util.unpack_archive(dist.location,
+ build_tmp)
+ if os.path.exists(os.path.join(build_tmp, 'setup.py')):
+ base = build_tmp
+ else:
+ setups = glob.glob(
+ os.path.join(build_tmp, '*', 'setup.py'))
+ if not setups:
+ raise distutils.errors.DistutilsError(
+ "Couldn't find a setup script in %s"
+ % os.path.basename(dist.location)
+ )
+ if len(setups) > 1:
+ raise distutils.errors.DistutilsError(
+ "Multiple setup scripts in %s"
+ % os.path.basename(dist.location)
+ )
+ base = os.path.dirname(setups[0])
+
+ setup_cfg = os.path.join(base, 'setup.cfg')
+ if not os.path.exists(setup_cfg):
+ f = open(setup_cfg, 'w')
+ f.close()
+ setuptools.command.setopt.edit_config(
+ setup_cfg, dict(build_ext=build_ext))
- setup_cfg = os.path.join(base, 'setup.cfg')
- if not os.path.exists(setup_cfg):
- f = open(setup_cfg, 'w')
- f.close()
- setuptools.command.setopt.edit_config(
- setup_cfg, dict(build_ext=build_ext))
+ dists = self._call_easy_install(
+ base, pkg_resources.WorkingSet(),
+ self._dest, dist)
- tmp3 = tempfile.mkdtemp('build', dir=self._dest)
- undo.append(lambda : shutil.rmtree(tmp3))
+ return [dist.location for dist in dists]
+ finally:
+ shutil.rmtree(build_tmp)
- self._call_easy_install(base, pkg_resources.WorkingSet(), tmp3)
+ finally:
+ if tmp != self._download_cache:
+ shutil.rmtree(tmp)
- return _copyeggs(tmp3, self._dest, '.egg', undo)
- finally:
- undo.reverse()
- [f() for f in undo]
-
def default_versions(versions=None):
old = Installer._versions
if versions is not None:
Installer._versions = versions
return old
+def download_cache(path=-1):
+ old = Installer._download_cache
+ if path != -1:
+ Installer._download_cache = path
+ return old
+
def install(specs, dest,
links=(), index=None,
executable=sys.executable, always_unzip=False,
Modified: zc.buildout/trunk/src/zc/buildout/easy_install.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.txt 2007-03-18 18:48:45 UTC (rev 73326)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.txt 2007-03-18 18:56:31 UTC (rev 73327)
@@ -645,7 +645,7 @@
#endif
}
-The extension depends on a system-dependnt include file, extdemo.h,
+The extension depends on a system-dependent include file, extdemo.h,
that defines a constant, EXTDEMO, that is exposed by the extension.
We'll add an include directory to our sample buildout and add the
@@ -664,7 +664,7 @@
... 'extdemo', dest,
... {'include-dirs': os.path.join(sample_buildout, 'include')},
... links=[link_server], index=link_server+'index/')
- '/sample-install/extdemo-1.4-py2.4-unix-i686.egg'
+ ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg']
The function returns the list of eggs
@@ -706,7 +706,7 @@
... {'include-dirs': os.path.join(sample_buildout, 'include')},
... links=[link_server], index=link_server+'index/',
... newest=False)
- '/sample-install/extdemo-1.4-py2.4-linux-i686.egg'
+ ['/sample-install/extdemo-1.4-py2.4-linux-i686.egg']
>>> ls(dest)
- demo-0.2-py2.4.egg
@@ -722,7 +722,7 @@
... 'extdemo', dest,
... {'include-dirs': os.path.join(sample_buildout, 'include')},
... links=[link_server], index=link_server+'index/')
- '/sample-install/extdemo-1.5-py2.4-unix-i686.egg'
+ ['/sample-install/extdemo-1.5-py2.4-unix-i686.egg']
>>> ls(dest)
- demo-0.2-py2.4.egg
@@ -746,7 +746,7 @@
... {'include-dirs': os.path.join(sample_buildout, 'include')},
... links=[link_server], index=link_server+'index/',
... versions=dict(extdemo='1.4'))
- '/sample-install/extdemo-1.4-py2.4-unix-i686.egg'
+ ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg']
>>> ls(dest)
d extdemo-1.4-py2.4-unix-i686.egg
@@ -814,3 +814,112 @@
d extdemo.egg-info
- extdemo.so
- setup.py
+
+Download cache
+--------------
+
+Normally, when distributions are installed, if any processing is
+needed, they are downloaded from the internet to a temporary directory
+and then installed from there. A download cache can be used to avoid
+the download step. This can be useful to reduce network access and to
+create source distributions of an entire buildout.
+
+A download cache is specified by calling the download_cache
+function. The function always returns the previous setting. If no
+argument is passed, then the setting is unchanged. Is an argument is
+passed, the download cache is set to the given path, which must point
+to an existing directory. Passing None clears the cache setting.
+
+To see this work, we'll create a directory and set it as the cache
+directory:
+
+ >>> cache = tmpdir('cache')
+ >>> zc.buildout.easy_install.download_cache(cache)
+
+We'll recreate out destination directory:
+
+ >>> remove(dest)
+ >>> dest = tmpdir('sample-install')
+
+We'd like to see what is being fetched from the server, so we'll
+enable server logging:
+
+ >>> get(link_server+'enable_server_logging')
+ GET 200 /enable_server_logging
+ ''
+
+Now, if we install demo, and extdemo:
+
+ >>> ws = zc.buildout.easy_install.install(
+ ... ['demo==0.2'], dest,
+ ... links=[link_server], index=link_server+'index/',
+ ... always_unzip=True)
+ GET 200 /
+ GET 404 /index/demo/
+ GET 200 /index/
+ GET 200 /demo-0.2-py2.4.egg
+ GET 404 /index/demoneeded/
+ GET 200 /demoneeded-1.1.zip
+ GET 404 /index/setuptools/
+
+ >>> zc.buildout.easy_install.build(
+ ... 'extdemo', dest,
+ ... {'include-dirs': os.path.join(sample_buildout, 'include')},
+ ... links=[link_server], index=link_server+'index/')
+ GET 404 /index/extdemo/
+ GET 200 /extdemo-1.5.zip
+ ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg']
+
+Not only will we get eggs in our destination directory:
+
+ >>> ls(dest)
+ d demo-0.2-py2.4.egg
+ d demoneeded-1.1-py2.4.egg
+ d extdemo-1.5-py2.4-linux-i686.egg
+
+But we'll get distributions in the cache directory:
+
+ >>> ls(cache)
+ - demo-0.2-py2.4.egg
+ - demoneeded-1.1.zip
+ - extdemo-1.5.zip
+
+The cache directory contains uninstalled distributions, such as zipped
+eggs or source distributions.
+
+Let's recreate our destination directory and clear the index cache:
+
+ >>> remove(dest)
+ >>> dest = tmpdir('sample-install')
+ >>> zc.buildout.easy_install.clear_index_cache()
+
+Now when we install the distributions:
+
+ >>> ws = zc.buildout.easy_install.install(
+ ... ['demo==0.2'], dest,
+ ... links=[link_server], index=link_server+'index/',
+ ... always_unzip=True)
+ GET 200 /
+ GET 404 /index/demo/
+ GET 200 /index/
+ GET 404 /index/demoneeded/
+ GET 404 /index/setuptools/
+
+ >>> zc.buildout.easy_install.build(
+ ... 'extdemo', dest,
+ ... {'include-dirs': os.path.join(sample_buildout, 'include')},
+ ... links=[link_server], index=link_server+'index/')
+ GET 404 /index/extdemo/
+ ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg']
+
+ >>> ls(dest)
+ d demo-0.2-py2.4.egg
+ d demoneeded-1.1-py2.4.egg
+ d extdemo-1.5-py2.4-linux-i686.egg
+
+Note that we didn't download the distributions from the link server.
+
+.. Disable the download cache:
+
+ >>> zc.buildout.easy_install.download_cache(None)
+ '/cache'
More information about the Checkins
mailing list